mercurial/revset.py
author Wagner Bruna <wbruna@yahoo.com>
Fri, 15 Oct 2010 03:30:38 -0300
changeset 12786 9aae04f4fcf6
parent 12736 7e14e67e6622
child 12815 079a618ea89d
permissions -rw-r--r--
revset: disable subset optimization for parents() and children() (issue2437) For the boolean operators, the subset optimization works by calculating the cheaper argument first, and passing the subset to the second argument to restrict the revision domain. This works well for filtering predicates. But parents() don't work like a filter: it may return revisions outside the specified set. So, combining it with boolean operators may easily yield incorrect results. For instance, for the following revision graph: 0 -- 1 the expression '0 and parents(1)' should evaluate as follows: 0 and parents(1) -> 0 and 0 -> 0 But since [0] is passed to parents() as a subset, we get instead: 0 and parents(1 and 0) -> 0 and parents([]) -> 0 and [] -> [] This also affects children(), p1() and p2(), for the same reasons. Predicates that call these (like heads()) are also affected. We work around this issue by ignoring the subset when propagating the call inside those predicates.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# revset.py - revision set queries for mercurial
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2010 Matt Mackall <mpm@selenic.com>
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
import re
11301
3d0591a66118 move discovery methods from localrepo into new discovery module
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 11293
diff changeset
     9
import parser, util, error, discovery
12085
6f833fc3ccab Consistently import foo as foomod when foo to avoid shadowing
Martin Geisler <mg@aragost.com>
parents: 11944
diff changeset
    10
import match as matchmod
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
    11
from i18n import _
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
elements = {
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
    "(": (20, ("group", 1, ")"), ("func", 1, ")")),
12616
e797fdf91df4 revset: lower precedence of minus infix (issue2361)
Matt Mackall <mpm@selenic.com>
parents: 12615
diff changeset
    15
    "-": (5, ("negate", 19), ("minus", 5)),
11278
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    16
    "::": (17, ("dagrangepre", 17), ("dagrange", 17),
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    17
           ("dagrangepost", 17)),
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    18
    "..": (17, ("dagrangepre", 17), ("dagrange", 17),
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    19
           ("dagrangepost", 17)),
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    20
    ":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
    "not": (10, ("not", 10)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
    "!": (10, ("not", 10)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
    "and": (5, None, ("and", 5)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
    "&": (5, None, ("and", 5)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
    "or": (4, None, ("or", 4)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
    "|": (4, None, ("or", 4)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
    "+": (4, None, ("or", 4)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
    ",": (2, None, ("list", 2)),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
    ")": (0, None, None),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
    "symbol": (0, ("symbol",), None),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
    "string": (0, ("string",), None),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    "end": (0, None, None),
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
}
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
keywords = set(['and', 'or', 'not'])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
def tokenize(program):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
    pos, l = 0, len(program)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
    while pos < l:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
        c = program[pos]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
        if c.isspace(): # skip inter-token whitespace
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
            pass
11278
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    43
        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
    44
            yield ('::', None, pos)
11278
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    45
            pos += 1 # skip ahead
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
        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
    47
            yield ('..', None, pos)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
            pos += 1 # skip ahead
11278
7df88cdf47fd revset: add support for prefix and suffix versions of : and ::
Matt Mackall <mpm@selenic.com>
parents: 11275
diff changeset
    49
        elif c in "():,-|&+!": # handle simple operators
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    50
            yield (c, None, pos)
12408
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    51
        elif (c in '"\'' or c == 'r' and
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    52
              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
    53
            if c == 'r':
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    54
                pos += 1
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    55
                c = program[pos]
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    56
                decode = lambda x: x
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    57
            else:
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    58
                decode = lambda x: x.decode('string-escape')
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
            pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
            s = pos
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
            while pos < l: # find closing quote
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
                d = program[pos]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                if d == '\\': # skip over escaped characters
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
                    pos += 2
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
                    continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
                if d == c:
12408
78a97859b90d revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents: 12401
diff changeset
    67
                    yield ('string', decode(program[s:pos]), s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
                pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
            else:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
    71
                raise error.ParseError(_("unterminated string"), s)
11404
37cbedbeae96 revset: allow extended characters in symbols
Matt Mackall <mpm@selenic.com>
parents: 11385
diff changeset
    72
        elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
            s = pos
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
            pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
            while pos < l: # find end of symbol
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
                d = program[pos]
11404
37cbedbeae96 revset: allow extended characters in symbols
Matt Mackall <mpm@selenic.com>
parents: 11385
diff changeset
    77
                if not (d.isalnum() or d in "._" or ord(d) > 127):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
                if d == '.' and program[pos - 1] == '.': # special case for ..
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
                    pos -= 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
                pos += 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
            sym = program[s:pos]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
            if sym in keywords: # operator keywords
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    85
                yield (sym, None, s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
            else:
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    87
                yield ('symbol', sym, s)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
            pos -= 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
        else:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
    90
            raise error.ParseError(_("syntax error"), pos)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
        pos += 1
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    92
    yield ('end', None, pos)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
# helpers
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
def getstring(x, err):
11406
42408cd43f55 revset: fix up contains/getstring when no args passed
Matt Mackall <mpm@selenic.com>
parents: 11404
diff changeset
    97
    if x and (x[0] == 'string' or x[0] == 'symbol'):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
        return x[1]
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
    99
    raise error.ParseError(err)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
def getlist(x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
    if not x:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
        return []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
    if x[0] == 'list':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        return getlist(x[1]) + [x[2]]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
    return [x]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
11339
744d5b73f776 revset: improve filter argument handling
Matt Mackall <mpm@selenic.com>
parents: 11304
diff changeset
   108
def getargs(x, min, max, err):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   109
    l = getlist(x)
11339
744d5b73f776 revset: improve filter argument handling
Matt Mackall <mpm@selenic.com>
parents: 11304
diff changeset
   110
    if len(l) < min or len(l) > max:
11289
4215ce511134 revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents: 11284
diff changeset
   111
        raise error.ParseError(err)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
    return l
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
def getset(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
    if not x:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   116
        raise error.ParseError(_("missing argument"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
    return methods[x[0]](repo, subset, *x[1:])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
# operator methods
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
def stringset(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
    x = repo[x].rev()
11282
e581f3acc338 revset: fix up tests
Matt Mackall <mpm@selenic.com>
parents: 11280
diff changeset
   123
    if x == -1 and len(subset) == len(repo):
e581f3acc338 revset: fix up tests
Matt Mackall <mpm@selenic.com>
parents: 11280
diff changeset
   124
        return [-1]
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
    if x in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   126
        return [x]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   127
    return []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   128
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   129
def symbolset(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
    if x in symbols:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   131
        raise error.ParseError(_("can't use %s here") % x)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   132
    return stringset(repo, subset, x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   133
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   134
def rangeset(repo, subset, x, y):
11456
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   135
    m = getset(repo, subset, x)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   136
    if not m:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   137
        m = getset(repo, range(len(repo)), x)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   138
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   139
    n = getset(repo, subset, y)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   140
    if not n:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   141
        n = getset(repo, range(len(repo)), y)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   142
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   143
    if not m or not n:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   144
        return []
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   145
    m, n = m[0], n[-1]
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   146
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   147
    if m < n:
11456
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   148
        r = range(m, n + 1)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   149
    else:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   150
        r = range(m, n - 1, -1)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   151
    s = set(subset)
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   152
    return [x for x in r if x in s]
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
def andset(repo, subset, x, y):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   155
    return getset(repo, getset(repo, subset, x), y)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   157
def orset(repo, subset, x, y):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   158
    s = set(getset(repo, subset, x))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   159
    s |= set(getset(repo, [r for r in subset if r not in s], y))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   160
    return [r for r in subset if r in s]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   162
def notset(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   163
    s = set(getset(repo, subset, x))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   164
    return [r for r in subset if r not in s]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   165
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   166
def listset(repo, subset, a, b):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   167
    raise error.ParseError(_("can't use a list in this context"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   168
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
def func(repo, subset, a, b):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
    if a[0] == 'symbol' and a[1] in symbols:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   171
        return symbols[a[1]](repo, subset, b)
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   172
    raise error.ParseError(_("not a function: %s") % a[1])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   173
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   174
# functions
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   176
def node(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   177
    l = getargs(x, 1, 1, _("id requires one argument"))
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   178
    n = getstring(l[0], _("id requires a string"))
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   179
    if len(n) == 40:
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   180
        rn = repo[n].rev()
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   181
    else:
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   182
        rn = repo.changelog.rev(repo.changelog._partialmatch(n))
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   183
    return [r for r in subset if r == rn]
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   184
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   185
def rev(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   186
    l = getargs(x, 1, 1, _("rev requires one argument"))
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   187
    try:
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   188
        l = int(getstring(l[0], _("rev requires a number")))
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   189
    except ValueError:
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   190
        raise error.ParseError(_("rev expects a number"))
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   191
    return [r for r in subset if r == l]
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   192
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   193
def p1(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   194
    ps = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   195
    cl = repo.changelog
12786
9aae04f4fcf6 revset: disable subset optimization for parents() and children() (issue2437)
Wagner Bruna <wbruna@yahoo.com>
parents: 12736
diff changeset
   196
    for r in getset(repo, range(len(repo)), x):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   197
        ps.add(cl.parentrevs(r)[0])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   198
    return [r for r in subset if r in ps]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   199
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   200
def p2(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   201
    ps = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   202
    cl = repo.changelog
12786
9aae04f4fcf6 revset: disable subset optimization for parents() and children() (issue2437)
Wagner Bruna <wbruna@yahoo.com>
parents: 12736
diff changeset
   203
    for r in getset(repo, range(len(repo)), x):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   204
        ps.add(cl.parentrevs(r)[1])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   205
    return [r for r in subset if r in ps]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   206
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
def parents(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
    ps = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   209
    cl = repo.changelog
12786
9aae04f4fcf6 revset: disable subset optimization for parents() and children() (issue2437)
Wagner Bruna <wbruna@yahoo.com>
parents: 12736
diff changeset
   210
    for r in getset(repo, range(len(repo)), x):
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   211
        ps.update(cl.parentrevs(r))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   212
    return [r for r in subset if r in ps]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   213
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
def maxrev(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   215
    s = getset(repo, subset, x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   216
    if s:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
        m = max(s)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
        if m in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
            return [m]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   220
    return []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   221
11708
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   222
def minrev(repo, subset, x):
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   223
    s = getset(repo, subset, x)
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   224
    if s:
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   225
        m = min(s)
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   226
        if m in subset:
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   227
            return [m]
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   228
    return []
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   229
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   230
def limit(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   231
    l = getargs(x, 2, 2, _("limit requires two arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   232
    try:
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   233
        lim = int(getstring(l[1], _("limit requires a number")))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   234
    except ValueError:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   235
        raise error.ParseError(_("limit expects a number"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   236
    return getset(repo, subset, l[0])[:lim]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   237
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   238
def children(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   239
    cs = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   240
    cl = repo.changelog
12786
9aae04f4fcf6 revset: disable subset optimization for parents() and children() (issue2437)
Wagner Bruna <wbruna@yahoo.com>
parents: 12736
diff changeset
   241
    s = set(getset(repo, range(len(repo)), x))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   242
    for r in xrange(0, len(repo)):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   243
        for p in cl.parentrevs(r):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   244
            if p in s:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   245
                cs.add(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   246
    return [r for r in subset if r in cs]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   247
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   248
def branch(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   249
    s = getset(repo, range(len(repo)), x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   250
    b = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   251
    for r in s:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   252
        b.add(repo[r].branch())
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   253
    s = set(s)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   254
    return [r for r in subset if r in s or repo[r].branch() in b]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   255
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   256
def ancestor(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   257
    l = getargs(x, 2, 2, _("ancestor requires two arguments"))
11650
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   258
    r = range(len(repo))
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   259
    a = getset(repo, r, l[0])
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   260
    b = getset(repo, r, l[1])
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   261
    if len(a) != 1 or len(b) != 1:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   262
        raise error.ParseError(_("ancestor arguments must be single revisions"))
11650
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   263
    an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   264
ebaf117c2642 revset: fix ancestor subset handling (issue2298)
Matt Mackall <mpm@selenic.com>
parents: 11467
diff changeset
   265
    return [r for r in an if r in subset]
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   267
def ancestors(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   268
    args = getset(repo, range(len(repo)), x)
11456
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   269
    if not args:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   270
        return []
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   271
    s = set(repo.changelog.ancestors(*args)) | set(args)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   272
    return [r for r in subset if r in s]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   273
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   274
def descendants(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   275
    args = getset(repo, range(len(repo)), x)
11456
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   276
    if not args:
88abbb046e66 revset: deal with empty sets in range endpoints
Matt Mackall <mpm@selenic.com>
parents: 11446
diff changeset
   277
        return []
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   278
    s = set(repo.changelog.descendants(*args)) | set(args)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   279
    return [r for r in subset if r in s]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   280
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   281
def follow(repo, subset, x):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   282
    getargs(x, 0, 0, _("follow takes no arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   283
    p = repo['.'].rev()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   284
    s = set(repo.changelog.ancestors(p)) | set([p])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   285
    return [r for r in subset if r in s]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   286
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   287
def date(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   288
    ds = getstring(x, _("date requires a string"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   289
    dm = util.matchdate(ds)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   290
    return [r for r in subset if dm(repo[r].date()[0])]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   291
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   292
def keyword(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   293
    kw = getstring(x, _("keyword requires a string")).lower()
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   294
    l = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   295
    for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   296
        c = repo[r]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   297
        t = " ".join(c.files() + [c.user(), c.description()])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   298
        if kw in t.lower():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   299
            l.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   300
    return l
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   301
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   302
def grep(repo, subset, x):
12320
40c40c6f20b8 revset: handle re.compile() errors in grep()
Brodie Rao <brodie@bitheap.org>
parents: 11882
diff changeset
   303
    try:
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   304
        gr = re.compile(getstring(x, _("grep requires a string")))
12320
40c40c6f20b8 revset: handle re.compile() errors in grep()
Brodie Rao <brodie@bitheap.org>
parents: 11882
diff changeset
   305
    except re.error, e:
40c40c6f20b8 revset: handle re.compile() errors in grep()
Brodie Rao <brodie@bitheap.org>
parents: 11882
diff changeset
   306
        raise error.ParseError(_('invalid match pattern: %s') % e)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   307
    l = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   308
    for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   309
        c = repo[r]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   310
        for e in c.files() + [c.user(), c.description()]:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   311
            if gr.search(e):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   312
                l.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   313
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   314
    return l
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   315
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   316
def author(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   317
    n = getstring(x, _("author requires a string")).lower()
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   318
    return [r for r in subset if n in repo[r].user().lower()]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   319
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   320
def hasfile(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   321
    pat = getstring(x, _("file requires a pattern"))
12085
6f833fc3ccab Consistently import foo as foomod when foo to avoid shadowing
Martin Geisler <mg@aragost.com>
parents: 11944
diff changeset
   322
    m = matchmod.match(repo.root, repo.getcwd(), [pat])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   323
    s = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   324
    for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   325
        for f in repo[r].files():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   326
            if m(f):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   327
                s.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   328
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   329
    return s
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   330
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   331
def contains(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   332
    pat = getstring(x, _("contains requires a pattern"))
12085
6f833fc3ccab Consistently import foo as foomod when foo to avoid shadowing
Martin Geisler <mg@aragost.com>
parents: 11944
diff changeset
   333
    m = matchmod.match(repo.root, repo.getcwd(), [pat])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   334
    s = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   335
    if m.files() == [pat]:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   336
        for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   337
            if pat in repo[r]:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   338
                s.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   339
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   340
    else:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   341
        for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   342
            for f in repo[r].manifest():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   343
                if m(f):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   344
                    s.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   345
                    continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   346
    return s
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   347
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   348
def checkstatus(repo, subset, pat, field):
12085
6f833fc3ccab Consistently import foo as foomod when foo to avoid shadowing
Martin Geisler <mg@aragost.com>
parents: 11944
diff changeset
   349
    m = matchmod.match(repo.root, repo.getcwd(), [pat])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   350
    s = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   351
    fast = (m.files() == [pat])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   352
    for r in subset:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   353
        c = repo[r]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   354
        if fast:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   355
            if pat not in c.files():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   356
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   357
        else:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   358
            for f in c.files():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   359
                if m(f):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   360
                    break
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   361
            else:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   362
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   363
        files = repo.status(c.p1().node(), c.node())[field]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   364
        if fast:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   365
            if pat in files:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   366
                s.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   367
                continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   368
        else:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   369
            for f in files:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   370
                if m(f):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   371
                    s.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   372
                    continue
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   373
    return s
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   374
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   375
def modifies(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   376
    pat = getstring(x, _("modifies requires a pattern"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   377
    return checkstatus(repo, subset, pat, 0)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   378
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   379
def adds(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   380
    pat = getstring(x, _("adds requires a pattern"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   381
    return checkstatus(repo, subset, pat, 1)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   382
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   383
def removes(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   384
    pat = getstring(x, _("removes requires a pattern"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   385
    return checkstatus(repo, subset, pat, 2)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   386
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   387
def merge(repo, subset, x):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   388
    getargs(x, 0, 0, _("merge takes no arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   389
    cl = repo.changelog
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   390
    return [r for r in subset if cl.parentrevs(r)[1] != -1]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   391
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   392
def closed(repo, subset, x):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   393
    getargs(x, 0, 0, _("closed takes no arguments"))
11349
cf8a9154a362 revset: fix call to ctx.extra() in closed()
Georg Brandl <georg@python.org>
parents: 11339
diff changeset
   394
    return [r for r in subset if repo[r].extra().get('close')]
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   395
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   396
def head(repo, subset, x):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   397
    getargs(x, 0, 0, _("head takes no arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   398
    hs = set()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   399
    for b, ls in repo.branchmap().iteritems():
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   400
        hs.update(repo[h].rev() for h in ls)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   401
    return [r for r in subset if r in hs]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   402
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   403
def reverse(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   404
    l = getset(repo, subset, x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   405
    l.reverse()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   406
    return l
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   407
11944
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   408
def present(repo, subset, x):
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   409
    try:
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   410
        return getset(repo, subset, x)
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   411
    except error.RepoLookupError:
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   412
        return []
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   413
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   414
def sort(repo, subset, x):
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   415
    l = getargs(x, 1, 2, _("sort requires one or two arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   416
    keys = "rev"
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   417
    if len(l) == 2:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   418
        keys = getstring(l[1], _("sort spec must be a string"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   419
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   420
    s = l[0]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   421
    keys = keys.split()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   422
    l = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   423
    def invert(s):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   424
        return "".join(chr(255 - ord(c)) for c in s)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   425
    for r in getset(repo, subset, s):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   426
        c = repo[r]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   427
        e = []
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   428
        for k in keys:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   429
            if k == 'rev':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   430
                e.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   431
            elif k == '-rev':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   432
                e.append(-r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   433
            elif k == 'branch':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   434
                e.append(c.branch())
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   435
            elif k == '-branch':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   436
                e.append(invert(c.branch()))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   437
            elif k == 'desc':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   438
                e.append(c.description())
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   439
            elif k == '-desc':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   440
                e.append(invert(c.description()))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   441
            elif k in 'user author':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   442
                e.append(c.user())
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   443
            elif k in '-user -author':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   444
                e.append(invert(c.user()))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   445
            elif k == 'date':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   446
                e.append(c.date()[0])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   447
            elif k == '-date':
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   448
                e.append(-c.date()[0])
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   449
            else:
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   450
                raise error.ParseError(_("unknown sort key %r") % k)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   451
        e.append(r)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   452
        l.append(e)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   453
    l.sort()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   454
    return [e[-1] for e in l]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   455
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   456
def getall(repo, subset, x):
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   457
    getargs(x, 0, 0, _("all takes no arguments"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   458
    return subset
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   459
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   460
def heads(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   461
    s = getset(repo, subset, x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   462
    ps = set(parents(repo, subset, x))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   463
    return [r for r in s if r not in ps]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   464
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   465
def roots(repo, subset, x):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   466
    s = getset(repo, subset, x)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   467
    cs = set(children(repo, subset, x))
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   468
    return [r for r in s if r not in cs]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   469
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   470
def outgoing(repo, subset, x):
11293
0e5ce2325795 revset: delay import of hg to avoid start-up import loops
Matt Mackall <mpm@selenic.com>
parents: 11289
diff changeset
   471
    import hg # avoid start-up nasties
12736
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   472
    l = getargs(x, 0, 1, _("outgoing requires a repository path"))
7e14e67e6622 revset: use 'requires' instead of 'wants' in error message
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 12733
diff changeset
   473
    dest = l and getstring(l[0], _("outgoing requires a repository path")) or ''
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   474
    dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   475
    dest, branches = hg.parseurl(dest)
12614
f314723f36f5 revset: fix #branch in urls for outgoing()
Adrian Buehlmann <adrian@cadifra.com>
parents: 12320
diff changeset
   476
    revs, checkout = hg.addbranchrevs(repo, repo, branches, [])
f314723f36f5 revset: fix #branch in urls for outgoing()
Adrian Buehlmann <adrian@cadifra.com>
parents: 12320
diff changeset
   477
    if revs:
f314723f36f5 revset: fix #branch in urls for outgoing()
Adrian Buehlmann <adrian@cadifra.com>
parents: 12320
diff changeset
   478
        revs = [repo.lookup(rev) for rev in revs]
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   479
    other = hg.repository(hg.remoteui(repo, {}), dest)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   480
    repo.ui.pushbuffer()
11301
3d0591a66118 move discovery methods from localrepo into new discovery module
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 11293
diff changeset
   481
    o = discovery.findoutgoing(repo, other)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   482
    repo.ui.popbuffer()
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   483
    cl = repo.changelog
12614
f314723f36f5 revset: fix #branch in urls for outgoing()
Adrian Buehlmann <adrian@cadifra.com>
parents: 12320
diff changeset
   484
    o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, revs)[0]])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   485
    return [r for r in subset if r in o]
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   486
12715
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   487
def tag(repo, subset, x):
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   488
    args = getargs(x, 0, 1, _("tag takes one or no arguments"))
11280
a5eb0bf7e158 revset: add tagged predicate
Matt Mackall <mpm@selenic.com>
parents: 11279
diff changeset
   489
    cl = repo.changelog
12715
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   490
    if args:
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   491
        tn = getstring(args[0],
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   492
                       _('the argument to tag must be a string'))
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   493
        s = set([cl.rev(n) for t, n in repo.tagslist() if t == tn])
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   494
    else:
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   495
        s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
11280
a5eb0bf7e158 revset: add tagged predicate
Matt Mackall <mpm@selenic.com>
parents: 11279
diff changeset
   496
    return [r for r in subset if r in s]
a5eb0bf7e158 revset: add tagged predicate
Matt Mackall <mpm@selenic.com>
parents: 11279
diff changeset
   497
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   498
symbols = {
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   499
    "adds": adds,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   500
    "all": getall,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   501
    "ancestor": ancestor,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   502
    "ancestors": ancestors,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   503
    "author": author,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   504
    "branch": branch,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   505
    "children": children,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   506
    "closed": closed,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   507
    "contains": contains,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   508
    "date": date,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   509
    "descendants": descendants,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   510
    "file": hasfile,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   511
    "follow": follow,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   512
    "grep": grep,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   513
    "head": head,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   514
    "heads": heads,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   515
    "keyword": keyword,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   516
    "limit": limit,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   517
    "max": maxrev,
11708
ba65d61f3158 revset: add min function
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11650
diff changeset
   518
    "min": minrev,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   519
    "merge": merge,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   520
    "modifies": modifies,
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   521
    "id": node,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   522
    "outgoing": outgoing,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   523
    "p1": p1,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   524
    "p2": p2,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   525
    "parents": parents,
11944
df52ff0980fe revset: predicate to avoid lookup errors
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 11886
diff changeset
   526
    "present": present,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   527
    "removes": removes,
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   528
    "reverse": reverse,
12716
c7e619e30ba3 revset: add id() and rev() to allow explicitly referring to changes by hash or rev
Augie Fackler <durin42@gmail.com>
parents: 12715
diff changeset
   529
    "rev": rev,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   530
    "roots": roots,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   531
    "sort": sort,
12715
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   532
    "tag": tag,
33820dccbea4 revset: rename tagged() to tag() and allow it to take an optional tag name
Augie Fackler <durin42@gmail.com>
parents: 12616
diff changeset
   533
    "tagged": tag,
11284
0b5c2e82aeb5 revset: sort the predicate list
Matt Mackall <mpm@selenic.com>
parents: 11283
diff changeset
   534
    "user": author,
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   535
}
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   536
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   537
methods = {
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   538
    "range": rangeset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   539
    "string": stringset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   540
    "symbol": symbolset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   541
    "and": andset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   542
    "or": orset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   543
    "not": notset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   544
    "list": listset,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   545
    "func": func,
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   546
}
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   547
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   548
def optimize(x, small):
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   549
    if x == None:
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   550
        return 0, x
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   551
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   552
    smallbonus = 1
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   553
    if small:
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   554
        smallbonus = .5
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   555
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   556
    op = x[0]
11283
a6356b2695a3 revset: fix - handling in the optimizer
Matt Mackall <mpm@selenic.com>
parents: 11282
diff changeset
   557
    if op == 'minus':
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   558
        return optimize(('and', x[1], ('not', x[2])), small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   559
    elif op == 'dagrange':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   560
        return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   561
                         ('func', ('symbol', 'ancestors'), x[2])), small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   562
    elif op == 'dagrangepre':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   563
        return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   564
    elif op == 'dagrangepost':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   565
        return optimize(('func', ('symbol', 'descendants'), x[1]), small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   566
    elif op == 'rangepre':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   567
        return optimize(('range', ('string', '0'), x[1]), small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   568
    elif op == 'rangepost':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   569
        return optimize(('range', x[1], ('string', 'tip')), small)
11467
6b836d5c8c9e revset: make negate work for sort specs
Matt Mackall <mpm@selenic.com>
parents: 11456
diff changeset
   570
    elif op == 'negate':
6b836d5c8c9e revset: make negate work for sort specs
Matt Mackall <mpm@selenic.com>
parents: 11456
diff changeset
   571
        return optimize(('string',
6b836d5c8c9e revset: make negate work for sort specs
Matt Mackall <mpm@selenic.com>
parents: 11456
diff changeset
   572
                         '-' + getstring(x[1], _("can't negate that"))), small)
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   573
    elif op in 'string symbol negate':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   574
        return smallbonus, x # single revisions are small
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   575
    elif op == 'and' or op == 'dagrange':
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   576
        wa, ta = optimize(x[1], True)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   577
        wb, tb = optimize(x[2], True)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   578
        w = min(wa, wb)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   579
        if wa > wb:
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   580
            return w, (op, tb, ta)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   581
        return w, (op, ta, tb)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   582
    elif op == 'or':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   583
        wa, ta = optimize(x[1], False)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   584
        wb, tb = optimize(x[2], False)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   585
        if wb < wa:
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   586
            wb, wa = wa, wb
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   587
        return max(wa, wb), (op, ta, tb)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   588
    elif op == 'not':
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   589
        o = optimize(x[1], not small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   590
        return o[0], (op, o[1])
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   591
    elif op == 'group':
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   592
        return optimize(x[1], small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   593
    elif op in 'range list':
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   594
        wa, ta = optimize(x[1], small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   595
        wb, tb = optimize(x[2], small)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   596
        return wa + wb, (op, ta, tb)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   597
    elif op == 'func':
11383
de544774ebea revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents: 11349
diff changeset
   598
        f = getstring(x[1], _("not a symbol"))
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   599
        wa, ta = optimize(x[2], small)
12351
b913232d13c1 revsets: reduce cost of outgoing in the optimizer
Matt Mackall <mpm@selenic.com>
parents: 12321
diff changeset
   600
        if f in "grep date user author keyword branch file outgoing":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   601
            w = 10 # slow
12351
b913232d13c1 revsets: reduce cost of outgoing in the optimizer
Matt Mackall <mpm@selenic.com>
parents: 12321
diff changeset
   602
        elif f in "modifies adds removes":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   603
            w = 30 # slower
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   604
        elif f == "contains":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   605
            w = 100 # very slow
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   606
        elif f == "ancestor":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   607
            w = 1 * smallbonus
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   608
        elif f == "reverse limit":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   609
            w = 0
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   610
        elif f in "sort":
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   611
            w = 10 # assume most sorts look at changelog
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   612
        else:
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   613
            w = 1
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   614
        return w + wa, (op, x[1], ta)
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   615
    return 1, x
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   616
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   617
parse = parser.parser(tokenize, elements).parse
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   618
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   619
def match(spec):
11385
e5a2134c083b revset: nicer exception for empty queries
Matt Mackall <mpm@selenic.com>
parents: 11383
diff changeset
   620
    if not spec:
e5a2134c083b revset: nicer exception for empty queries
Matt Mackall <mpm@selenic.com>
parents: 11383
diff changeset
   621
        raise error.ParseError(_("empty query"))
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   622
    tree = parse(spec)
11279
62ccf4cd6e7f revset: optimize the parse tree directly
Matt Mackall <mpm@selenic.com>
parents: 11278
diff changeset
   623
    weight, tree = optimize(tree, True)
11275
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   624
    def mfunc(repo, subset):
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   625
        return getset(repo, subset, tree)
c9ce8ecd6ca1 revset: introduce revset core
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   626
    return mfunc