Mercurial > hg
annotate mercurial/revsetlang.py @ 39343:bab58b1d87c7
shelve: rename method for data write/read
There are no user of this code nor any code related to obsshelve in the
extensions right now, so we rename the function before using them.
Note: The shelvedfile looks a bit strange. We should probably refactor it,
however, this is an adventure for another series.
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Tue, 29 May 2018 11:40:40 +0200 |
parents | b902b177901d |
children | 4aa04d009167 |
rev | line source |
---|---|
31024
0b8356705de6
revset: split language services to revsetlang module (API)
Yuya Nishihara <yuya@tcha.org>
parents:
31017
diff
changeset
|
1 # revsetlang.py - parser, tokenizer and utility for revision set language |
11275 | 2 # |
3 # Copyright 2010 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2 or any later version. | |
7 | |
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
8 from __future__ import absolute_import |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
9 |
30071
2def3d55b1b9
revset: build _syminitletters from a saner source: the string module
Augie Fackler <augie@google.com>
parents:
30056
diff
changeset
|
10 import string |
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
11 |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
12 from .i18n import _ |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
13 from . import ( |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
14 error, |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
15 node, |
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
16 parser, |
30071
2def3d55b1b9
revset: build _syminitletters from a saner source: the string module
Augie Fackler <augie@google.com>
parents:
30056
diff
changeset
|
17 pycompat, |
31606
0b3eb280564b
revsetlang: perform quoting using ui.escapestr instead of repr()
Augie Fackler <augie@google.com>
parents:
31605
diff
changeset
|
18 util, |
25971
e9cd028f2dff
revset: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25929
diff
changeset
|
19 ) |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36691
diff
changeset
|
20 from .utils import ( |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36691
diff
changeset
|
21 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36691
diff
changeset
|
22 ) |
11275 | 23 |
24 elements = { | |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
25 # token-type: binding-strength, primary, prefix, infix, suffix |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
26 "(": (21, None, ("group", 1, ")"), ("func", 1, ")"), None), |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
27 "[": (21, None, None, ("subscript", 1, "]"), None), |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
28 "#": (21, None, None, ("relation", 21), None), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
29 "##": (20, None, None, ("_concat", 20), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
30 "~": (18, None, None, ("ancestor", 18), None), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
31 "^": (18, None, None, ("parent", 18), "parentpost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
32 "-": (5, None, ("negate", 19), ("minus", 5), None), |
35542
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
33 "::": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17), |
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
34 "dagrangepost"), |
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
35 "..": (17, "dagrangeall", ("dagrangepre", 17), ("dagrange", 17), |
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
36 "dagrangepost"), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
37 ":": (15, "rangeall", ("rangepre", 15), ("range", 15), "rangepost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
38 "not": (10, None, ("not", 10), None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
39 "!": (10, None, ("not", 10), None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
40 "and": (5, None, None, ("and", 5), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
41 "&": (5, None, None, ("and", 5), None), |
29767
e5b794063fd4
parser: remove unused binding parameter from suffix action
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
42 "%": (5, None, None, ("only", 5), "onlypost"), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
43 "or": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
44 "|": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
45 "+": (4, None, None, ("or", 4), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
46 "=": (3, None, None, ("keyvalue", 3), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
47 ",": (2, None, None, ("list", 2), None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
48 ")": (0, None, None, None, None), |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
49 "]": (0, None, None, None, None), |
25815
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
50 "symbol": (0, "symbol", None, None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
51 "string": (0, "string", None, None, None), |
e71e5629e006
parser: separate actions for primary expression and prefix operator
Yuya Nishihara <yuya@tcha.org>
parents:
25801
diff
changeset
|
52 "end": (0, None, None, None, None), |
11275 | 53 } |
54 | |
32291
bd872f64a8ba
cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents:
31997
diff
changeset
|
55 keywords = {'and', 'or', 'not'} |
11275 | 56 |
34273
b0790bebfcf8
revset: move weight information to predicate
Jun Wu <quark@fb.com>
parents:
34272
diff
changeset
|
57 symbols = {} |
b0790bebfcf8
revset: move weight information to predicate
Jun Wu <quark@fb.com>
parents:
34272
diff
changeset
|
58 |
32291
bd872f64a8ba
cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents:
31997
diff
changeset
|
59 _quoteletters = {'"', "'"} |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
60 _simpleopletters = set(pycompat.iterbytestr("()[]#:=,-|&+!~^%")) |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
61 |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
62 # default set of valid characters for the initial letter of symbols |
31383
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
63 _syminitletters = set(pycompat.iterbytestr( |
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
64 string.ascii_letters.encode('ascii') + |
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
65 string.digits.encode('ascii') + |
38783
e7aa113b14f7
global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
38625
diff
changeset
|
66 '._@')) | set(map(pycompat.bytechr, pycompat.xrange(128, 256))) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
67 |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
68 # default set of valid characters for non-initial letters of symbols |
31383
7556fe09cc48
py3: convert set of revset initial symbols back to bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31355
diff
changeset
|
69 _symletters = _syminitletters | set(pycompat.iterbytestr('-/')) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
70 |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
71 def tokenize(program, lookup=None, syminitletters=None, symletters=None): |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
72 ''' |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
73 Parse a revset statement into a stream of tokens |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
74 |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
75 ``syminitletters`` is the set of valid characters for the initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
76 letter of symbols. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
77 |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
78 By default, character ``c`` is recognized as valid for initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
79 letter of symbols, if ``c.isalnum() or c in '._@' or ord(c) > 127``. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
80 |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
81 ``symletters`` is the set of valid characters for non-initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
82 letters of symbols. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
83 |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
84 By default, character ``c`` is recognized as valid for non-initial |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
85 letters of symbols, if ``c.isalnum() or c in '-._/@' or ord(c) > 127``. |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
86 |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
87 Check that @ is a valid unquoted token character (issue3686): |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
88 >>> list(tokenize(b"@::")) |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
89 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)] |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
90 |
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
91 ''' |
37775
03d7f885d5f2
revsetlang: do not pass in non-bytes to parse()
Yuya Nishihara <yuya@tcha.org>
parents:
37760
diff
changeset
|
92 if not isinstance(program, bytes): |
03d7f885d5f2
revsetlang: do not pass in non-bytes to parse()
Yuya Nishihara <yuya@tcha.org>
parents:
37760
diff
changeset
|
93 raise error.ProgrammingError('revset statement must be bytes, got %r' |
03d7f885d5f2
revsetlang: do not pass in non-bytes to parse()
Yuya Nishihara <yuya@tcha.org>
parents:
37760
diff
changeset
|
94 % program) |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
95 program = pycompat.bytestr(program) |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
96 if syminitletters is None: |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
97 syminitletters = _syminitletters |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
98 if symletters is None: |
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
99 symletters = _symletters |
17886
d8905e2c1301
revset: accept @ in unquoted symbols (issue3686)
Matt Mackall <mpm@selenic.com>
parents:
17829
diff
changeset
|
100 |
25902
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
101 if program and lookup: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
102 # attempt to parse old-style ranges first to deal with |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
103 # things like old-tag which contain query metacharacters |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
104 parts = program.split(':', 1) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
105 if all(lookup(sym) for sym in parts if sym): |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
106 if parts[0]: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
107 yield ('symbol', parts[0], 0) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
108 if len(parts) > 1: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
109 s = len(parts[0]) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
110 yield (':', None, s) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
111 if parts[1]: |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
112 yield ('symbol', parts[1], s + 1) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
113 yield ('end', None, len(program)) |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
114 return |
5214cbdc37e5
revset: port parsing rule of old-style ranges from scmutil.revrange()
Yuya Nishihara <yuya@tcha.org>
parents:
25819
diff
changeset
|
115 |
11275 | 116 pos, l = 0, len(program) |
117 while pos < l: | |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
118 c = program[pos] |
11275 | 119 if c.isspace(): # skip inter-token whitespace |
120 pass | |
11278
7df88cdf47fd
revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents:
11275
diff
changeset
|
121 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
122 yield ('::', None, pos) |
11278
7df88cdf47fd
revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents:
11275
diff
changeset
|
123 pos += 1 # skip ahead |
11275 | 124 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
125 yield ('..', None, pos) |
11275 | 126 pos += 1 # skip ahead |
23742
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
127 elif c == '#' and program[pos:pos + 2] == '##': # look ahead carefully |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
128 yield ('##', None, pos) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
129 pos += 1 # skip ahead |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
130 elif c in _simpleopletters: # handle simple operators |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
131 yield (c, None, pos) |
31384
fac5cd3b8673
py3: make set of revset operators and quotes in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
31383
diff
changeset
|
132 elif (c in _quoteletters or c == 'r' and |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
133 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
134 if c == 'r': |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
135 pos += 1 |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
136 c = program[pos] |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
137 decode = lambda x: x |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
138 else: |
26232
43f9976346e9
revset: handle error of string unescaping
Yuya Nishihara <yuya@tcha.org>
parents:
26212
diff
changeset
|
139 decode = parser.unescapestr |
11275 | 140 pos += 1 |
141 s = pos | |
142 while pos < l: # find closing quote | |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
143 d = program[pos] |
11275 | 144 if d == '\\': # skip over escaped characters |
145 pos += 2 | |
146 continue | |
147 if d == c: | |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
148 yield ('string', decode(program[s:pos]), s) |
11275 | 149 break |
150 pos += 1 | |
151 else: | |
11383
de544774ebea
revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents:
11349
diff
changeset
|
152 raise error.ParseError(_("unterminated string"), s) |
16683 | 153 # gather up a symbol/keyword |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
154 elif c in syminitletters: |
11275 | 155 s = pos |
156 pos += 1 | |
157 while pos < l: # find end of symbol | |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
158 d = program[pos] |
23842
91dbb98b3513
revset: make tokenize extensible to parse alias declarations and definitions
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23836
diff
changeset
|
159 if d not in symletters: |
11275 | 160 break |
31441
80c8a6db450d
py3: use bytestr wrapper in revsetlang.tokenize()
Yuya Nishihara <yuya@tcha.org>
parents:
31440
diff
changeset
|
161 if d == '.' and program[pos - 1] == '.': # special case for .. |
11275 | 162 pos -= 1 |
163 break | |
164 pos += 1 | |
165 sym = program[s:pos] | |
166 if sym in keywords: # operator keywords | |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
167 yield (sym, None, s) |
20780
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
168 elif '-' in sym: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
169 # some jerk gave us foo-bar-baz, try to check if it's a symbol |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
170 if lookup and lookup(sym): |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
171 # looks like a real symbol |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
172 yield ('symbol', sym, s) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
173 else: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
174 # looks like an expression |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
175 parts = sym.split('-') |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
176 for p in parts[:-1]: |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
177 if p: # possible consecutive - |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
178 yield ('symbol', p, s) |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
179 s += len(p) |
39324
b902b177901d
revsetlang: fix position of '-' in spaceless 'a-b' expressions
Martin von Zweigbergk <martinvonz@google.com>
parents:
38783
diff
changeset
|
180 yield ('-', None, s) |
20780
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
181 s += 1 |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
182 if parts[-1]: # possible trailing - |
403f1f73d30f
revset: try to handle hyphenated symbols if lookup callback is available
Matt Mackall <mpm@selenic.com>
parents:
20779
diff
changeset
|
183 yield ('symbol', parts[-1], s) |
11275 | 184 else: |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
185 yield ('symbol', sym, s) |
11275 | 186 pos -= 1 |
187 else: | |
24708
fb47816e1a9c
revsets: more informative syntax error message
Ryan McElroy <rmcelroy@fb.com>
parents:
24518
diff
changeset
|
188 raise error.ParseError(_("syntax error in revset '%s'") % |
fb47816e1a9c
revsets: more informative syntax error message
Ryan McElroy <rmcelroy@fb.com>
parents:
24518
diff
changeset
|
189 program, pos) |
11275 | 190 pos += 1 |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
191 yield ('end', None, pos) |
11275 | 192 |
193 # helpers | |
194 | |
30802
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
195 _notset = object() |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
196 |
29441
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
197 def getsymbol(x): |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
198 if x and x[0] == 'symbol': |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
199 return x[1] |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
200 raise error.ParseError(_('not a symbol')) |
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
201 |
11275 | 202 def getstring(x, err): |
11406
42408cd43f55
revset: fix up contains/getstring when no args passed
Matt Mackall <mpm@selenic.com>
parents:
11404
diff
changeset
|
203 if x and (x[0] == 'string' or x[0] == 'symbol'): |
11275 | 204 return x[1] |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
205 raise error.ParseError(err) |
11275 | 206 |
30802
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
207 def getinteger(x, err, default=_notset): |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
208 if not x and default is not _notset: |
5eb3e4568c94
revset: add default value to getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30801
diff
changeset
|
209 return default |
30801
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
210 try: |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
211 return int(getstring(x, err)) |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
212 except ValueError: |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
213 raise error.ParseError(err) |
67ee7874e53b
revset: factor out getinteger() helper
Yuya Nishihara <yuya@tcha.org>
parents:
30800
diff
changeset
|
214 |
31997
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
215 def getboolean(x, err): |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36691
diff
changeset
|
216 value = stringutil.parsebool(getsymbol(x)) |
31997
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
217 if value is not None: |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
218 return value |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
219 raise error.ParseError(err) |
11f501f0a213
revsetlang: add a getboolean helper function
Denis Laxalde <denis@laxalde.org>
parents:
31800
diff
changeset
|
220 |
11275 | 221 def getlist(x): |
222 if not x: | |
223 return [] | |
224 if x[0] == 'list': | |
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
225 return list(x[1:]) |
11275 | 226 return [x] |
227 | |
30804
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
228 def getrange(x, err): |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
229 if not x: |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
230 raise error.ParseError(err) |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
231 op = x[0] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
232 if op == 'range': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
233 return x[1], x[2] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
234 elif op == 'rangepre': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
235 return None, x[1] |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
236 elif op == 'rangepost': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
237 return x[1], None |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
238 elif op == 'rangeall': |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
239 return None, None |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
240 raise error.ParseError(err) |
4227f80f72b2
revset: abuse x:y syntax to specify line range of followlines()
Yuya Nishihara <yuya@tcha.org>
parents:
30803
diff
changeset
|
241 |
11339
744d5b73f776
revset: improve filter argument handling
Matt Mackall <mpm@selenic.com>
parents:
11304
diff
changeset
|
242 def getargs(x, min, max, err): |
11275 | 243 l = getlist(x) |
16161
5a627b49b4d9
graphlog: paths/-I/-X handling requires a new revset
Patrick Mezard <patrick@mezard.eu>
parents:
16096
diff
changeset
|
244 if len(l) < min or (max >= 0 and len(l) > max): |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
245 raise error.ParseError(err) |
11275 | 246 return l |
247 | |
25767
026105c442d7
revset: rename getkwargs() to getargsdict()
Yuya Nishihara <yuya@tcha.org>
parents:
25766
diff
changeset
|
248 def getargsdict(x, funcname, keys): |
30753
c3a3896a9fa8
parser: extend buildargsdict() to support variable-length positional args
Yuya Nishihara <yuya@tcha.org>
parents:
30719
diff
changeset
|
249 return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys), |
25705
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25704
diff
changeset
|
250 keyvaluenode='keyvalue', keynode='symbol') |
48919d246a47
revset: add function to build dict of positional and keyword arguments
Yuya Nishihara <yuya@tcha.org>
parents:
25704
diff
changeset
|
251 |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
252 # cache of {spec: raw parsed tree} built internally |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
253 _treecache = {} |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
254 |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
255 def _cachedtree(spec): |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
256 # thread safe because parse() is reentrant and dict.__setitem__() is atomic |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
257 tree = _treecache.get(spec) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
258 if tree is None: |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
259 _treecache[spec] = tree = parse(spec) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
260 return tree |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
261 |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
262 def _build(tmplspec, *repls): |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
263 """Create raw parsed tree from a template revset statement |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
264 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
265 >>> _build(b'f(_) and _', (b'string', b'1'), (b'symbol', b'2')) |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
266 ('and', ('func', ('symbol', 'f'), ('string', '1')), ('symbol', '2')) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
267 """ |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
268 template = _cachedtree(tmplspec) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
269 return parser.buildtree(template, ('symbol', '_'), *repls) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
270 |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
271 def _match(patspec, tree): |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
272 """Test if a tree matches the given pattern statement; return the matches |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
273 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
274 >>> _match(b'f(_)', parse(b'f()')) |
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
275 >>> _match(b'f(_)', parse(b'f(1)')) |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
276 [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')] |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
277 >>> _match(b'f(_)', parse(b'f(1, 2)')) |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
278 """ |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
279 pattern = _cachedtree(patspec) |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
280 return parser.matchtree(pattern, tree, ('symbol', '_'), |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
281 {'keyvalue', 'list'}) |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
282 |
29117
7828cadd2873
revset: construct arguments of only() against matched tree
Yuya Nishihara <yuya@tcha.org>
parents:
29116
diff
changeset
|
283 def _matchonly(revs, bases): |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
284 return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases)) |
29116
0c9b05dae010
revset: unnest isonly() closure from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29098
diff
changeset
|
285 |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
286 def _fixops(x): |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
287 """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
288 handled well by our simple top-down parser""" |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
289 if not isinstance(x, tuple): |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
290 return x |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
291 |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
292 op = x[0] |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
293 if op == 'parent': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
294 # x^:y means (x^) : y, not x ^ (:y) |
29770
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
295 # x^: means (x^) :, not x ^ (:) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
296 post = ('parentpost', x[1]) |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
297 if x[2][0] == 'dagrangepre': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
298 return _fixops(('dagrange', post, x[2][1])) |
35542
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
299 elif x[2][0] == 'dagrangeall': |
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
300 return _fixops(('dagrangepost', post)) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
301 elif x[2][0] == 'rangepre': |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
302 return _fixops(('range', post, x[2][1])) |
29770
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
303 elif x[2][0] == 'rangeall': |
9c51a5de76db
revset: also parse x^: as (x^):
Yuya Nishihara <yuya@tcha.org>
parents:
29769
diff
changeset
|
304 return _fixops(('rangepost', post)) |
29929
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
305 elif op == 'or': |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
306 # make number of arguments deterministic: |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
307 # x + y + z -> (or x y z) -> (or (list x y z)) |
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
308 return (op, _fixops(('list',) + x[1:])) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
309 elif op == 'subscript' and x[1][0] == 'relation': |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
310 # x#y[z] ternary |
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
311 return _fixops(('relsubscript', x[1][1], x[1][2], x[2])) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
312 |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
313 return (op,) + tuple(_fixops(y) for y in x[1:]) |
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
314 |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
315 def _analyze(x): |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
316 if x is None: |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
317 return x |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
318 |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
319 op = x[0] |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
320 if op == 'minus': |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
321 return _analyze(_build('_ and not _', *x[1:])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
322 elif op == 'only': |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
323 return _analyze(_build('only(_, _)', *x[1:])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
324 elif op == 'onlypost': |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
325 return _analyze(_build('only(_)', x[1])) |
35542
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
326 elif op == 'dagrangeall': |
beb667c9880f
revset: parse x^:: as (x^):: (issue5764)
Yuya Nishihara <yuya@tcha.org>
parents:
35494
diff
changeset
|
327 raise error.ParseError(_("can't use '::' in this context")) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
328 elif op == 'dagrangepre': |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
329 return _analyze(_build('ancestors(_)', x[1])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
330 elif op == 'dagrangepost': |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
331 return _analyze(_build('descendants(_)', x[1])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
332 elif op == 'negate': |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
333 s = getstring(x[1], _("can't negate that")) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
334 return _analyze(('string', '-' + s)) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
335 elif op in ('string', 'symbol'): |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
336 return x |
30803
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
337 elif op == 'rangeall': |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
338 return (op, None) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
339 elif op in {'or', 'not', 'rangepre', 'rangepost', 'parentpost'}: |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
340 return (op, _analyze(x[1])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
341 elif op == 'group': |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
342 return _analyze(x[1]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
343 elif op in {'and', 'dagrange', 'range', 'parent', 'ancestor', 'relation', |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
344 'subscript'}: |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
345 ta = _analyze(x[1]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
346 tb = _analyze(x[2]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
347 return (op, ta, tb) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
348 elif op == 'relsubscript': |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
349 ta = _analyze(x[1]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
350 tb = _analyze(x[2]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
351 tc = _analyze(x[3]) |
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
352 return (op, ta, tb, tc) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
353 elif op == 'list': |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
354 return (op,) + tuple(_analyze(y) for y in x[1:]) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
355 elif op == 'keyvalue': |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
356 return (op, x[1], _analyze(x[2])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
357 elif op == 'func': |
37760
29eb4cafeeb8
revset: skip legacy lookup for revspec wrapped in 'revset(...)'
Boris Feld <boris.feld@octobus.net>
parents:
37084
diff
changeset
|
358 f = getsymbol(x[1]) |
29eb4cafeeb8
revset: skip legacy lookup for revspec wrapped in 'revset(...)'
Boris Feld <boris.feld@octobus.net>
parents:
37084
diff
changeset
|
359 if f == 'revset': |
29eb4cafeeb8
revset: skip legacy lookup for revspec wrapped in 'revset(...)'
Boris Feld <boris.feld@octobus.net>
parents:
37084
diff
changeset
|
360 return _analyze(x[2]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
361 return (op, x[1], _analyze(x[2])) |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
362 raise ValueError('invalid operator %r' % op) |
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
363 |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
364 def analyze(x): |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
365 """Transform raw parsed tree to evaluatable tree which can be fed to |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
366 optimize() or getset() |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
367 |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
368 All pseudo operations should be mapped to real operations or functions |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
369 defined in methods or symbols table respectively. |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
370 """ |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
371 return _analyze(x) |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
372 |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
373 def _optimize(x): |
13031
3da456d0c885
code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents:
12936
diff
changeset
|
374 if x is None: |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
375 return 0, x |
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
376 |
11275 | 377 op = x[0] |
29904
e4b4168a4f1c
revset: extract tree transformation from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29898
diff
changeset
|
378 if op in ('string', 'symbol'): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
379 return 0.5, x # single revisions are small |
16859
eeb464ed7275
revset: drop unreachable code
Bryan O'Sullivan <bryano@fb.com>
parents:
16838
diff
changeset
|
380 elif op == 'and': |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
381 wa, ta = _optimize(x[1]) |
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
382 wb, tb = _optimize(x[2]) |
29116
0c9b05dae010
revset: unnest isonly() closure from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29098
diff
changeset
|
383 w = min(wa, wb) |
20499
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
384 |
34065
c6c8a52e28c9
revset: optimize "draft() & ::x" pattern
Jun Wu <quark@fb.com>
parents:
34047
diff
changeset
|
385 # (draft/secret/_notpublic() & ::x) have a fast path |
c6c8a52e28c9
revset: optimize "draft() & ::x" pattern
Jun Wu <quark@fb.com>
parents:
34047
diff
changeset
|
386 m = _match('_() & ancestors(_)', ('and', ta, tb)) |
c6c8a52e28c9
revset: optimize "draft() & ::x" pattern
Jun Wu <quark@fb.com>
parents:
34047
diff
changeset
|
387 if m and getsymbol(m[1]) in {'draft', 'secret', '_notpublic'}: |
c6c8a52e28c9
revset: optimize "draft() & ::x" pattern
Jun Wu <quark@fb.com>
parents:
34047
diff
changeset
|
388 return w, _build('_phaseandancestors(_, _)', m[1], m[2]) |
c6c8a52e28c9
revset: optimize "draft() & ::x" pattern
Jun Wu <quark@fb.com>
parents:
34047
diff
changeset
|
389 |
20499
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
390 # (::x and not ::y)/(not ::y and ::x) have a fast path |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
391 m = _matchonly(ta, tb) or _matchonly(tb, ta) |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
392 if m: |
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
393 return w, _build('only(_, _)', *m[1:]) |
20499
2efd608473fb
revset: optimize missing ancestor expressions
Siddharth Agarwal <sid0@fb.com>
parents:
20498
diff
changeset
|
394 |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
395 m = _match('not _', tb) |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
396 if m: |
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
397 return wa, ('difference', ta, m[1]) |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
398 if wa > wb: |
34020
37b82485097f
revset: do not flip "and" arguments when optimizing
Jun Wu <quark@fb.com>
parents:
34016
diff
changeset
|
399 op = 'andsmally' |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
400 return w, (op, ta, tb) |
11279
62ccf4cd6e7f
revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents:
11278
diff
changeset
|
401 elif op == 'or': |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
402 # fast path for machine-generated expression, that is likely to have |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
403 # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()' |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
404 ws, ts, ss = [], [], [] |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
405 def flushss(): |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
406 if not ss: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
407 return |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
408 if len(ss) == 1: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
409 w, t = ss[0] |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
410 else: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
411 s = '\0'.join(t[1] for w, t in ss) |
34044
b862e6fca7ac
revsetlang: build optimized tree by helper function
Yuya Nishihara <yuya@tcha.org>
parents:
34020
diff
changeset
|
412 y = _build('_list(_)', ('string', s)) |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
413 w, t = _optimize(y) |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
414 ws.append(w) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
415 ts.append(t) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
416 del ss[:] |
29929
b3845cab4ddc
revset: wrap arguments of 'or' by 'list' node
Yuya Nishihara <yuya@tcha.org>
parents:
29922
diff
changeset
|
417 for y in getlist(x[1]): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
418 w, t = _optimize(y) |
25996
b12e00a05d57
revset: prevent crash caused by empty group expression while optimizing "or"
Yuya Nishihara <yuya@tcha.org>
parents:
25995
diff
changeset
|
419 if t is not None and (t[0] == 'string' or t[0] == 'symbol'): |
25343
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
420 ss.append((w, t)) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
421 continue |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
422 flushss() |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
423 ws.append(w) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
424 ts.append(t) |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
425 flushss() |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
426 if len(ts) == 1: |
7fbef7932af9
revset: optimize 'or' operation of trivial revisions to a list
Yuya Nishihara <yuya@tcha.org>
parents:
25342
diff
changeset
|
427 return ws[0], ts[0] # 'or' operation is fully optimized out |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
428 return max(ws), (op, ('list',) + tuple(ts)) |
11275 | 429 elif op == 'not': |
25191
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
430 # Optimize not public() to _notpublic() because we have a fast version |
34046
f23cbca9b277
revsetlang: match tree by helper function on optimize
Yuya Nishihara <yuya@tcha.org>
parents:
34044
diff
changeset
|
431 if _match('public()', x[1]): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
432 o = _optimize(_build('_notpublic()')) |
25191
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
433 return o[0], o[1] |
08d1ef09ed37
revset: optimize not public revset
Laurent Charignon <lcharignon@fb.com>
parents:
25149
diff
changeset
|
434 else: |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
435 o = _optimize(x[1]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
436 return o[0], (op, o[1]) |
30803
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
437 elif op == 'rangeall': |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
438 return 1, x |
30803
d389f19f14aa
revset: do not transform range* operators in parsed tree
Yuya Nishihara <yuya@tcha.org>
parents:
30802
diff
changeset
|
439 elif op in ('rangepre', 'rangepost', 'parentpost'): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
440 o = _optimize(x[1]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
441 return o[0], (op, o[1]) |
33415
371f59c6a89e
revset: do not compute weight for integer literal argument
Yuya Nishihara <yuya@tcha.org>
parents:
33336
diff
changeset
|
442 elif op in ('dagrange', 'range'): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
443 wa, ta = _optimize(x[1]) |
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
444 wb, tb = _optimize(x[2]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
445 return wa + wb, (op, ta, tb) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
446 elif op in ('parent', 'ancestor', 'relation', 'subscript'): |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
447 w, t = _optimize(x[1]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
448 return w, (op, t, x[2]) |
33416
9467d5337292
revset: add experimental relation and subscript operators
Yuya Nishihara <yuya@tcha.org>
parents:
33415
diff
changeset
|
449 elif op == 'relsubscript': |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
450 w, t = _optimize(x[1]) |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
451 return w, (op, t, x[2], x[3]) |
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
452 elif op == 'list': |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
453 ws, ts = zip(*(_optimize(y) for y in x[1:])) |
27987
b19d8d5d6b51
revset: flatten chained 'list' operations (aka function args) (issue5072)
Yuya Nishihara <yuya@tcha.org>
parents:
27945
diff
changeset
|
454 return sum(ws), (op,) + ts |
29766
5004ef47f437
revset: fix keyword arguments to go through optimization process
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
455 elif op == 'keyvalue': |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
456 w, t = _optimize(x[2]) |
29766
5004ef47f437
revset: fix keyword arguments to go through optimization process
Yuya Nishihara <yuya@tcha.org>
parents:
29646
diff
changeset
|
457 return w, (op, x[1], t) |
11275 | 458 elif op == 'func': |
29441
9e8d258708bb
revset: check invalid function syntax "func-name"() explicitly
Yuya Nishihara <yuya@tcha.org>
parents:
29425
diff
changeset
|
459 f = getsymbol(x[1]) |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
460 wa, ta = _optimize(x[2]) |
34273
b0790bebfcf8
revset: move weight information to predicate
Jun Wu <quark@fb.com>
parents:
34272
diff
changeset
|
461 w = getattr(symbols.get(f), '_weight', 1) |
38625
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
462 m = _match('commonancestors(_)', ta) |
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
463 |
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
464 # Optimize heads(commonancestors(_)) because we have a fast version |
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
465 if f == 'heads' and m: |
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
466 return w + wa, _build('_commonancestorheads(_)', m[1]) |
52f19a840543
revset: add optimization for heads(commonancestors())
Sean Farley <sean@farley.io>
parents:
37775
diff
changeset
|
467 |
34011
1b28525e6698
revset: remove order information from tree (API)
Jun Wu <quark@fb.com>
parents:
34010
diff
changeset
|
468 return w + wa, (op, x[1], ta) |
29896
104914b03b83
revset: make optimize() reject unknown operators
Yuya Nishihara <yuya@tcha.org>
parents:
29814
diff
changeset
|
469 raise ValueError('invalid operator %r' % op) |
11275 | 470 |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
471 def optimize(tree): |
29905
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
472 """Optimize evaluatable tree |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
473 |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
474 All pseudo operations should be transformed beforehand. |
371c2a39eead
revset: make analyze() a separate step from optimize()
Yuya Nishihara <yuya@tcha.org>
parents:
29904
diff
changeset
|
475 """ |
34272
53fb09c73ba8
revset: remove "small" argument from "_optimize"
Jun Wu <quark@fb.com>
parents:
34131
diff
changeset
|
476 _weight, newtree = _optimize(tree) |
29119
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
477 return newtree |
a032ebea4e97
revset: factor out public optimize() function from recursion
Yuya Nishihara <yuya@tcha.org>
parents:
29118
diff
changeset
|
478 |
23845
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
479 # the set of valid characters for the initial letter of symbols in |
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
480 # alias declarations and definitions |
34069
e18119b1ad5d
py3: fix mixed bytes/unicode in revsetlang._aliassyminitletters
Yuya Nishihara <yuya@tcha.org>
parents:
34065
diff
changeset
|
481 _aliassyminitletters = _syminitletters | {'$'} |
23845
0a7fd54d4e60
revset: introduce "_parsealiasdecl" to parse alias declarations strictly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23844
diff
changeset
|
482 |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
483 def _parsewith(spec, lookup=None, syminitletters=None): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
484 """Generate a parse tree of given spec with given tokenizing options |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
485 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
486 >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters) |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
487 ('func', ('symbol', 'foo'), ('symbol', '$1')) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
488 >>> _parsewith(b'$1') |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
489 Traceback (most recent call last): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
490 ... |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
491 ParseError: ("syntax error in revset '$1'", 0) |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
492 >>> _parsewith(b'foo bar') |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
493 Traceback (most recent call last): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
494 ... |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
495 ParseError: ('invalid token', 4) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
496 """ |
37760
29eb4cafeeb8
revset: skip legacy lookup for revspec wrapped in 'revset(...)'
Boris Feld <boris.feld@octobus.net>
parents:
37084
diff
changeset
|
497 if lookup and spec.startswith('revset(') and spec.endswith(')'): |
29eb4cafeeb8
revset: skip legacy lookup for revspec wrapped in 'revset(...)'
Boris Feld <boris.feld@octobus.net>
parents:
37084
diff
changeset
|
498 lookup = None |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
499 p = parser.parser(elements) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
500 tree, pos = p.parse(tokenize(spec, lookup=lookup, |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
501 syminitletters=syminitletters)) |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
502 if pos != len(spec): |
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
503 raise error.ParseError(_('invalid token'), pos) |
29769
abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
Yuya Nishihara <yuya@tcha.org>
parents:
29767
diff
changeset
|
504 return _fixops(parser.simplifyinfixops(tree, ('list', 'or'))) |
29073
81bac118f9e2
revset: factor out common parsing function
Yuya Nishihara <yuya@tcha.org>
parents:
29072
diff
changeset
|
505 |
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
506 class _aliasrules(parser.basealiasrules): |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
507 """Parsing and expansion rule set of revset aliases""" |
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
508 _section = _('revset alias') |
29074
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
509 |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
510 @staticmethod |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
511 def _parse(spec): |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
512 """Parse alias declaration/definition ``spec`` |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
513 |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
514 This allows symbol names to use also ``$`` as an initial letter |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
515 (for backward compatibility), and callers of this function should |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
516 examine whether ``$`` is used also for unexpected symbols or not. |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
517 """ |
e7c679738503
revset: define _parsealias() in _aliasrules class
Yuya Nishihara <yuya@tcha.org>
parents:
29073
diff
changeset
|
518 return _parsewith(spec, syminitletters=_aliassyminitletters) |
28910
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
519 |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
520 @staticmethod |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
521 def _trygetfunc(tree): |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
522 if tree[0] == 'func' and tree[1][0] == 'symbol': |
1203159c8928
parser: factor out _trygetfunc() that extracts function name and arguments
Yuya Nishihara <yuya@tcha.org>
parents:
28898
diff
changeset
|
523 return tree[1][1], getlist(tree[2]) |
28870
475dad3432fd
parser: add stub class that will host alias parsing and expansion
Yuya Nishihara <yuya@tcha.org>
parents:
28869
diff
changeset
|
524 |
33336
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
525 def expandaliases(tree, aliases, warn=None): |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
526 """Expand aliases in a tree, aliases is a list of (name, value) tuples""" |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
527 aliases = _aliasrules.buildmap(aliases) |
28895
4bf9ed7a260e
parser: move functions that process alias expansion to rule-set class
Yuya Nishihara <yuya@tcha.org>
parents:
28894
diff
changeset
|
528 tree = _aliasrules.expand(aliases, tree) |
29922
ae933e3e2226
revset: remove showwarning option from expandaliases()
Yuya Nishihara <yuya@tcha.org>
parents:
29906
diff
changeset
|
529 # warn about problematic (but not referred) aliases |
33336
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
530 if warn is not None: |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
531 for name, alias in sorted(aliases.iteritems()): |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
532 if alias.error and not alias.warned: |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
533 warn(_('warning: %s\n') % (alias.error)) |
4672db164c98
revset: make repo.anyrevs accept customized alias override (API)
Jun Wu <quark@fb.com>
parents:
32913
diff
changeset
|
534 alias.warned = True |
23725
6a81f88758aa
revset: delay showing parse error for the revset alias until it is referred
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23720
diff
changeset
|
535 return tree |
14098
9f5a0acb0056
revset aliases
Alexander Solovyov <alexander@solovyov.net>
parents:
14073
diff
changeset
|
536 |
23742
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
537 def foldconcat(tree): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
538 """Fold elements to be concatenated by `##` |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
539 """ |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
540 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
541 return tree |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
542 if tree[0] == '_concat': |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
543 pending = [tree] |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
544 l = [] |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
545 while pending: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
546 e = pending.pop() |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
547 if e[0] == '_concat': |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
548 pending.extend(reversed(e[1:])) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
549 elif e[0] in ('string', 'symbol'): |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
550 l.append(e[1]) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
551 else: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
552 msg = _("\"##\" can't concatenate \"%s\" element") % (e[0]) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
553 raise error.ParseError(msg) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
554 return ('string', ''.join(l)) |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
555 else: |
3a4d8a6ce432
revset: introduce new operator "##" to concatenate strings/symbols at runtime
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
23729
diff
changeset
|
556 return tuple(foldconcat(t) for t in tree) |
14098
9f5a0acb0056
revset aliases
Alexander Solovyov <alexander@solovyov.net>
parents:
14073
diff
changeset
|
557 |
20779
ffc2295c6b80
revset: pass a lookup function to the tokenizer
Matt Mackall <mpm@selenic.com>
parents:
20754
diff
changeset
|
558 def parse(spec, lookup=None): |
36685
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
559 try: |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
560 return _parsewith(spec, lookup=lookup) |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
561 except error.ParseError as inst: |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
562 if len(inst.args) > 1: # has location |
36691
1b179d151578
templater: fix position of terminator character in error message
Yuya Nishihara <yuya@tcha.org>
parents:
36685
diff
changeset
|
563 loc = inst.args[1] |
36685
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
564 # Remove newlines -- spaces are equivalent whitespace. |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
565 spec = spec.replace('\n', ' ') |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
566 # We want the caret to point to the place in the template that |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
567 # failed to parse, but in a hint we get a open paren at the |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
568 # start. Therefore, we print "loc + 1" spaces (instead of "loc") |
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
569 # to line up the caret with the location of the error. |
36691
1b179d151578
templater: fix position of terminator character in error message
Yuya Nishihara <yuya@tcha.org>
parents:
36685
diff
changeset
|
570 inst.hint = spec + '\n' + ' ' * (loc + 1) + '^ ' + _('here') |
36685
2a258985ffeb
revsetlang: add a hint for more useful parse errors
Ryan McElroy <rmcelroy@fb.com>
parents:
35882
diff
changeset
|
571 raise |
20779
ffc2295c6b80
revset: pass a lookup function to the tokenizer
Matt Mackall <mpm@selenic.com>
parents:
20754
diff
changeset
|
572 |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
573 def _quote(s): |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
574 r"""Quote a value in order to make it safe for the revset engine. |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
575 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
576 >>> _quote(b'asdf') |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
577 "'asdf'" |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
578 >>> _quote(b"asdf'\"") |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
579 '\'asdf\\\'"\'' |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
580 >>> _quote(b'asdf\'') |
31606
0b3eb280564b
revsetlang: perform quoting using ui.escapestr instead of repr()
Augie Fackler <augie@google.com>
parents:
31605
diff
changeset
|
581 "'asdf\\''" |
31605
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
582 >>> _quote(1) |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
583 "'1'" |
0b94c19b641c
revsetlang: add docstring with some tests to _quote
Augie Fackler <augie@google.com>
parents:
31604
diff
changeset
|
584 """ |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36691
diff
changeset
|
585 return "'%s'" % stringutil.escapestr(pycompat.bytestr(s)) |
31604
7eac6fcf2ffa
revsetlang: move quoting function to not be a closure
Augie Fackler <augie@google.com>
parents:
31603
diff
changeset
|
586 |
35596
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
587 def _formatargtype(c, arg): |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
588 if c == 'd': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
589 return '%d' % int(arg) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
590 elif c == 's': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
591 return _quote(arg) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
592 elif c == 'r': |
37775
03d7f885d5f2
revsetlang: do not pass in non-bytes to parse()
Yuya Nishihara <yuya@tcha.org>
parents:
37760
diff
changeset
|
593 if not isinstance(arg, bytes): |
03d7f885d5f2
revsetlang: do not pass in non-bytes to parse()
Yuya Nishihara <yuya@tcha.org>
parents:
37760
diff
changeset
|
594 raise TypeError |
35596
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
595 parse(arg) # make sure syntax errors are confined |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
596 return '(%s)' % arg |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
597 elif c == 'n': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
598 return _quote(node.hex(arg)) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
599 elif c == 'b': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
600 try: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
601 return _quote(arg.branch()) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
602 except AttributeError: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
603 raise TypeError |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
604 raise error.ParseError(_('unexpected revspec format character %s') % c) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
605 |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
606 def _formatlistexp(s, t): |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
607 l = len(s) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
608 if l == 0: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
609 return "_list('')" |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
610 elif l == 1: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
611 return _formatargtype(t, s[0]) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
612 elif t == 'd': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
613 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
614 elif t == 's': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
615 return "_list(%s)" % _quote("\0".join(s)) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
616 elif t == 'n': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
617 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
618 elif t == 'b': |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
619 try: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
620 return "_list('%s')" % "\0".join(a.branch() for a in s) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
621 except AttributeError: |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
622 raise TypeError |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
623 |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
624 m = l // 2 |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
625 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t)) |
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
626 |
35597
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
627 def _formatparamexp(args, t): |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
628 return ', '.join(_formatargtype(t, a) for a in args) |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
629 |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
630 _formatlistfuncs = { |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
631 'l': _formatlistexp, |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
632 'p': _formatparamexp, |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
633 } |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
634 |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
635 def formatspec(expr, *args): |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
636 ''' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
637 This is a convenience function for using revsets internally, and |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
638 escapes arguments appropriately. Aliases are intentionally ignored |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
639 so that intended expression behavior isn't accidentally subverted. |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
640 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
641 Supported arguments: |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
642 |
15266
8bea39ca9acb
revset: add %r for embedded revset support to formatspec
Matt Mackall <mpm@selenic.com>
parents:
15153
diff
changeset
|
643 %r = revset expression, parenthesized |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
644 %d = int(arg), no quoting |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
645 %s = string(arg), escaped and single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
646 %b = arg.branch(), escaped and single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
647 %n = hex(arg), single-quoted |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
648 %% = a literal '%' |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
649 |
35597
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
650 Prefixing the type with 'l' specifies a parenthesized list of that type, |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
651 and 'p' specifies a list of function parameters of that type. |
15140
353a1ba928f6
revset: add 'l' flag to formatspec for args
Matt Mackall <mpm@selenic.com>
parents:
15138
diff
changeset
|
652 |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
653 >>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()")) |
15268
bd5103819c2e
revset: fix %r handling in formatspec
Matt Mackall <mpm@selenic.com>
parents:
15266
diff
changeset
|
654 '(10 or 11):: and ((this()) or (that()))' |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
655 >>> formatspec(b'%d:: and not %d::', 10, 20) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
656 '10:: and not 20::' |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
657 >>> formatspec(b'%ld or %ld', [], [1]) |
15898
6902e13ddd03
revset: optimize building large lists in formatrevspec
Matt Mackall <mpm@selenic.com>
parents:
15837
diff
changeset
|
658 "_list('') or 1" |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
659 >>> formatspec(b'keyword(%s)', b'foo\\xe9') |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
660 "keyword('foo\\\\xe9')" |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
661 >>> b = lambda: b'default' |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
662 >>> b.branch = b |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
663 >>> formatspec(b'branch(%b)', b) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
664 "branch('default')" |
34131
0fa781320203
doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents:
34069
diff
changeset
|
665 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) |
35595
91201737d07a
revsetlang: fix quoting of %ls string
Yuya Nishihara <yuya@tcha.org>
parents:
35594
diff
changeset
|
666 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))" |
35597
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
667 >>> formatspec(b'sort(%r, %ps)', b':', [b'desc', b'user']) |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
668 "sort((:), 'desc', 'user')" |
35822
4269971b0d26
revsetlang: fix a doctest example on Python 3
Augie Fackler <augie@google.com>
parents:
35597
diff
changeset
|
669 >>> formatspec(b'%ls', [b'a', b"'"]) |
35595
91201737d07a
revsetlang: fix quoting of %ls string
Yuya Nishihara <yuya@tcha.org>
parents:
35594
diff
changeset
|
670 "_list('a\\\\x00\\\\'')" |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
671 ''' |
31440
f784ba187089
py3: use bytestr wrapper in revsetlang.formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
31385
diff
changeset
|
672 expr = pycompat.bytestr(expr) |
35560
3a8810c1b9bc
revsetlang: use iterator to track current argument in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35559
diff
changeset
|
673 argiter = iter(args) |
35557
2df8d12f23bc
revsetlang: avoid string concatenation in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35542
diff
changeset
|
674 ret = [] |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
675 pos = 0 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
676 while pos < len(expr): |
35558
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
677 q = expr.find('%', pos) |
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
678 if q < 0: |
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
679 ret.append(expr[pos:]) |
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
680 break |
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
681 ret.append(expr[pos:q]) |
dfc628611144
revsetlang: use str.find() to scan expr in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35557
diff
changeset
|
682 pos = q + 1 |
35593
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
683 try: |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
684 d = expr[pos] |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
685 except IndexError: |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
686 raise error.ParseError(_('incomplete revspec format character')) |
35559
a480551bd1b4
revsetlang: unnest "if True" in formatrevspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35558
diff
changeset
|
687 if d == '%': |
a480551bd1b4
revsetlang: unnest "if True" in formatrevspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35558
diff
changeset
|
688 ret.append(d) |
35592
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
689 pos += 1 |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
690 continue |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
691 |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
692 try: |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
693 arg = next(argiter) |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
694 except StopIteration: |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
695 raise error.ParseError(_('missing argument for revspec')) |
35597
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
696 f = _formatlistfuncs.get(d) |
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
697 if f: |
35559
a480551bd1b4
revsetlang: unnest "if True" in formatrevspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35558
diff
changeset
|
698 # a list of some type |
a480551bd1b4
revsetlang: unnest "if True" in formatrevspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35558
diff
changeset
|
699 pos += 1 |
35593
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
700 try: |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
701 d = expr[pos] |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
702 except IndexError: |
850cd045b1df
revsetlang: check incomplete revspec format character
Yuya Nishihara <yuya@tcha.org>
parents:
35592
diff
changeset
|
703 raise error.ParseError(_('incomplete revspec format character')) |
35594
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
704 try: |
35597
ed0902e8053e
revsetlang: add %p specifier to format list of function arguments
Yuya Nishihara <yuya@tcha.org>
parents:
35596
diff
changeset
|
705 ret.append(f(list(arg), d)) |
35594
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
706 except (TypeError, ValueError): |
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
707 raise error.ParseError(_('invalid argument for revspec')) |
35559
a480551bd1b4
revsetlang: unnest "if True" in formatrevspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35558
diff
changeset
|
708 else: |
35594
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
709 try: |
35596
a57acea31b3b
revsetlang: unnest inner functions from formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35595
diff
changeset
|
710 ret.append(_formatargtype(d, arg)) |
35594
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
711 except (TypeError, ValueError): |
468d7a1f6633
revsetlang: catch invalid value passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35593
diff
changeset
|
712 raise error.ParseError(_('invalid argument for revspec')) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
713 pos += 1 |
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
714 |
35592
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
715 try: |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
716 next(argiter) |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
717 raise error.ParseError(_('too many revspec arguments specified')) |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
718 except StopIteration: |
0fd617afebc0
revsetlang: check number of arguments passed to formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35591
diff
changeset
|
719 pass |
35557
2df8d12f23bc
revsetlang: avoid string concatenation in formatspec()
Yuya Nishihara <yuya@tcha.org>
parents:
35542
diff
changeset
|
720 return ''.join(ret) |
14901
a773119f30ba
revset: add formatspec convenience query builder
Matt Mackall <mpm@selenic.com>
parents:
14900
diff
changeset
|
721 |
16218
81a1a00f5738
debugrevspec: pretty print output
Patrick Mezard <patrick@mezard.eu>
parents:
16185
diff
changeset
|
722 def prettyformat(tree): |
25253
3f1a9b44b8c2
parser: move prettyformat() function from revset module
Yuya Nishihara <yuya@tcha.org>
parents:
25251
diff
changeset
|
723 return parser.prettyformat(tree, ('string', 'symbol')) |
16218
81a1a00f5738
debugrevspec: pretty print output
Patrick Mezard <patrick@mezard.eu>
parents:
16185
diff
changeset
|
724 |
19719
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
725 def depth(tree): |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
726 if isinstance(tree, tuple): |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
727 return max(map(depth, tree)) + 1 |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
728 else: |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
729 return 0 |
2f9d5c5256ea
revset: add helper function to get revset parse tree depth
Alexander Plavin <alexander@plav.in>
parents:
19706
diff
changeset
|
730 |
19720
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
731 def funcsused(tree): |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
732 if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'): |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
733 return set() |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
734 else: |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
735 funcs = set() |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
736 for s in tree[1:]: |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
737 funcs |= funcsused(s) |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
738 if tree[0] == 'func': |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
739 funcs.add(tree[1][1]) |
f0b992a9be9c
revset: add helper function to get functions used in a revset parse tree
Alexander Plavin <alexander@plav.in>
parents:
19719
diff
changeset
|
740 return funcs |
35494
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
741 |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
742 _hashre = util.re.compile('[0-9a-fA-F]{1,40}$') |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
743 |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
744 def _ishashlikesymbol(symbol): |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
745 """returns true if the symbol looks like a hash""" |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
746 return _hashre.match(symbol) |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
747 |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
748 def gethashlikesymbols(tree): |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
749 """returns the list of symbols of the tree that look like hashes |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
750 |
35882
87416288be98
tests: make doctest py3-compatible again
Yuya Nishihara <yuya@tcha.org>
parents:
35822
diff
changeset
|
751 >>> gethashlikesymbols(parse(b'3::abe3ff')) |
35494
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
752 ['3', 'abe3ff'] |
35882
87416288be98
tests: make doctest py3-compatible again
Yuya Nishihara <yuya@tcha.org>
parents:
35822
diff
changeset
|
753 >>> gethashlikesymbols(parse(b'precursors(.)')) |
35494
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
754 [] |
35882
87416288be98
tests: make doctest py3-compatible again
Yuya Nishihara <yuya@tcha.org>
parents:
35822
diff
changeset
|
755 >>> gethashlikesymbols(parse(b'precursors(34)')) |
35494
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
756 ['34'] |
35882
87416288be98
tests: make doctest py3-compatible again
Yuya Nishihara <yuya@tcha.org>
parents:
35822
diff
changeset
|
757 >>> gethashlikesymbols(parse(b'abe3ffZ')) |
35494
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
758 [] |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
759 """ |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
760 if not tree: |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
761 return [] |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
762 |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
763 if tree[0] == "symbol": |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
764 if _ishashlikesymbol(tree[1]): |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
765 return [tree[1]] |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
766 elif len(tree) >= 3: |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
767 results = [] |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
768 for subtree in tree[1:]: |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
769 results += gethashlikesymbols(subtree) |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
770 return results |
dd911f95cbda
revsetlang: add utility function to return hash like symbols from the tree
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34273
diff
changeset
|
771 return [] |