##// END OF EJS Templates
revset aliases
Alexander Solovyov -
r14098:9f5a0acb default
parent child Browse files
Show More
@@ -174,7 +174,7 b' def revrange(repo, revs):'
174 pass
174 pass
175
175
176 # fall through to new-style queries if old-style fails
176 # fall through to new-style queries if old-style fails
177 m = revset.match(spec)
177 m = revset.match(repo.ui, spec)
178 for r in m(repo, range(len(repo))):
178 for r in m(repo, range(len(repo))):
179 if r not in seen:
179 if r not in seen:
180 l.append(r)
180 l.append(r)
@@ -1296,7 +1296,10 b' def debugrevspec(ui, repo, expr):'
1296 if ui.verbose:
1296 if ui.verbose:
1297 tree = revset.parse(expr)[0]
1297 tree = revset.parse(expr)[0]
1298 ui.note(tree, "\n")
1298 ui.note(tree, "\n")
1299 func = revset.match(expr)
1299 newtree = revset.findaliases(ui, tree)
1300 if newtree != tree:
1301 ui.note(newtree, "\n")
1302 func = revset.match(ui, expr)
1300 for c in func(repo, range(len(repo))):
1303 for c in func(repo, range(len(repo))):
1301 ui.write("%s\n" % c)
1304 ui.write("%s\n" % c)
1302
1305
@@ -61,6 +61,26 b' The following predicates are supported:'
61
61
62 .. predicatesmarker
62 .. predicatesmarker
63
63
64 New predicates (known as "aliases") can be defined, using any combination of
65 existing predicates or other aliases. An alias definition looks like::
66
67 <alias> = <definition>
68
69 in the ``revsetalias`` section of ``.hgrc``. Arguments of the form `$1`, `$2`,
70 etc. are substituted from the alias into the definition.
71
72 For example,
73
74 ::
75
76 [revsetalias]
77 h = heads()
78 d($1) = sort($1, date)
79 rs($1, $2) = reverse(sort($1, $2))
80
81 defines three aliases, ``h``, ``d``, and ``rs``. ``rs(0:tip, author)`` is
82 exactly equivalent to ``reverse(sort(0:tip, author))``.
83
64 Command line equivalents for :hg:`log`::
84 Command line equivalents for :hg:`log`::
65
85
66 -f -> ::.
86 -f -> ::.
@@ -889,14 +889,89 b' def optimize(x, small):'
889 return w + wa, (op, x[1], ta)
889 return w + wa, (op, x[1], ta)
890 return 1, x
890 return 1, x
891
891
892 class revsetalias(object):
893 funcre = re.compile('^([^(]+)\(([^)]+)\)$')
894 args = ()
895
896 def __init__(self, token, value):
897 '''Aliases like:
898
899 h = heads(default)
900 b($1) = ancestors($1) - ancestors(default)
901 '''
902 if isinstance(token, tuple):
903 self.type, self.name = token
904 else:
905 m = self.funcre.search(token)
906 if m:
907 self.type = 'func'
908 self.name = m.group(1)
909 self.args = [x.strip() for x in m.group(2).split(',')]
910 else:
911 self.type = 'symbol'
912 self.name = token
913
914 if isinstance(value, str):
915 for arg in self.args:
916 value = value.replace(arg, repr(arg))
917 self.replacement, pos = parse(value)
918 if pos != len(value):
919 raise error.ParseError('invalid token', pos)
920 else:
921 self.replacement = value
922
923 def match(self, tree):
924 if not tree:
925 return False
926 if tree == (self.type, self.name):
927 return True
928 if tree[0] != self.type:
929 return False
930 if len(tree) > 1 and tree[1] != ('symbol', self.name):
931 return False
932 # 'func' + funcname + args
933 if ((self.args and len(tree) != 3) or
934 (len(self.args) == 1 and tree[2][0] == 'list') or
935 (len(self.args) > 1 and (tree[2][0] != 'list' or
936 len(tree[2]) - 1 != len(self.args)))):
937 raise error.ParseError('invalid amount of arguments', len(tree) - 2)
938 return True
939
940 def replace(self, tree):
941 if tree == (self.type, self.name):
942 return self.replacement
943 result = self.replacement
944 def getsubtree(i):
945 if tree[2][0] == 'list':
946 return tree[2][i + 1]
947 return tree[i + 2]
948 for i, v in enumerate(self.args):
949 valalias = revsetalias(('string', v), getsubtree(i))
950 result = valalias.process(result)
951 return result
952
953 def process(self, tree):
954 if self.match(tree):
955 return self.replace(tree)
956 if isinstance(tree, tuple):
957 return tuple(map(self.process, tree))
958 return tree
959
960 def findaliases(ui, tree):
961 for k, v in ui.configitems('revsetalias'):
962 alias = revsetalias(k, v)
963 tree = alias.process(tree)
964 return tree
965
892 parse = parser.parser(tokenize, elements).parse
966 parse = parser.parser(tokenize, elements).parse
893
967
894 def match(spec):
968 def match(ui, spec):
895 if not spec:
969 if not spec:
896 raise error.ParseError(_("empty query"))
970 raise error.ParseError(_("empty query"))
897 tree, pos = parse(spec)
971 tree, pos = parse(spec)
898 if (pos != len(spec)):
972 if (pos != len(spec)):
899 raise error.ParseError("invalid token", pos)
973 raise error.ParseError("invalid token", pos)
974 tree = findaliases(ui, tree)
900 weight, tree = optimize(tree, True)
975 weight, tree = optimize(tree, True)
901 def mfunc(repo, subset):
976 def mfunc(repo, subset):
902 return getset(repo, subset, tree)
977 return getset(repo, subset, tree)
@@ -2,7 +2,7 b''
2 $ export HGENCODING
2 $ export HGENCODING
3
3
4 $ try() {
4 $ try() {
5 > hg debugrevspec --debug $@
5 > hg debugrevspec --debug "$@"
6 > }
6 > }
7
7
8 $ log() {
8 $ log() {
@@ -411,3 +411,27 b' parentrevspec'
411 $ log 'tip^foo'
411 $ log 'tip^foo'
412 hg: parse error: ^ expects a number 0, 1, or 2
412 hg: parse error: ^ expects a number 0, 1, or 2
413 [255]
413 [255]
414
415 aliases:
416
417 $ echo '[revsetalias]' >> .hg/hgrc
418 $ echo 'm = merge()' >> .hg/hgrc
419 $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc
420 $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc
421
422 $ try m
423 ('symbol', 'm')
424 ('func', ('symbol', 'merge'), None)
425 6
426 $ try 'd(2:5)'
427 ('func', ('symbol', 'd'), ('range', ('symbol', '2'), ('symbol', '5')))
428 ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('range', ('symbol', '2'), ('symbol', '5')), ('symbol', 'date'))))
429 4
430 5
431 3
432 2
433 $ try 'rs(2 or 3, date)'
434 ('func', ('symbol', 'rs'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date')))
435 ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date'))))
436 3
437 2
General Comments 0
You need to be logged in to leave comments. Login now