mercurial/match.py
author Martin von Zweigbergk <martinvonz@google.com>
Wed, 27 May 2015 10:44:04 -0700
changeset 25362 20ad936ac5d2
parent 25301 caaf4045eca8
child 25433 419ac63fe29c
permissions -rw-r--r--
treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?' For globs like 'foo/ba?', match._roots() will return 'foo'. Since visitdir(), excludes directories in the excluded roots, it would skip the entire foo directory. This is incorrect, since 'foo/ba?' doesn't mean that everything in foo/ should be exluded. Note that visitdir() is called only from the treemanifest class, so this only affects tree manifests. Fix by adding roots to the set of excluded roots only if there are no excluded patterns. Since 'glob' is the default pattern type for globs, we also need to update some -X patterns in the tests to be of 'path' type to take advantage of the visitdir tricks. For consistency, also update the -I patterns. It seems a little unfortunate that 'foo' in 'hg files -X foo' is considered a pattern because of the implied 'glob' type, but improving that is left for another day.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8761
0289f384e1e5 Generally replace "file name" with "filename" in help and comments.
timeless <timeless@gmail.com>
parents: 8682
diff changeset
     1
# match.py - filename matching
8231
5d4d88a4f5e6 match: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8152
diff changeset
     2
#
5d4d88a4f5e6 match: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8152
diff changeset
     3
#  Copyright 2008, 2009 Matt Mackall <mpm@selenic.com> and others
5d4d88a4f5e6 match: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8152
diff changeset
     4
#
5d4d88a4f5e6 match: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8152
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9036
diff changeset
     6
# GNU General Public License version 2 or any later version.
8231
5d4d88a4f5e6 match: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8152
diff changeset
     7
9036
32e678f9045f split local and stdlib module imports (eases migration issues)
Alejandro Santos <alejolp@alejolp.com>
parents: 8761
diff changeset
     8
import re
20401
906358d0350e match: use ctx.getfileset() instead of fileset.getfileset()
Augie Fackler <raf@durin42.com>
parents: 20033
diff changeset
     9
import util, pathutil
12133
b046b90c4ae5 match: mark error messages for translation
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
    10
from i18n import _
6576
69f3e9ac7c56 walk: introduce match objects
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    12
propertycache = util.propertycache
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    13
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    14
def _rematcher(regex):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    15
    '''compile the regexp with the best available regexp engine and return a
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    16
    matcher function'''
21909
335bb8b80443 match: use util.re.compile instead of util.compilere
Siddharth Agarwal <sid0@fb.com>
parents: 21815
diff changeset
    17
    m = util.re.compile(regex)
16943
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    18
    try:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    19
        # slightly faster, provided by facebook's re2 bindings
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    20
        return m.test_match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    21
    except AttributeError:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    22
        return m.match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    23
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    24
def _expandsets(kindpats, ctx, listsubrepos):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    25
    '''Returns the kindpats list with the 'set' patterns expanded.'''
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    26
    fset = set()
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    27
    other = []
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    28
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    29
    for kind, pat, source in kindpats:
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    30
        if kind == 'set':
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    31
            if not ctx:
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    32
                raise util.Abort("fileset expression with no context")
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    33
            s = ctx.getfileset(pat)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    34
            fset.update(s)
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    35
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    36
            if listsubrepos:
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    37
                for subpath in ctx.substate:
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    38
                    s = ctx.sub(subpath).getfileset(pat)
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    39
                    fset.update(subpath + '/' + f for f in s)
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    40
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    41
            continue
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    42
        other.append((kind, pat, source))
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    43
    return fset, other
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    44
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    45
def _expandsubinclude(kindpats, root):
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    46
    '''Returns the list of subinclude matchers and the kindpats without the
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    47
    subincludes in it.'''
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    48
    relmatchers = []
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    49
    other = []
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    50
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    51
    for kind, pat, source in kindpats:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    52
        if kind == 'subinclude':
25301
caaf4045eca8 match: normpath the ignore source when expanding the 'subinclude' kind
Matt Harbison <matt_harbison@yahoo.com>
parents: 25283
diff changeset
    53
            sourceroot = pathutil.dirname(util.normpath(source))
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    54
            pat = util.pconvert(pat)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    55
            path = pathutil.join(sourceroot, pat)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    56
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    57
            newroot = pathutil.dirname(path)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    58
            relmatcher = match(newroot, '', [], ['include:%s' % path])
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    59
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    60
            prefix = pathutil.canonpath(root, root, newroot)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    61
            if prefix:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    62
                prefix += '/'
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    63
            relmatchers.append((prefix, relmatcher))
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    64
        else:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    65
            other.append((kind, pat, source))
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    66
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    67
    return relmatchers, other
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    68
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    69
def _kindpatsalwaysmatch(kindpats):
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    70
    """"Checks whether the kindspats match everything, as e.g.
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    71
    'relpath:.' does.
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    72
    """
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    73
    for kind, pat, source in kindpats:
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    74
        if pat != '' or kind not in ['relpath', 'glob']:
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    75
            return False
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    76
    return True
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    77
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
    78
class match(object):
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
    79
    def __init__(self, root, cwd, patterns, include=[], exclude=[],
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    80
                 default='glob', exact=False, auditor=None, ctx=None,
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
    81
                 listsubrepos=False, warn=None):
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    82
        """build an object to match a set of file patterns
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    83
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    84
        arguments:
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    85
        root - the canonical root of the tree you're matching against
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    86
        cwd - the current working directory, if relevant
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    87
        patterns - patterns to find
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    88
        include - patterns to include (unless they are excluded)
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    89
        exclude - patterns to exclude (even if they are included)
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    90
        default - if a pattern in patterns has no explicit type, assume this one
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    91
        exact - patterns are actually filenames (include/exclude still apply)
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
    92
        warn - optional function used for printing warnings
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    93
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    94
        a pattern is one of:
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    95
        'glob:<glob>' - a glob relative to cwd
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    96
        're:<regexp>' - a regular expression
17425
e95ec38f86b0 fix wording and not-completely-trivial spelling errors and bad docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 16943
diff changeset
    97
        'path:<path>' - a path relative to repository root
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    98
        'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
    99
        'relpath:<path>' - a path relative to cwd
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   100
        'relre:<regexp>' - a regexp that needn't match the start of a name
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   101
        'set:<fileset>' - a fileset expression
25215
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   102
        'include:<path>' - a file of patterns to read and include
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   103
        'subinclude:<path>' - a file of patterns to match against files under
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   104
                              the same directory
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   105
        '<something>' - a pattern of the specified default type
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   106
        """
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   107
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   108
        self._root = root
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   109
        self._cwd = cwd
21079
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   110
        self._files = [] # exact files and roots of patterns
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   111
        self._anypats = bool(include or exclude)
18713
8728579f6bdc match: more accurately report when we're always going to match
Bryan O'Sullivan <bryano@fb.com>
parents: 17425
diff changeset
   112
        self._always = False
23480
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   113
        self._pathrestricted = bool(include or exclude or patterns)
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
   114
        self._warn = warn
25231
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   115
        self._includeroots = set()
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   116
        self._includedirs = set(['.'])
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   117
        self._excluderoots = set()
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   118
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   119
        matchfns = []
8586
347fe1ac4f21 match: add exact flag to match() to unify all match forms
Matt Mackall <mpm@selenic.com>
parents: 8585
diff changeset
   120
        if include:
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   121
            kindpats = self._normalize(include, 'glob', root, cwd, auditor)
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   122
            self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)',
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   123
                                              listsubrepos, root)
25231
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   124
            self._includeroots.update(_roots(kindpats))
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   125
            self._includeroots.discard('.')
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   126
            self._includedirs.update(util.dirs(self._includeroots))
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   127
            matchfns.append(im)
8586
347fe1ac4f21 match: add exact flag to match() to unify all match forms
Matt Mackall <mpm@selenic.com>
parents: 8585
diff changeset
   128
        if exclude:
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   129
            kindpats = self._normalize(exclude, 'glob', root, cwd, auditor)
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   130
            self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)',
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   131
                                              listsubrepos, root)
25362
20ad936ac5d2 treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?'
Martin von Zweigbergk <martinvonz@google.com>
parents: 25301
diff changeset
   132
            if not _anypats(kindpats):
20ad936ac5d2 treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?'
Martin von Zweigbergk <martinvonz@google.com>
parents: 25301
diff changeset
   133
                self._excluderoots.update(_roots(kindpats))
20ad936ac5d2 treemanifest: visit directory 'foo' when given e.g. '-X foo/ba?'
Martin von Zweigbergk <martinvonz@google.com>
parents: 25301
diff changeset
   134
                self._excluderoots.discard('.')
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   135
            matchfns.append(lambda f: not em(f))
8586
347fe1ac4f21 match: add exact flag to match() to unify all match forms
Matt Mackall <mpm@selenic.com>
parents: 8585
diff changeset
   136
        if exact:
16789
c17ce7cd5090 match: make 'match.files()' return list object always
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16182
diff changeset
   137
            if isinstance(patterns, list):
c17ce7cd5090 match: make 'match.files()' return list object always
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16182
diff changeset
   138
                self._files = patterns
c17ce7cd5090 match: make 'match.files()' return list object always
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16182
diff changeset
   139
            else:
c17ce7cd5090 match: make 'match.files()' return list object always
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 16182
diff changeset
   140
                self._files = list(patterns)
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   141
            matchfns.append(self.exact)
8586
347fe1ac4f21 match: add exact flag to match() to unify all match forms
Matt Mackall <mpm@selenic.com>
parents: 8585
diff changeset
   142
        elif patterns:
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   143
            kindpats = self._normalize(patterns, default, root, cwd, auditor)
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
   144
            if not _kindpatsalwaysmatch(kindpats):
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
   145
                self._files = _roots(kindpats)
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
   146
                self._anypats = self._anypats or _anypats(kindpats)
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   147
                self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   148
                                                   listsubrepos, root)
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
   149
                matchfns.append(pm)
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   150
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   151
        if not matchfns:
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   152
            m = util.always
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   153
            self._always = True
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   154
        elif len(matchfns) == 1:
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   155
            m = matchfns[0]
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   156
        else:
22513
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   157
            def m(f):
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   158
                for matchfn in matchfns:
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   159
                    if not matchfn(f):
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   160
                        return False
ca709785caf2 match: simplify brittle predicate construction
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 21915
diff changeset
   161
                return True
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   162
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   163
        self.matchfn = m
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   164
        self._fileroots = set(self._files)
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   165
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   166
    def __call__(self, fn):
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   167
        return self.matchfn(fn)
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   168
    def __iter__(self):
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   169
        for f in self._files:
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   170
            yield f
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   171
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   172
    # Callbacks related to how the matcher is used by dirstate.walk.
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   173
    # Subscribers to these events must monkeypatch the matcher object.
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   174
    def bad(self, f, msg):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   175
        '''Callback from dirstate.walk for each explicit file that can't be
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   176
        found/accessed, with an error message.'''
8680
b6511055d37b match: ignore return of match.bad
Matt Mackall <mpm@selenic.com>
parents: 8678
diff changeset
   177
        pass
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   178
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   179
    # If an explicitdir is set, it will be called when an explicitly listed
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   180
    # directory is visited.
19143
3cb9468535bd match: make explicitdir and traversedir None by default
Siddharth Agarwal <sid0@fb.com>
parents: 19141
diff changeset
   181
    explicitdir = None
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   182
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   183
    # If an traversedir is set, it will be called when a directory discovered
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   184
    # by recursive traversal is visited.
19143
3cb9468535bd match: make explicitdir and traversedir None by default
Siddharth Agarwal <sid0@fb.com>
parents: 19141
diff changeset
   185
    traversedir = None
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   186
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   187
    def abs(self, f):
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   188
        '''Convert a repo path back to path that is relative to the root of the
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   189
        matcher.'''
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   190
        return f
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   191
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   192
    def rel(self, f):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   193
        '''Convert repo path back to path that is relative to cwd of matcher.'''
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   194
        return util.pathto(self._root, self._cwd, f)
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   195
23480
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   196
    def uipath(self, f):
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   197
        '''Convert repo path to a display path.  If patterns or -I/-X were used
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   198
        to create this matcher, the display path will be relative to cwd.
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   199
        Otherwise it is relative to the root of the repo.'''
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   200
        return (self._pathrestricted and self.rel(f)) or self.abs(f)
23480
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   201
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   202
    def files(self):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   203
        '''Explicitly listed files or patterns or roots:
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   204
        if no patterns or .always(): empty list,
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   205
        if exact: list exact files,
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   206
        if not .anypats(): list all files and dirs,
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   207
        else: optimal roots'''
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   208
        return self._files
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   209
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   210
    @propertycache
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   211
    def _dirs(self):
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   212
        return set(util.dirs(self._fileroots)) | set(['.'])
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   213
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   214
    def visitdir(self, dir):
25231
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   215
        '''Decides whether a directory should be visited based on whether it
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   216
        has potential matches in it or one of its subdirectories. This is
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   217
        based on the match's primary, included, and excluded patterns.
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   218
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   219
        This function's behavior is undefined if it has returned False for
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   220
        one of the dir's parent directories.
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   221
        '''
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   222
        if dir in self._excluderoots:
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   223
            return False
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   224
        parentdirs = None
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   225
        if (self._includeroots and dir not in self._includeroots and
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   226
                dir not in self._includedirs):
25250
f9a29dc964a3 match: fix bug in match.visitdir()
Drew Gottlieb <drgott@google.com>
parents: 25239
diff changeset
   227
            parentdirs = list(util.finddirs(dir))
25231
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   228
            if not any(parent in self._includeroots for parent in parentdirs):
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   229
                return False
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   230
        return (not self._fileroots or '.' in self._fileroots or
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   231
                dir in self._fileroots or dir in self._dirs or
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   232
                any(parentdir in self._fileroots
25231
8545bd381504 match: have visitdir() consider includes and excludes
Drew Gottlieb <drgott@google.com>
parents: 25216
diff changeset
   233
                    for parentdir in parentdirs or util.finddirs(dir)))
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   234
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   235
    def exact(self, f):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   236
        '''Returns True if f is in .files().'''
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   237
        return f in self._fileroots
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   238
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   239
    def anypats(self):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   240
        '''Matcher uses patterns or include/exclude.'''
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   241
        return self._anypats
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   242
16645
9a21fc2c7d32 localrepo: optimize internode status calls using match.always
Jesse Glick <jesse.glick@oracle.com>
parents: 16182
diff changeset
   243
    def always(self):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   244
        '''Matcher will match everything and .files() will be empty
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   245
        - optimization might be possible and necessary.'''
18713
8728579f6bdc match: more accurately report when we're always going to match
Bryan O'Sullivan <bryano@fb.com>
parents: 17425
diff changeset
   246
        return self._always
8568
4fa1618bf495 match: refactor patkind
Matt Mackall <mpm@selenic.com>
parents: 8567
diff changeset
   247
25114
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   248
    def ispartial(self):
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   249
        '''True if the matcher won't always match.
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   250
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   251
        Although it's just the inverse of _always in this implementation,
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   252
        an extenion such as narrowhg might make it return something
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   253
        slightly different.'''
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   254
        return not self._always
d1d69ca78883 match: add match.ispartial()
Drew Gottlieb <drgott@google.com>
parents: 24790
diff changeset
   255
24448
55c449345b10 match: add isexact() method to hide internals
Martin von Zweigbergk <martinvonz@google.com>
parents: 24447
diff changeset
   256
    def isexact(self):
55c449345b10 match: add isexact() method to hide internals
Martin von Zweigbergk <martinvonz@google.com>
parents: 24447
diff changeset
   257
        return self.matchfn == self.exact
55c449345b10 match: add isexact() method to hide internals
Martin von Zweigbergk <martinvonz@google.com>
parents: 24447
diff changeset
   258
25233
9789b4a7c595 match: introduce boolean prefix() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 25231
diff changeset
   259
    def prefix(self):
9789b4a7c595 match: introduce boolean prefix() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 25231
diff changeset
   260
        return not self.always() and not self.isexact() and not self.anypats()
9789b4a7c595 match: introduce boolean prefix() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 25231
diff changeset
   261
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   262
    def _normalize(self, patterns, default, root, cwd, auditor):
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   263
        '''Convert 'kind:pat' from the patterns list to tuples with kind and
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   264
        normalized and rooted patterns and with listfiles expanded.'''
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   265
        kindpats = []
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   266
        for kind, pat in [_patsplit(p, default) for p in patterns]:
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   267
            if kind in ('glob', 'relpath'):
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   268
                pat = pathutil.canonpath(root, cwd, pat, auditor)
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   269
            elif kind in ('relglob', 'path'):
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   270
                pat = util.normpath(pat)
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   271
            elif kind in ('listfile', 'listfile0'):
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   272
                try:
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   273
                    files = util.readfile(pat)
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   274
                    if kind == 'listfile0':
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   275
                        files = files.split('\0')
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   276
                    else:
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   277
                        files = files.splitlines()
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   278
                    files = [f for f in files if f]
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   279
                except EnvironmentError:
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   280
                    raise util.Abort(_("unable to read file list (%s)") % pat)
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   281
                for k, p, source in self._normalize(files, default, root, cwd,
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   282
                                                    auditor):
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   283
                    kindpats.append((k, p, pat))
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   284
                continue
25215
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   285
            elif kind == 'include':
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   286
                try:
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   287
                    includepats = readpatternfile(pat, self._warn)
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   288
                    for k, p, source in self._normalize(includepats, default,
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   289
                                                        root, cwd, auditor):
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   290
                        kindpats.append((k, p, source or pat))
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   291
                except util.Abort, inst:
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   292
                    raise util.Abort('%s: %s' % (pat, inst[0]))
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   293
                except IOError, inst:
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   294
                    if self._warn:
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   295
                        self._warn(_("skipping unreadable pattern file "
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   296
                                     "'%s': %s\n") % (pat, inst.strerror))
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   297
                continue
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   298
            # else: re or relre - which cannot be normalized
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   299
            kindpats.append((kind, pat, ''))
24789
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   300
        return kindpats
0b1577c892f2 match: move _normalize() into the match class
Matt Harbison <matt_harbison@yahoo.com>
parents: 24636
diff changeset
   301
23549
609ecde2778f match: make 'always' and 'exact' functions, not classes
Martin von Zweigbergk <martinvonz@google.com>
parents: 23480
diff changeset
   302
def exact(root, cwd, files):
609ecde2778f match: make 'always' and 'exact' functions, not classes
Martin von Zweigbergk <martinvonz@google.com>
parents: 23480
diff changeset
   303
    return match(root, cwd, files, exact=True)
8585
bbcd0da50e96 match: redefine always and never in terms of match and exact
Matt Mackall <mpm@selenic.com>
parents: 8584
diff changeset
   304
23549
609ecde2778f match: make 'always' and 'exact' functions, not classes
Martin von Zweigbergk <martinvonz@google.com>
parents: 23480
diff changeset
   305
def always(root, cwd):
609ecde2778f match: make 'always' and 'exact' functions, not classes
Martin von Zweigbergk <martinvonz@google.com>
parents: 23480
diff changeset
   306
    return match(root, cwd, [])
8585
bbcd0da50e96 match: redefine always and never in terms of match and exact
Matt Mackall <mpm@selenic.com>
parents: 8584
diff changeset
   307
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   308
class narrowmatcher(match):
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   309
    """Adapt a matcher to work on a subdirectory only.
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   310
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   311
    The paths are remapped to remove/insert the path as needed:
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   312
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   313
    >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   314
    >>> m2 = narrowmatcher('sub', m1)
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   315
    >>> bool(m2('a.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   316
    False
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   317
    >>> bool(m2('b.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   318
    True
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   319
    >>> bool(m2.matchfn('a.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   320
    False
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   321
    >>> bool(m2.matchfn('b.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   322
    True
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   323
    >>> m2.files()
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   324
    ['b.txt']
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   325
    >>> m2.exact('b.txt')
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   326
    True
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   327
    >>> util.pconvert(m2.rel('b.txt'))
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   328
    'sub/b.txt'
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   329
    >>> def bad(f, msg):
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   330
    ...     print "%s: %s" % (f, msg)
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   331
    >>> m1.bad = bad
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   332
    >>> m2.bad('x.txt', 'No such file')
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   333
    sub/x.txt: No such file
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   334
    >>> m2.abs('c.txt')
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   335
    'sub/c.txt'
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   336
    """
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   337
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   338
    def __init__(self, path, matcher):
12267
69e43c0515f2 narrowmatcher: fix broken rel method
Martin Geisler <mg@lazybytes.net>
parents: 12165
diff changeset
   339
        self._root = matcher._root
69e43c0515f2 narrowmatcher: fix broken rel method
Martin Geisler <mg@lazybytes.net>
parents: 12165
diff changeset
   340
        self._cwd = matcher._cwd
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   341
        self._path = path
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   342
        self._matcher = matcher
18713
8728579f6bdc match: more accurately report when we're always going to match
Bryan O'Sullivan <bryano@fb.com>
parents: 17425
diff changeset
   343
        self._always = matcher._always
23480
88d2d77eb981 match: introduce uipath() to properly style a file path
Matt Harbison <matt_harbison@yahoo.com>
parents: 22777
diff changeset
   344
        self._pathrestricted = matcher._pathrestricted
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   345
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   346
        self._files = [f[len(path) + 1:] for f in matcher._files
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   347
                       if f.startswith(path + "/")]
25194
ef4538ba67ef match: explicitly naming a subrepo implies always() for the submatcher
Matt Harbison <matt_harbison@yahoo.com>
parents: 24790
diff changeset
   348
ef4538ba67ef match: explicitly naming a subrepo implies always() for the submatcher
Matt Harbison <matt_harbison@yahoo.com>
parents: 24790
diff changeset
   349
        # If the parent repo had a path to this subrepo and no patterns are
ef4538ba67ef match: explicitly naming a subrepo implies always() for the submatcher
Matt Harbison <matt_harbison@yahoo.com>
parents: 24790
diff changeset
   350
        # specified, this submatcher always matches.
ef4538ba67ef match: explicitly naming a subrepo implies always() for the submatcher
Matt Harbison <matt_harbison@yahoo.com>
parents: 24790
diff changeset
   351
        if not self._always and not matcher._anypats:
25195
472a685a4961 merge with stable
Matt Mackall <mpm@selenic.com>
parents: 25189 25194
diff changeset
   352
            self._always = any(f == path for f in matcher._files)
25194
ef4538ba67ef match: explicitly naming a subrepo implies always() for the submatcher
Matt Harbison <matt_harbison@yahoo.com>
parents: 24790
diff changeset
   353
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   354
        self._anypats = matcher._anypats
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   355
        self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   356
        self._fileroots = set(self._files)
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   357
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   358
    def abs(self, f):
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   359
        return self._matcher.abs(self._path + "/" + f)
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   360
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   361
    def bad(self, f, msg):
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   362
        self._matcher.bad(self._path + "/" + f, msg)
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   363
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   364
    def rel(self, f):
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   365
        return self._matcher.rel(self._path + "/" + f)
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   366
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   367
class icasefsmatcher(match):
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   368
    """A matcher for wdir on case insensitive filesystems, which normalizes the
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   369
    given patterns to the case in the filesystem.
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   370
    """
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   371
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   372
    def __init__(self, root, cwd, patterns, include, exclude, default, auditor,
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   373
                 ctx, listsubrepos=False):
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   374
        init = super(icasefsmatcher, self).__init__
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   375
        self._dsnormalize = ctx.repo().dirstate.normalize
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   376
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   377
        init(root, cwd, patterns, include, exclude, default, auditor=auditor,
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   378
             ctx=ctx, listsubrepos=listsubrepos)
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   379
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   380
        # m.exact(file) must be based off of the actual user input, otherwise
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   381
        # inexact case matches are treated as exact, and not noted without -v.
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   382
        if self._files:
25189
1c8c33eaea0a match: rename _fmap to _fileroots for clarity
Drew Gottlieb <drgott@google.com>
parents: 25188
diff changeset
   383
            self._fileroots = set(_roots(self._kp))
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   384
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   385
    def _normalize(self, patterns, default, root, cwd, auditor):
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   386
        self._kp = super(icasefsmatcher, self)._normalize(patterns, default,
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   387
                                                          root, cwd, auditor)
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   388
        kindpats = []
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   389
        for kind, pats, source in self._kp:
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   390
            if kind not in ('re', 'relre'):  # regex can't be normalized
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   391
                pats = self._dsnormalize(pats)
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   392
            kindpats.append((kind, pats, source))
24790
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   393
        return kindpats
baa11dde8c0e match: add a subclass for dirstate normalizing of the matched patterns
Matt Harbison <matt_harbison@yahoo.com>
parents: 24789
diff changeset
   394
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   395
def patkind(pattern, default=None):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   396
    '''If pattern is 'kind:pat' with a known kind, return kind.'''
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   397
    return _patsplit(pattern, default)[0]
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   398
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   399
def _patsplit(pattern, default):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   400
    """Split a string into the optional pattern kind prefix and the actual
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   401
    pattern."""
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   402
    if ':' in pattern:
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   403
        kind, pat = pattern.split(':', 1)
13218
1f4721de2ca9 match: support reading pattern lists from files
Steve Borho <steve@borho.org>
parents: 12268
diff changeset
   404
        if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   405
                    'listfile', 'listfile0', 'set', 'include', 'subinclude'):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   406
            return kind, pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   407
    return default, pattern
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   408
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   409
def _globre(pat):
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   410
    r'''Convert an extended glob string to a regexp string.
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   411
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   412
    >>> print _globre(r'?')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   413
    .
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   414
    >>> print _globre(r'*')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   415
    [^/]*
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   416
    >>> print _globre(r'**')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   417
    .*
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   418
    >>> print _globre(r'**/a')
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   419
    (?:.*/)?a
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   420
    >>> print _globre(r'a/**/b')
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   421
    a\/(?:.*/)?b
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   422
    >>> print _globre(r'[a*?!^][^b][!c]')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   423
    [a*?!^][\^b][^c]
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   424
    >>> print _globre(r'{a,b}')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   425
    (?:a|b)
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   426
    >>> print _globre(r'.\*\?')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   427
    \.\*\?
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   428
    '''
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   429
    i, n = 0, len(pat)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   430
    res = ''
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   431
    group = 0
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   432
    escape = util.re.escape
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   433
    def peek():
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   434
        return i < n and pat[i]
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   435
    while i < n:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   436
        c = pat[i]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   437
        i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   438
        if c not in '*?[{},\\':
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   439
            res += escape(c)
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   440
        elif c == '*':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   441
            if peek() == '*':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   442
                i += 1
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   443
                if peek() == '/':
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   444
                    i += 1
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   445
                    res += '(?:.*/)?'
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   446
                else:
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   447
                    res += '.*'
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   448
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   449
                res += '[^/]*'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   450
        elif c == '?':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   451
            res += '.'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   452
        elif c == '[':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   453
            j = i
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   454
            if j < n and pat[j] in '!]':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   455
                j += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   456
            while j < n and pat[j] != ']':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   457
                j += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   458
            if j >= n:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   459
                res += '\\['
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   460
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   461
                stuff = pat[i:j].replace('\\','\\\\')
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   462
                i = j + 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   463
                if stuff[0] == '!':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   464
                    stuff = '^' + stuff[1:]
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   465
                elif stuff[0] == '^':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   466
                    stuff = '\\' + stuff
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   467
                res = '%s[%s]' % (res, stuff)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   468
        elif c == '{':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   469
            group += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   470
            res += '(?:'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   471
        elif c == '}' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   472
            res += ')'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   473
            group -= 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   474
        elif c == ',' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   475
            res += '|'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   476
        elif c == '\\':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   477
            p = peek()
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   478
            if p:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   479
                i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   480
                res += escape(p)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   481
            else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   482
                res += escape(c)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   483
        else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   484
            res += escape(c)
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   485
    return res
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   486
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   487
def _regex(kind, pat, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   488
    '''Convert a (normalized) pattern of any kind into a regular expression.
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   489
    globsuffix is appended to the regexp of globs.'''
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   490
    if not pat:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   491
        return ''
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   492
    if kind == 're':
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   493
        return pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   494
    if kind == 'path':
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   495
        return '^' + util.re.escape(pat) + '(?:/|$)'
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   496
    if kind == 'relglob':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   497
        return '(?:|.*/)' + _globre(pat) + globsuffix
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   498
    if kind == 'relpath':
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   499
        return util.re.escape(pat) + '(?:/|$)'
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   500
    if kind == 'relre':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   501
        if pat.startswith('^'):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   502
            return pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   503
        return '.*' + pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   504
    return _globre(pat) + globsuffix
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   505
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   506
def _buildmatch(ctx, kindpats, globsuffix, listsubrepos, root):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   507
    '''Return regexp string and a matcher function for kindpats.
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   508
    globsuffix is appended to the regexp of globs.'''
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   509
    matchfuncs = []
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   510
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   511
    subincludes, kindpats = _expandsubinclude(kindpats, root)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   512
    if subincludes:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   513
        def matchsubinclude(f):
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   514
            for prefix, mf in subincludes:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   515
                if f.startswith(prefix) and mf(f[len(prefix):]):
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   516
                    return True
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   517
            return False
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   518
        matchfuncs.append(matchsubinclude)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   519
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   520
    fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   521
    if fset:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   522
        matchfuncs.append(fset.__contains__)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   523
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   524
    regex = ''
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   525
    if kindpats:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   526
        regex, mf = _buildregexmatch(kindpats, globsuffix)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   527
        matchfuncs.append(mf)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   528
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   529
    if len(matchfuncs) == 1:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   530
        return regex, matchfuncs[0]
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   531
    else:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   532
        return regex, lambda f: any(mf(f) for mf in matchfuncs)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   533
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   534
def _buildregexmatch(kindpats, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   535
    """Build a match function from a list of kinds and kindpats,
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   536
    return regexp string and a matcher function."""
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   537
    try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   538
        regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   539
                                     for (k, p, s) in kindpats])
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   540
        if len(regex) > 20000:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16645
diff changeset
   541
            raise OverflowError
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   542
        return regex, _rematcher(regex)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   543
    except OverflowError:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   544
        # We're using a Python with a tiny regex engine and we
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   545
        # made it explode, so we'll divide the pattern list in two
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   546
        # until it works
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   547
        l = len(kindpats)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   548
        if l < 2:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   549
            raise
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   550
        regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   551
        regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
21191
a2f4ea82d6d3 match: fix NameError 'pat' on overflow of regex pattern length
Yuya Nishihara <yuya@tcha.org>
parents: 21113
diff changeset
   552
        return regex, lambda s: a(s) or b(s)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   553
    except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   554
        for k, p, s in kindpats:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   555
            try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   556
                _rematcher('(?:%s)' % _regex(k, p, globsuffix))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   557
            except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   558
                if s:
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   559
                    raise util.Abort(_("%s: invalid pattern (%s): %s") %
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   560
                                     (s, k, p))
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   561
                else:
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   562
                    raise util.Abort(_("invalid pattern (%s): %s") % (k, p))
12133
b046b90c4ae5 match: mark error messages for translation
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   563
        raise util.Abort(_("invalid pattern"))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   564
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   565
def _roots(kindpats):
21079
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   566
    '''return roots and exact explicitly listed files from patterns
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   567
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   568
    >>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')])
21079
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   569
    ['g', 'g', '.']
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   570
    >>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
21079
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   571
    ['r', 'p/p', '.']
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   572
    >>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
21079
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   573
    ['.', '.', '.']
b02ab6486a78 match: make it more clear what _roots do and that it ends up in match()._files
Mads Kiilerich <madski@unity3d.com>
parents: 20401
diff changeset
   574
    '''
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   575
    r = []
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   576
    for kind, pat, source in kindpats:
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   577
        if kind == 'glob': # find the non-glob prefix
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   578
            root = []
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   579
            for p in pat.split('/'):
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   580
                if '[' in p or '{' in p or '*' in p or '?' in p:
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   581
                    break
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   582
                root.append(p)
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   583
            r.append('/'.join(root) or '.')
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   584
        elif kind in ('relpath', 'path'):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   585
            r.append(pat or '.')
19107
fcf08023c011 match: fix root calculation for combining regexps with simple paths
Mads Kiilerich <madski@unity3d.com>
parents: 18713
diff changeset
   586
        else: # relglob, re, relre
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   587
            r.append('.')
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   588
    return r
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   589
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   590
def _anypats(kindpats):
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   591
    for kind, pat, source in kindpats:
16182
bd12ef347680 match: consider filesets as "anypats"
Patrick Mezard <patrick@mezard.eu>
parents: 15029
diff changeset
   592
        if kind in ('glob', 're', 'relglob', 'relre', 'set'):
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   593
            return True
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   594
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   595
_commentre = None
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   596
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   597
def readpatternfile(filepath, warn):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   598
    '''parse a pattern file, returning a list of
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   599
    patterns. These patterns should be given to compile()
25216
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   600
    to be validated and converted into a match function.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   601
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   602
    trailing white space is dropped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   603
    the escape character is backslash.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   604
    comments start with #.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   605
    empty lines are skipped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   606
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   607
    lines can be of the following formats:
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   608
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   609
    syntax: regexp # defaults following lines to non-rooted regexps
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   610
    syntax: glob   # defaults following lines to non-rooted globs
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   611
    re:pattern     # non-rooted regular expression
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   612
    glob:pattern   # non-rooted glob
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   613
    pattern        # pattern of the current default type'''
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   614
25215
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   615
    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   616
                'include': 'include', 'subinclude': 'subinclude'}
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   617
    syntax = 'relre:'
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   618
    patterns = []
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   619
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   620
    fp = open(filepath)
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   621
    for line in fp:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   622
        if "#" in line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   623
            global _commentre
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   624
            if not _commentre:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   625
                _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   626
            # remove comments prefixed by an even number of escapes
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   627
            line = _commentre.sub(r'\1', line)
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   628
            # fixup properly escaped comments that survived the above
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   629
            line = line.replace("\\#", "#")
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   630
        line = line.rstrip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   631
        if not line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   632
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   633
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   634
        if line.startswith('syntax:'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   635
            s = line[7:].strip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   636
            try:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   637
                syntax = syntaxes[s]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   638
            except KeyError:
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
   639
                if warn:
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
   640
                    warn(_("%s: ignoring invalid syntax '%s'\n") %
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
   641
                         (filepath, s))
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   642
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   643
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   644
        linesyntax = syntax
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   645
        for s, rels in syntaxes.iteritems():
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   646
            if line.startswith(rels):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   647
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   648
                line = line[len(rels):]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   649
                break
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   650
            elif line.startswith(s+':'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   651
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   652
                line = line[len(s) + 1:]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   653
                break
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   654
        patterns.append(linesyntax + line)
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   655
    fp.close()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   656
    return patterns