mercurial/match.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 06 Jul 2017 17:39:24 -0700
changeset 33319 3c84591e7321
parent 33306 a9808bd1449e
child 33357 a21819f439fe
permissions -rw-r--r--
match: move matchers from sparse into core The sparse extension contains some matcher types that are generic and can exist in core. As part of the move, the classes now inherit from basematcher. always(), files(), and isexact() have been dropped because they match the default implementations in basematcher.
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
25958
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
     8
from __future__ import absolute_import
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
     9
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    10
import copy
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    11
import os
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    12
import re
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    13
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    14
from .i18n import _
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    15
from . import (
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
    16
    error,
25958
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    17
    pathutil,
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    18
    util,
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    19
)
6576
69f3e9ac7c56 walk: introduce match objects
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    21
propertycache = util.propertycache
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    22
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    23
def _rematcher(regex):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    24
    '''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
    25
    matcher function'''
21909
335bb8b80443 match: use util.re.compile instead of util.compilere
Siddharth Agarwal <sid0@fb.com>
parents: 21815
diff changeset
    26
    m = util.re.compile(regex)
16943
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    27
    try:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    28
        # 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
    29
        return m.test_match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    30
    except AttributeError:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    31
        return m.match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    32
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    33
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
    34
    '''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
    35
    fset = set()
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    36
    other = []
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    37
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    38
    for kind, pat, source in kindpats:
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    39
        if kind == 'set':
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    40
            if not ctx:
32444
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32415
diff changeset
    41
                raise error.ProgrammingError("fileset expression with no "
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32415
diff changeset
    42
                                             "context")
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    43
            s = ctx.getfileset(pat)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    44
            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
    45
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    46
            if listsubrepos:
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    47
                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
    48
                    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
    49
                    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
    50
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    51
            continue
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    52
        other.append((kind, pat, source))
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    53
    return fset, other
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    54
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    55
def _expandsubinclude(kindpats, root):
32132
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
    56
    '''Returns the list of subinclude matcher args and the kindpats without the
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    57
    subincludes in it.'''
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    58
    relmatchers = []
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    59
    other = []
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    60
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    61
    for kind, pat, source in kindpats:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    62
        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
    63
            sourceroot = pathutil.dirname(util.normpath(source))
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    64
            pat = util.pconvert(pat)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    65
            path = pathutil.join(sourceroot, pat)
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
            newroot = pathutil.dirname(path)
32132
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
    68
            matcherargs = (newroot, '', [], ['include:%s' % path])
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    69
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    70
            prefix = pathutil.canonpath(root, root, newroot)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    71
            if prefix:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    72
                prefix += '/'
32132
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
    73
            relmatchers.append((prefix, matcherargs))
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    74
        else:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    75
            other.append((kind, pat, source))
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    76
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    77
    return relmatchers, other
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    78
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    79
def _kindpatsalwaysmatch(kindpats):
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    80
    """"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
    81
    'relpath:.' does.
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    82
    """
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    83
    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
    84
        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
    85
            return False
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    86
    return True
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    87
32728
3e8eb6d84a5c match: allow pats to be None
Martin von Zweigbergk <martinvonz@google.com>
parents: 32650
diff changeset
    88
def match(root, cwd, patterns=None, include=None, exclude=None, default='glob',
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    89
          exact=False, auditor=None, ctx=None, listsubrepos=False, warn=None,
32401
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
    90
          badfn=None, icasefs=False):
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    91
    """build an object to match a set of file patterns
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    92
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    93
    arguments:
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    94
    root - the canonical root of the tree you're matching against
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    95
    cwd - the current working directory, if relevant
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    96
    patterns - patterns to find
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    97
    include - patterns to include (unless they are excluded)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    98
    exclude - patterns to exclude (even if they are included)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
    99
    default - if a pattern in patterns has no explicit type, assume this one
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   100
    exact - patterns are actually filenames (include/exclude still apply)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   101
    warn - optional function used for printing warnings
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   102
    badfn - optional bad() callback for this matcher instead of the default
32401
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   103
    icasefs - make a matcher for wdir on case insensitive filesystems, which
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   104
        normalizes the given patterns to the case in the filesystem
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   105
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   106
    a pattern is one of:
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   107
    'glob:<glob>' - a glob relative to cwd
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   108
    're:<regexp>' - a regular expression
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   109
    'path:<path>' - a path relative to repository root, which is matched
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   110
                    recursively
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   111
    'rootfilesin:<path>' - a path relative to repository root, which is
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   112
                    matched non-recursively (will not match subdirectories)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   113
    'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   114
    'relpath:<path>' - a path relative to cwd
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   115
    'relre:<regexp>' - a regexp that needn't match the start of a name
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   116
    'set:<fileset>' - a fileset expression
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   117
    'include:<path>' - a file of patterns to read and include
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   118
    'subinclude:<path>' - a file of patterns to match against files under
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   119
                          the same directory
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   120
    '<something>' - a pattern of the specified default type
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   121
    """
32401
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   122
    normalize = _donormalize
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   123
    if icasefs:
32415
9695aca1a3a0 match: catch attempts to create case-insenstive exact matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32406
diff changeset
   124
        if exact:
32444
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32415
diff changeset
   125
            raise error.ProgrammingError("a case-insensitive exact matcher "
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32415
diff changeset
   126
                                         "doesn't make sense")
32401
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   127
        dirstate = ctx.repo().dirstate
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   128
        dsnormalize = dirstate.normalize
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   129
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   130
        def normalize(patterns, default, root, cwd, auditor, warn):
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   131
            kp = _donormalize(patterns, default, root, cwd, auditor, warn)
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   132
            kindpats = []
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   133
            for kind, pats, source in kp:
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   134
                if kind not in ('re', 'relre'):  # regex can't be normalized
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   135
                    p = pats
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   136
                    pats = dsnormalize(pats)
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   137
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   138
                    # Preserve the original to handle a case only rename.
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   139
                    if p != pats and p in dirstate:
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   140
                        kindpats.append((kind, p, source))
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   141
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   142
                kindpats.append((kind, pats, source))
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   143
            return kindpats
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32400
diff changeset
   144
32499
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   145
    if exact:
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   146
        m = exactmatcher(root, cwd, patterns, badfn)
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   147
    elif patterns:
32556
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   148
        kindpats = normalize(patterns, default, root, cwd, auditor, warn)
32557
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   149
        if _kindpatsalwaysmatch(kindpats):
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   150
            m = alwaysmatcher(root, cwd, badfn, relativeuipath=True)
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   151
        else:
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   152
            m = patternmatcher(root, cwd, kindpats, ctx=ctx,
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   153
                               listsubrepos=listsubrepos, badfn=badfn)
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   154
    else:
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   155
        # It's a little strange that no patterns means to match everything.
32650
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32605
diff changeset
   156
        # Consider changing this to match nothing (probably using nevermatcher).
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   157
        m = alwaysmatcher(root, cwd, badfn)
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   158
32497
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   159
    if include:
32556
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   160
        kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   161
        im = includematcher(root, cwd, kindpats, ctx=ctx,
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   162
                            listsubrepos=listsubrepos, badfn=None)
32497
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   163
        m = intersectmatchers(m, im)
32465
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   164
    if exclude:
32556
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   165
        kindpats = normalize(exclude, 'glob', root, cwd, auditor, warn)
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   166
        em = includematcher(root, cwd, kindpats, ctx=ctx,
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   167
                            listsubrepos=listsubrepos, badfn=None)
32465
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   168
        m = differencematcher(m, em)
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   169
    return m
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   170
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   171
def exact(root, cwd, files, badfn=None):
32499
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   172
    return exactmatcher(root, cwd, files, badfn=badfn)
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   173
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   174
def always(root, cwd):
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   175
    return alwaysmatcher(root, cwd)
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   176
32605
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   177
def never(root, cwd):
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   178
    return nevermatcher(root, cwd)
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   179
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   180
def badmatch(match, badfn):
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   181
    """Make a copy of the given matcher, replacing its bad method with the given
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   182
    one.
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   183
    """
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   184
    m = copy.copy(match)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   185
    m.bad = badfn
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   186
    return m
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   187
32397
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   188
def _donormalize(patterns, default, root, cwd, auditor, warn):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   189
    '''Convert 'kind:pat' from the patterns list to tuples with kind and
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   190
    normalized and rooted patterns and with listfiles expanded.'''
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   191
    kindpats = []
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   192
    for kind, pat in [_patsplit(p, default) for p in patterns]:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   193
        if kind in ('glob', 'relpath'):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   194
            pat = pathutil.canonpath(root, cwd, pat, auditor)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   195
        elif kind in ('relglob', 'path', 'rootfilesin'):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   196
            pat = util.normpath(pat)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   197
        elif kind in ('listfile', 'listfile0'):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   198
            try:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   199
                files = util.readfile(pat)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   200
                if kind == 'listfile0':
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   201
                    files = files.split('\0')
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   202
                else:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   203
                    files = files.splitlines()
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   204
                files = [f for f in files if f]
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   205
            except EnvironmentError:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   206
                raise error.Abort(_("unable to read file list (%s)") % pat)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   207
            for k, p, source in _donormalize(files, default, root, cwd,
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   208
                                             auditor, warn):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   209
                kindpats.append((k, p, pat))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   210
            continue
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   211
        elif kind == 'include':
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   212
            try:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   213
                fullpath = os.path.join(root, util.localpath(pat))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   214
                includepats = readpatternfile(fullpath, warn)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   215
                for k, p, source in _donormalize(includepats, default,
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   216
                                                 root, cwd, auditor, warn):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   217
                    kindpats.append((k, p, source or pat))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   218
            except error.Abort as inst:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   219
                raise error.Abort('%s: %s' % (pat, inst[0]))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   220
            except IOError as inst:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   221
                if warn:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   222
                    warn(_("skipping unreadable pattern file '%s': %s\n") %
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   223
                         (pat, inst.strerror))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   224
            continue
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   225
        # else: re or relre - which cannot be normalized
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   226
        kindpats.append((kind, pat, ''))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   227
    return kindpats
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32396
diff changeset
   228
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   229
class basematcher(object):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   230
32496
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32466
diff changeset
   231
    def __init__(self, root, cwd, badfn=None, relativeuipath=True):
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   232
        self._root = root
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   233
        self._cwd = cwd
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   234
        if badfn is not None:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   235
            self.bad = badfn
32496
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32466
diff changeset
   236
        self._relativeuipath = relativeuipath
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   237
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   238
    def __call__(self, fn):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   239
        return self.matchfn(fn)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   240
    def __iter__(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   241
        for f in self._files:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   242
            yield f
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   243
    # Callbacks related to how the matcher is used by dirstate.walk.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   244
    # Subscribers to these events must monkeypatch the matcher object.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   245
    def bad(self, f, msg):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   246
        '''Callback from dirstate.walk for each explicit file that can't be
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   247
        found/accessed, with an error message.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   248
        pass
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   249
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   250
    # If an explicitdir is set, it will be called when an explicitly listed
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   251
    # directory is visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   252
    explicitdir = None
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   253
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   254
    # If an traversedir is set, it will be called when a directory discovered
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   255
    # by recursive traversal is visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   256
    traversedir = None
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   257
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   258
    def abs(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   259
        '''Convert a repo path back to path that is relative to the root of the
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   260
        matcher.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   261
        return f
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   262
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   263
    def rel(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   264
        '''Convert repo path back to path that is relative to cwd of matcher.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   265
        return util.pathto(self._root, self._cwd, f)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   266
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   267
    def uipath(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   268
        '''Convert repo path to a display path.  If patterns or -I/-X were used
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   269
        to create this matcher, the display path will be relative to cwd.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   270
        Otherwise it is relative to the root of the repo.'''
32496
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32466
diff changeset
   271
        return (self._relativeuipath and self.rel(f)) or self.abs(f)
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   272
32459
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32458
diff changeset
   273
    @propertycache
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32458
diff changeset
   274
    def _files(self):
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32458
diff changeset
   275
        return []
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32458
diff changeset
   276
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   277
    def files(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   278
        '''Explicitly listed files or patterns or roots:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   279
        if no patterns or .always(): empty list,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   280
        if exact: list exact files,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   281
        if not .anypats(): list all files and dirs,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   282
        else: optimal roots'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   283
        return self._files
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   284
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   285
    @propertycache
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   286
    def _fileset(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   287
        return set(self._files)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   288
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   289
    def exact(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   290
        '''Returns True if f is in .files().'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   291
        return f in self._fileset
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   292
32463
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32461
diff changeset
   293
    def matchfn(self, f):
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32461
diff changeset
   294
        return False
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32461
diff changeset
   295
32458
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   296
    def visitdir(self, dir):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   297
        '''Decides whether a directory should be visited based on whether it
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   298
        has potential matches in it or one of its subdirectories. This is
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   299
        based on the match's primary, included, and excluded patterns.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   300
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   301
        Returns the string 'all' if the given directory and all subdirectories
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   302
        should be visited. Otherwise returns True or False indicating whether
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   303
        the given directory should be visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   304
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   305
        This function's behavior is undefined if it has returned False for
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   306
        one of the dir's parent directories.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   307
        '''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   308
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   309
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   310
    def anypats(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   311
        '''Matcher uses patterns or include/exclude.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   312
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   313
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   314
    def always(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   315
        '''Matcher will match everything and .files() will be empty
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   316
        - optimization might be possible and necessary.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   317
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   318
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   319
    def isexact(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   320
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   321
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   322
    def prefix(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   323
        return not self.always() and not self.isexact() and not self.anypats()
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   324
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   325
class alwaysmatcher(basematcher):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   326
    '''Matches everything.'''
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   327
32557
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   328
    def __init__(self, root, cwd, badfn=None, relativeuipath=False):
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   329
        super(alwaysmatcher, self).__init__(root, cwd, badfn,
32557
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   330
                                            relativeuipath=relativeuipath)
32553
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   331
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   332
    def always(self):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   333
        return True
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   334
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   335
    def matchfn(self, f):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   336
        return True
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   337
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   338
    def visitdir(self, dir):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   339
        return 'all'
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   340
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   341
    def __repr__(self):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   342
        return '<alwaysmatcher>'
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32552
diff changeset
   343
32605
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   344
class nevermatcher(basematcher):
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   345
    '''Matches nothing.'''
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   346
32650
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32605
diff changeset
   347
    def __init__(self, root, cwd, badfn=None):
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32605
diff changeset
   348
        super(nevermatcher, self).__init__(root, cwd, badfn)
32605
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   349
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   350
    def __repr__(self):
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   351
        return '<nevermatcher>'
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32557
diff changeset
   352
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   353
class patternmatcher(basematcher):
32395
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32325
diff changeset
   354
32556
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   355
    def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False,
32504
2ba4d3b74ba8 match: remove support for includes from patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32503
diff changeset
   356
                 badfn=None):
32555
b3083be7dcb9 match: drop support for empty pattern list in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32554
diff changeset
   357
        super(patternmatcher, self).__init__(root, cwd, badfn)
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   358
32557
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   359
        self._files = _explicitfiles(kindpats)
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32556
diff changeset
   360
        self._anypats = _anypats(kindpats)
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   361
        self._pats, self.matchfn = _buildmatch(ctx, kindpats, '$', listsubrepos,
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   362
                                               root)
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   363
32322
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32312
diff changeset
   364
    @propertycache
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   365
    def _dirs(self):
32322
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32312
diff changeset
   366
        return set(util.dirs(self._fileset)) | {'.'}
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   367
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   368
    def visitdir(self, dir):
32322
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32312
diff changeset
   369
        if self.prefix() and dir in self._fileset:
27343
c59647c6694d treemanifest: don't iterate entire matching submanifests on match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 27327
diff changeset
   370
            return 'all'
32554
f44ea253ffe2 match: optimize visitdir() for when no explicit files are listed
Martin von Zweigbergk <martinvonz@google.com>
parents: 32553
diff changeset
   371
        return ('.' in self._fileset or
32322
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32312
diff changeset
   372
                dir in self._fileset or
25576
d02f4b3e71f5 match: break boolean expressions into one operand per line
Martin von Zweigbergk <martinvonz@google.com>
parents: 25575
diff changeset
   373
                dir in self._dirs or
32322
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32312
diff changeset
   374
                any(parentdir in self._fileset
25577
a410479c7ee7 match: drop optimization (?) of 'parentdirs' calculation
Martin von Zweigbergk <martinvonz@google.com>
parents: 25576
diff changeset
   375
                    for parentdir in util.finddirs(dir)))
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   376
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   377
    def anypats(self):
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   378
        return self._anypats
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   379
32406
952017471f93 match: implement __repr__() and update users (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32401
diff changeset
   380
    def __repr__(self):
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   381
        return ('<patternmatcher patterns=%r>' % self._pats)
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   382
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   383
class includematcher(basematcher):
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   384
32556
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   385
    def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False,
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32555
diff changeset
   386
                 badfn=None):
32502
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   387
        super(includematcher, self).__init__(root, cwd, badfn)
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   388
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   389
        self._pats, self.matchfn = _buildmatch(ctx, kindpats, '(?:/|$)',
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   390
                                               listsubrepos, root)
32503
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   391
        self._anypats = _anypats(kindpats)
32502
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   392
        roots, dirs = _rootsanddirs(kindpats)
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   393
        # roots are directories which are recursively included.
32503
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   394
        self._roots = set(roots)
32502
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   395
        # dirs are directories which are non-recursively included.
32503
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   396
        self._dirs = set(dirs)
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   397
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   398
    def visitdir(self, dir):
32503
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   399
        if not self._anypats and dir in self._roots:
32502
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   400
            # The condition above is essentially self.prefix() for includes
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   401
            return 'all'
32503
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   402
        return ('.' in self._roots or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   403
                dir in self._roots or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   404
                dir in self._dirs or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   405
                any(parentdir in self._roots
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32502
diff changeset
   406
                    for parentdir in util.finddirs(dir)))
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   407
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   408
    def anypats(self):
32502
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32501
diff changeset
   409
        return True
32501
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   410
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   411
    def __repr__(self):
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32728
diff changeset
   412
        return ('<includematcher includes=%r>' % self._pats)
32406
952017471f93 match: implement __repr__() and update users (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32401
diff changeset
   413
32499
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   414
class exactmatcher(basematcher):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   415
    '''Matches the input files exactly. They are interpreted as paths, not
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   416
    patterns (so no kind-prefixes).
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   417
    '''
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   418
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   419
    def __init__(self, root, cwd, files, badfn=None):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   420
        super(exactmatcher, self).__init__(root, cwd, badfn)
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   421
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   422
        if isinstance(files, list):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   423
            self._files = files
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   424
        else:
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   425
            self._files = list(files)
32543
cf7c88986e9f match: define exactmatcher.matchfn statically
Yuya Nishihara <yuya@tcha.org>
parents: 32542
diff changeset
   426
cf7c88986e9f match: define exactmatcher.matchfn statically
Yuya Nishihara <yuya@tcha.org>
parents: 32542
diff changeset
   427
    matchfn = basematcher.exact
32499
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   428
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   429
    @propertycache
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   430
    def _dirs(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   431
        return set(util.dirs(self._fileset)) | {'.'}
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   432
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   433
    def visitdir(self, dir):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   434
        return dir in self._dirs
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   435
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   436
    def isexact(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   437
        return True
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   438
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   439
    def __repr__(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   440
        return ('<exactmatcher files=%r>' % self._files)
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   441
32465
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   442
class differencematcher(basematcher):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   443
    '''Composes two matchers by matching if the first matches and the second
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   444
    does not. Well, almost... If the user provides a pattern like "-X foo foo",
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   445
    Mercurial actually does match "foo" against that. That's because exact
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   446
    matches are treated specially. So, since this differencematcher is used for
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   447
    excludes, it needs to special-case exact matching.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   448
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   449
    The second matcher's non-matching-attributes (root, cwd, bad, explicitdir,
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   450
    traversedir) are ignored.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   451
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   452
    TODO: If we want to keep the behavior described above for exact matches, we
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   453
    should consider instead treating the above case something like this:
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   454
    union(exact(foo), difference(pattern(foo), include(foo)))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   455
    '''
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   456
    def __init__(self, m1, m2):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   457
        super(differencematcher, self).__init__(m1._root, m1._cwd)
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   458
        self._m1 = m1
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   459
        self._m2 = m2
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   460
        self.bad = m1.bad
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   461
        self.explicitdir = m1.explicitdir
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   462
        self.traversedir = m1.traversedir
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   463
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   464
    def matchfn(self, f):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   465
        return self._m1(f) and (not self._m2(f) or self._m1.exact(f))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   466
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   467
    @propertycache
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   468
    def _files(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   469
        if self.isexact():
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   470
            return [f for f in self._m1.files() if self(f)]
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   471
        # If m1 is not an exact matcher, we can't easily figure out the set of
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   472
        # files, because its files() are not always files. For example, if
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   473
        # m1 is "path:dir" and m2 is "rootfileins:.", we don't
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   474
        # want to remove "dir" from the set even though it would match m2,
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   475
        # because the "dir" in m1 may not be a file.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   476
        return self._m1.files()
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   477
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   478
    def visitdir(self, dir):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   479
        if self._m2.visitdir(dir) == 'all':
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   480
            # There's a bug here: If m1 matches file 'dir/file' and m2 excludes
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   481
            # 'dir' (recursively), we should still visit 'dir' due to the
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   482
            # exception we have for exact matches.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   483
            return False
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   484
        return bool(self._m1.visitdir(dir))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   485
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   486
    def isexact(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   487
        return self._m1.isexact()
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   488
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   489
    def anypats(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   490
        return self._m1.anypats() or self._m2.anypats()
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   491
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   492
    def __repr__(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   493
        return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32464
diff changeset
   494
32497
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   495
def intersectmatchers(m1, m2):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   496
    '''Composes two matchers by matching if both of them match.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   497
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   498
    The second matcher's non-matching-attributes (root, cwd, bad, explicitdir,
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   499
    traversedir) are ignored.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   500
    '''
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   501
    if m1 is None or m2 is None:
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   502
        return m1 or m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   503
    if m1.always():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   504
        m = copy.copy(m2)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   505
        # TODO: Consider encapsulating these things in a class so there's only
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   506
        # one thing to copy from m1.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   507
        m.bad = m1.bad
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   508
        m.explicitdir = m1.explicitdir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   509
        m.traversedir = m1.traversedir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   510
        m.abs = m1.abs
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   511
        m.rel = m1.rel
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   512
        m._relativeuipath |= m1._relativeuipath
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   513
        return m
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   514
    if m2.always():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   515
        m = copy.copy(m1)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   516
        m._relativeuipath |= m2._relativeuipath
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   517
        return m
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   518
    return intersectionmatcher(m1, m2)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   519
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   520
class intersectionmatcher(basematcher):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   521
    def __init__(self, m1, m2):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   522
        super(intersectionmatcher, self).__init__(m1._root, m1._cwd)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   523
        self._m1 = m1
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   524
        self._m2 = m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   525
        self.bad = m1.bad
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   526
        self.explicitdir = m1.explicitdir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   527
        self.traversedir = m1.traversedir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   528
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   529
    @propertycache
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   530
    def _files(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   531
        if self.isexact():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   532
            m1, m2 = self._m1, self._m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   533
            if not m1.isexact():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   534
                m1, m2 = m2, m1
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   535
            return [f for f in m1.files() if m2(f)]
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   536
        # It neither m1 nor m2 is an exact matcher, we can't easily intersect
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   537
        # the set of files, because their files() are not always files. For
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   538
        # example, if intersecting a matcher "-I glob:foo.txt" with matcher of
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   539
        # "path:dir2", we don't want to remove "dir2" from the set.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   540
        return self._m1.files() + self._m2.files()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   541
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   542
    def matchfn(self, f):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   543
        return self._m1(f) and self._m2(f)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   544
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   545
    def visitdir(self, dir):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   546
        visit1 = self._m1.visitdir(dir)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   547
        if visit1 == 'all':
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   548
            return self._m2.visitdir(dir)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   549
        # bool() because visit1=True + visit2='all' should not be 'all'
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   550
        return bool(visit1 and self._m2.visitdir(dir))
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   551
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   552
    def always(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   553
        return self._m1.always() and self._m2.always()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   554
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   555
    def isexact(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   556
        return self._m1.isexact() or self._m2.isexact()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   557
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   558
    def anypats(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   559
        return self._m1.anypats() or self._m2.anypats()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   560
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   561
    def __repr__(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   562
        return ('<intersectionmatcher m1=%r, m2=%r>' % (self._m1, self._m2))
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32496
diff changeset
   563
32460
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   564
class subdirmatcher(basematcher):
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   565
    """Adapt a matcher to work on a subdirectory only.
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   566
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   567
    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
   568
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   569
    >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
28017
d3f1b7ee5e70 match: rename "narrowmatcher" to "subdirmatcher" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 27595
diff changeset
   570
    >>> m2 = subdirmatcher('sub', m1)
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   571
    >>> bool(m2('a.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   572
    False
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   573
    >>> bool(m2('b.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   574
    True
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   575
    >>> bool(m2.matchfn('a.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   576
    False
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   577
    >>> bool(m2.matchfn('b.txt'))
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   578
    True
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   579
    >>> m2.files()
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   580
    ['b.txt']
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   581
    >>> m2.exact('b.txt')
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   582
    True
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   583
    >>> util.pconvert(m2.rel('b.txt'))
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   584
    'sub/b.txt'
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   585
    >>> def bad(f, msg):
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   586
    ...     print "%s: %s" % (f, msg)
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   587
    >>> m1.bad = bad
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   588
    >>> m2.bad('x.txt', 'No such file')
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   589
    sub/x.txt: No such file
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   590
    >>> m2.abs('c.txt')
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   591
    'sub/c.txt'
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   592
    """
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   593
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   594
    def __init__(self, path, matcher):
32460
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   595
        super(subdirmatcher, self).__init__(matcher._root, matcher._cwd)
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   596
        self._path = path
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   597
        self._matcher = matcher
32460
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   598
        self._always = matcher.always()
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   599
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   600
        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
   601
                       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
   602
32325
763d72925691 match: use match.prefix() in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32324
diff changeset
   603
        # If the parent repo had a path to this subrepo and the matcher is
763d72925691 match: use match.prefix() in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32324
diff changeset
   604
        # a prefix matcher, this submatcher always matches.
763d72925691 match: use match.prefix() in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32324
diff changeset
   605
        if matcher.prefix():
25195
472a685a4961 merge with stable
Matt Mackall <mpm@selenic.com>
parents: 25189 25194
diff changeset
   606
            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
   607
32324
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   608
    def bad(self, f, msg):
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   609
        self._matcher.bad(self._path + "/" + f, msg)
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   610
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   611
    def abs(self, f):
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   612
        return self._matcher.abs(self._path + "/" + f)
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   613
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   614
    def rel(self, f):
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   615
        return self._matcher.rel(self._path + "/" + f)
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   616
32324
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   617
    def uipath(self, f):
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   618
        return self._matcher.uipath(self._path + "/" + f)
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32323
diff changeset
   619
32464
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   620
    def matchfn(self, f):
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   621
        # Some information is lost in the superclass's constructor, so we
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   622
        # can not accurately create the matching function for the subdirectory
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   623
        # from the inputs. Instead, we override matchfn() and visitdir() to
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   624
        # call the original matcher with the subdirectory path prepended.
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   625
        return self._matcher.matchfn(self._path + "/" + f)
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32463
diff changeset
   626
32323
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   627
    def visitdir(self, dir):
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   628
        if dir == '.':
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   629
            dir = self._path
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   630
        else:
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   631
            dir = self._path + "/" + dir
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   632
        return self._matcher.visitdir(dir)
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32322
diff changeset
   633
32460
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   634
    def always(self):
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   635
        return self._always
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   636
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   637
    def anypats(self):
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   638
        return self._matcher.anypats()
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32459
diff changeset
   639
32552
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32543
diff changeset
   640
    def __repr__(self):
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32543
diff changeset
   641
        return ('<subdirmatcher path=%r, matcher=%r>' %
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32543
diff changeset
   642
                (self._path, self._matcher))
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32543
diff changeset
   643
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   644
class forceincludematcher(basematcher):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   645
    """A matcher that returns true for any of the forced includes before testing
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   646
    against the actual matcher."""
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   647
    def __init__(self, matcher, includes):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   648
        self._matcher = matcher
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   649
        self._includes = includes
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   650
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   651
    def __call__(self, value):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   652
        return value in self._includes or self._matcher(value)
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   653
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   654
    def anypats(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   655
        return True
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   656
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   657
    def prefix(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   658
        return False
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   659
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   660
    def __repr__(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   661
        return ('<forceincludematcher matcher=%r, includes=%r>' %
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   662
                (self._matcher, sorted(self._includes)))
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   663
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   664
class unionmatcher(basematcher):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   665
    """A matcher that is the union of several matchers."""
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   666
    def __init__(self, matchers):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   667
        self._matchers = matchers
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   668
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   669
    def __call__(self, value):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   670
        for match in self._matchers:
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   671
            if match(value):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   672
                return True
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   673
        return False
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   674
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   675
    def anypats(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   676
        return True
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   677
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   678
    def prefix(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   679
        return False
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   680
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   681
    def __repr__(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   682
        return ('<unionmatcher matchers=%r>' % self._matchers)
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   683
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   684
class negatematcher(basematcher):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   685
    def __init__(self, matcher):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   686
        self._matcher = matcher
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   687
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   688
    def __call__(self, value):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   689
        return not self._matcher(value)
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   690
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   691
    def anypats(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   692
        return True
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   693
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   694
    def __repr__(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   695
        return ('<negatematcher matcher=%r>' % self._matcher)
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   696
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   697
def patkind(pattern, default=None):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   698
    '''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
   699
    return _patsplit(pattern, default)[0]
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   700
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   701
def _patsplit(pattern, default):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   702
    """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
   703
    pattern."""
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   704
    if ':' in pattern:
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   705
        kind, pat = pattern.split(':', 1)
13218
1f4721de2ca9 match: support reading pattern lists from files
Steve Borho <steve@borho.org>
parents: 12268
diff changeset
   706
        if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
31012
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   707
                    'listfile', 'listfile0', 'set', 'include', 'subinclude',
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   708
                    'rootfilesin'):
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   709
            return kind, pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   710
    return default, pattern
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   711
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   712
def _globre(pat):
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   713
    r'''Convert an extended glob string to a regexp string.
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   714
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   715
    >>> print _globre(r'?')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   716
    .
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   717
    >>> print _globre(r'*')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   718
    [^/]*
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   719
    >>> print _globre(r'**')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   720
    .*
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   721
    >>> print _globre(r'**/a')
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   722
    (?:.*/)?a
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   723
    >>> print _globre(r'a/**/b')
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   724
    a\/(?:.*/)?b
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   725
    >>> print _globre(r'[a*?!^][^b][!c]')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   726
    [a*?!^][\^b][^c]
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   727
    >>> print _globre(r'{a,b}')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   728
    (?:a|b)
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   729
    >>> print _globre(r'.\*\?')
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   730
    \.\*\?
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   731
    '''
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   732
    i, n = 0, len(pat)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   733
    res = ''
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   734
    group = 0
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   735
    escape = util.re.escape
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   736
    def peek():
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   737
        return i < n and pat[i:i + 1]
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   738
    while i < n:
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   739
        c = pat[i:i + 1]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   740
        i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   741
        if c not in '*?[{},\\':
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   742
            res += escape(c)
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   743
        elif c == '*':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   744
            if peek() == '*':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   745
                i += 1
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   746
                if peek() == '/':
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   747
                    i += 1
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   748
                    res += '(?:.*/)?'
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   749
                else:
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   750
                    res += '.*'
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   751
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   752
                res += '[^/]*'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   753
        elif c == '?':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   754
            res += '.'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   755
        elif c == '[':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   756
            j = i
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   757
            if j < n and pat[j:j + 1] in '!]':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   758
                j += 1
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   759
            while j < n and pat[j:j + 1] != ']':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   760
                j += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   761
            if j >= n:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   762
                res += '\\['
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   763
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   764
                stuff = pat[i:j].replace('\\','\\\\')
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   765
                i = j + 1
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   766
                if stuff[0:1] == '!':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   767
                    stuff = '^' + stuff[1:]
31421
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
diff changeset
   768
                elif stuff[0:1] == '^':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   769
                    stuff = '\\' + stuff
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   770
                res = '%s[%s]' % (res, stuff)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   771
        elif c == '{':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   772
            group += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   773
            res += '(?:'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   774
        elif c == '}' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   775
            res += ')'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   776
            group -= 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   777
        elif c == ',' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   778
            res += '|'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   779
        elif c == '\\':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   780
            p = peek()
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   781
            if p:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   782
                i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   783
                res += escape(p)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   784
            else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   785
                res += escape(c)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   786
        else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   787
            res += escape(c)
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   788
    return res
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   789
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   790
def _regex(kind, pat, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   791
    '''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
   792
    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
   793
    if not pat:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   794
        return ''
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   795
    if kind == 're':
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   796
        return pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   797
    if kind == 'path':
25636
bfe9ed85f27c match: let 'path:.' and 'path:' match everything (issue4687)
Matt Harbison <matt_harbison@yahoo.com>
parents: 25194
diff changeset
   798
        if pat == '.':
bfe9ed85f27c match: let 'path:.' and 'path:' match everything (issue4687)
Matt Harbison <matt_harbison@yahoo.com>
parents: 25194
diff changeset
   799
            return ''
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   800
        return '^' + util.re.escape(pat) + '(?:/|$)'
31012
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   801
    if kind == 'rootfilesin':
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   802
        if pat == '.':
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   803
            escaped = ''
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   804
        else:
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   805
            # Pattern is a directory name.
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   806
            escaped = util.re.escape(pat) + '/'
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   807
        # Anything after the pattern must be a non-directory.
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   808
        return '^' + escaped + '[^/]+$'
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   809
    if kind == 'relglob':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   810
        return '(?:|.*/)' + _globre(pat) + globsuffix
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   811
    if kind == 'relpath':
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   812
        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
   813
    if kind == 'relre':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   814
        if pat.startswith('^'):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   815
            return pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   816
        return '.*' + pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   817
    return _globre(pat) + globsuffix
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   818
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   819
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
   820
    '''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
   821
    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
   822
    matchfuncs = []
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   823
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   824
    subincludes, kindpats = _expandsubinclude(kindpats, root)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   825
    if subincludes:
32132
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   826
        submatchers = {}
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   827
        def matchsubinclude(f):
32132
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   828
            for prefix, matcherargs in subincludes:
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   829
                if f.startswith(prefix):
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   830
                    mf = submatchers.get(prefix)
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   831
                    if mf is None:
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   832
                        mf = match(*matcherargs)
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   833
                        submatchers[prefix] = mf
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   834
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   835
                    if mf(f[len(prefix):]):
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31433
diff changeset
   836
                        return True
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   837
            return False
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   838
        matchfuncs.append(matchsubinclude)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   839
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   840
    fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   841
    if fset:
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   842
        matchfuncs.append(fset.__contains__)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   843
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   844
    regex = ''
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   845
    if kindpats:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   846
        regex, mf = _buildregexmatch(kindpats, globsuffix)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   847
        matchfuncs.append(mf)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   848
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   849
    if len(matchfuncs) == 1:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   850
        return regex, matchfuncs[0]
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   851
    else:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   852
        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
   853
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   854
def _buildregexmatch(kindpats, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   855
    """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
   856
    return regexp string and a matcher function."""
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   857
    try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   858
        regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   859
                                     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
   860
        if len(regex) > 20000:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16645
diff changeset
   861
            raise OverflowError
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   862
        return regex, _rematcher(regex)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   863
    except OverflowError:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   864
        # 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
   865
        # 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
   866
        # until it works
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   867
        l = len(kindpats)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   868
        if l < 2:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   869
            raise
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   870
        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
   871
        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
   872
        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
   873
    except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   874
        for k, p, s in kindpats:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   875
            try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   876
                _rematcher('(?:%s)' % _regex(k, p, globsuffix))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   877
            except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   878
                if s:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
   879
                    raise error.Abort(_("%s: invalid pattern (%s): %s") %
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   880
                                     (s, k, p))
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   881
                else:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
   882
                    raise error.Abort(_("invalid pattern (%s): %s") % (k, p))
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
   883
        raise error.Abort(_("invalid pattern"))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   884
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   885
def _patternrootsanddirs(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   886
    '''Returns roots and directories corresponding to each pattern.
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
   887
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   888
    This calculates the roots and directories exactly matching the patterns and
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   889
    returns a tuple of (roots, dirs) for each. It does not return other
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   890
    directories which may also need to be considered, like the parent
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   891
    directories.
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
   892
    '''
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   893
    r = []
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   894
    d = []
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   895
    for kind, pat, source in kindpats:
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   896
        if kind == 'glob': # find the non-glob prefix
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   897
            root = []
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   898
            for p in pat.split('/'):
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   899
                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
   900
                    break
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   901
                root.append(p)
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   902
            r.append('/'.join(root) or '.')
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   903
        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
   904
            r.append(pat or '.')
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   905
        elif kind in ('rootfilesin',):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   906
            d.append(pat or '.')
19107
fcf08023c011 match: fix root calculation for combining regexps with simple paths
Mads Kiilerich <madski@unity3d.com>
parents: 18713
diff changeset
   907
        else: # relglob, re, relre
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   908
            r.append('.')
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   909
    return r, d
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   910
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   911
def _roots(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   912
    '''Returns root directories to match recursively from the given patterns.'''
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   913
    roots, dirs = _patternrootsanddirs(kindpats)
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   914
    return roots
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   915
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   916
def _rootsanddirs(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   917
    '''Returns roots and exact directories from patterns.
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   918
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   919
    roots are directories to match recursively, whereas exact directories should
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   920
    be matched non-recursively. The returned (roots, dirs) tuple will also
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   921
    include directories that need to be implicitly considered as either, such as
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   922
    parent directories.
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   923
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   924
    >>> _rootsanddirs(\
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   925
        [('glob', 'g/h/*', ''), ('glob', 'g/h', ''), ('glob', 'g*', '')])
32176
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   926
    (['g/h', 'g/h', '.'], ['g', '.'])
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   927
    >>> _rootsanddirs(\
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   928
        [('rootfilesin', 'g/h', ''), ('rootfilesin', '', '')])
32176
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   929
    ([], ['g/h', '.', 'g', '.'])
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   930
    >>> _rootsanddirs(\
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   931
        [('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
32176
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   932
    (['r', 'p/p', '.'], ['p', '.'])
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   933
    >>> _rootsanddirs(\
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   934
        [('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
32176
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   935
    (['.', '.', '.'], ['.'])
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   936
    '''
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   937
    r, d = _patternrootsanddirs(kindpats)
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   938
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   939
    # Append the parents as non-recursive/exact directories, since they must be
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   940
    # scanned to get to either the roots or the other exact directories.
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   941
    d.extend(util.dirs(d))
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   942
    d.extend(util.dirs(r))
32176
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   943
    # util.dirs() does not include the root directory, so add it manually
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32132
diff changeset
   944
    d.append('.')
31013
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   945
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31012
diff changeset
   946
    return r, d
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   947
31012
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   948
def _explicitfiles(kindpats):
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   949
    '''Returns the potential explicit filenames from the patterns.
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   950
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   951
    >>> _explicitfiles([('path', 'foo/bar', '')])
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   952
    ['foo/bar']
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   953
    >>> _explicitfiles([('rootfilesin', 'foo/bar', '')])
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   954
    []
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   955
    '''
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   956
    # Keep only the pattern kinds where one can specify filenames (vs only
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   957
    # directory names).
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   958
    filable = [kp for kp in kindpats if kp[0] not in ('rootfilesin',)]
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   959
    return _roots(filable)
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   960
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   961
def _anypats(kindpats):
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   962
    for kind, pat, source in kindpats:
31012
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30399
diff changeset
   963
        if kind in ('glob', 're', 'relglob', 'relre', 'set', 'rootfilesin'):
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   964
            return True
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   965
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   966
_commentre = None
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   967
27595
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   968
def readpatternfile(filepath, warn, sourceinfo=False):
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   969
    '''parse a pattern file, returning a list of
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   970
    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
   971
    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
   972
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   973
    trailing white space is dropped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   974
    the escape character is backslash.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   975
    comments start with #.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   976
    empty lines are skipped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   977
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   978
    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
   979
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   980
    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
   981
    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
   982
    re:pattern     # non-rooted regular expression
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   983
    glob:pattern   # non-rooted glob
27595
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   984
    pattern        # pattern of the current default type
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   985
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   986
    if sourceinfo is set, returns a list of tuples:
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   987
    (pattern, lineno, originalline). This is useful to debug ignore patterns.
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   988
    '''
25216
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   989
25215
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   990
    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   991
                'include': 'include', 'subinclude': 'subinclude'}
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   992
    syntax = 'relre:'
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   993
    patterns = []
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   994
31403
10c17f8bfcf3 py3: open file in rb mode
Rishabh Madan <rishabhmadan96@gmail.com>
parents: 31392
diff changeset
   995
    fp = open(filepath, 'rb')
30399
7f3593c29473 match: migrate to util.iterfile
Jun Wu <quark@fb.com>
parents: 29803
diff changeset
   996
    for lineno, line in enumerate(util.iterfile(fp), start=1):
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   997
        if "#" in line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   998
            global _commentre
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   999
            if not _commentre:
31420
40704098853f match: make regular expression bytes to prevent TypeError
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31403
diff changeset
  1000
                _commentre = util.re.compile(br'((?:^|[^\\])(?:\\\\)*)#.*')
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1001
            # remove comments prefixed by an even number of escapes
27327
d500341e4f55 match: use re2 in readpatternfile if possible
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
  1002
            m = _commentre.search(line)
d500341e4f55 match: use re2 in readpatternfile if possible
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
  1003
            if m:
d500341e4f55 match: use re2 in readpatternfile if possible
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
  1004
                line = line[:m.end(1)]
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1005
            # fixup properly escaped comments that survived the above
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1006
            line = line.replace("\\#", "#")
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1007
        line = line.rstrip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1008
        if not line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1009
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1010
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1011
        if line.startswith('syntax:'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1012
            s = line[7:].strip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1013
            try:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1014
                syntax = syntaxes[s]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1015
            except KeyError:
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1016
                if warn:
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1017
                    warn(_("%s: ignoring invalid syntax '%s'\n") %
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1018
                         (filepath, s))
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1019
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1020
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1021
        linesyntax = syntax
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1022
        for s, rels in syntaxes.iteritems():
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1023
            if line.startswith(rels):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1024
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1025
                line = line[len(rels):]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1026
                break
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1027
            elif line.startswith(s+':'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1028
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1029
                line = line[len(s) + 1:]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1030
                break
27595
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1031
        if sourceinfo:
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1032
            patterns.append((linesyntax + line, lineno, line))
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1033
        else:
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1034
            patterns.append(linesyntax + line)
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1035
    fp.close()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1036
    return patterns