mercurial/match.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 01 Mar 2018 08:24:54 -0800
changeset 36557 72e487851a53
parent 36088 c4fa47f880d3
child 36601 9adfa48792a7
permissions -rw-r--r--
debugcommands: add debugwireproto command We currently don't have a low-level mechanism for sending arbitrary wire protocol commands. Having a generic and robust mechanism for sending wire protocol commands, examining wire data, etc would make it vastly easier to test the wire protocol and debug server operation. This is a problem I've wanted a solution for numerous times, especially recently as I've been hacking on a new version of the wire protocol. This commit establishes a `hg debugwireproto` command for sending data to a peer. The command invents a mini language for specifying actions to take. This will enable a lot of flexibility for issuing commands and testing variations for how commands are sent. Right now, we only support low-level raw sends and receives. These are probably the least valuable commands to intended users of this command. But they are the most useful commands to implement to bootstrap the feature (I've chosen to reimplement test-ssh-proto.t using this command to prove its usefulness). My eventual goal of `hg debugwireproto` is to allow calling wire protocol commands with a human-friendly interface. Essentially, people can type in a command name and arguments and `hg debugwireproto` will figure out how to send that on the wire. I'd love to eventually be able to save the server's raw response to a file. This would allow us to e.g. call "getbundle" wire protocol commands easily. test-ssh-proto.t has been updated to use the new command in lieu of piping directly to a server process. As part of the transition, test behavior improved. Before, we piped all request data to the server at once. Now, we have explicit control over the ordering of operations. e.g. we can send one command, receive its response, then send another command. This will allow us to more robustly test race conditions, buffering behavior, etc. There were some subtle changes in test behavior. For example, previous behavior would often send trailing newlines to the server. The new mechanism doesn't treat literal newlines specially and requires newlines be escaped in the payload. Because the new logging code is very low level, it is easy to introduce race conditions in tests. For example, the number of bytes returned by a read() may vary depending on load. This is why tests make heavy use of "readline" for consuming data: the result of that operation should be deterministic and not subject to race conditions. There are still some uses of "readavailable." However, those are only for reading from stderr. I was able to reproduce timing issues with my system under load when using "readavailable" globally. But if I "readline" to grab stdout, "readavailable" appears to work deterministically for stderr. I think this is because the server writes to stderr first. As long as the OS delivers writes to pipes in the same order they were made, this should work. If there are timing issues, we can introduce a mechanism to readline from stderr. Differential Revision: https://phab.mercurial-scm.org/D2392
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
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
     8
from __future__ import absolute_import, print_function
25958
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 (
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
    16
    encoding,
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
    17
    error,
25958
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    18
    pathutil,
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    19
    util,
c4ccf2d394a7 match: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25875
diff changeset
    20
)
6576
69f3e9ac7c56 walk: introduce match objects
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
33710
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
    22
allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
    23
                   'listfile', 'listfile0', 'set', 'include', 'subinclude',
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
    24
                   'rootfilesin')
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
    25
cwdrelativepatternkinds = ('relpath', 'glob')
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
    26
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    27
propertycache = util.propertycache
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
    28
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    29
def _rematcher(regex):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    30
    '''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
    31
    matcher function'''
21909
335bb8b80443 match: use util.re.compile instead of util.compilere
Siddharth Agarwal <sid0@fb.com>
parents: 21815
diff changeset
    32
    m = util.re.compile(regex)
16943
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    33
    try:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    34
        # 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
    35
        return m.test_match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    36
    except AttributeError:
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    37
        return m.match
8d08a28aa63e matcher: use re2 bindings if available
Bryan O'Sullivan <bryano@fb.com>
parents: 16791
diff changeset
    38
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    39
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
    40
    '''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
    41
    fset = set()
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    42
    other = []
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    43
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    44
    for kind, pat, source in kindpats:
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    45
        if kind == 'set':
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    46
            if not ctx:
32482
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32453
diff changeset
    47
                raise error.ProgrammingError("fileset expression with no "
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32453
diff changeset
    48
                                             "context")
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
    49
            s = ctx.getfileset(pat)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    50
            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
    51
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    52
            if listsubrepos:
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
    53
                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
    54
                    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
    55
                    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
    56
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    57
            continue
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    58
        other.append((kind, pat, source))
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    59
    return fset, other
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
    60
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    61
def _expandsubinclude(kindpats, root):
32185
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
    62
    '''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
    63
    subincludes in it.'''
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    64
    relmatchers = []
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    65
    other = []
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
    for kind, pat, source in kindpats:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    68
        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
    69
            sourceroot = pathutil.dirname(util.normpath(source))
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    70
            pat = util.pconvert(pat)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    71
            path = pathutil.join(sourceroot, pat)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    72
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    73
            newroot = pathutil.dirname(path)
32185
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
    74
            matcherargs = (newroot, '', [], ['include:%s' % path])
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    75
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    76
            prefix = pathutil.canonpath(root, root, newroot)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    77
            if prefix:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    78
                prefix += '/'
32185
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
    79
            relmatchers.append((prefix, matcherargs))
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    80
        else:
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    81
            other.append((kind, pat, source))
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    82
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    83
    return relmatchers, other
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
    84
24447
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    85
def _kindpatsalwaysmatch(kindpats):
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    86
    """"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
    87
    'relpath:.' does.
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    88
    """
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
    89
    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
    90
        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
    91
            return False
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    92
    return True
d44d53bc9a1e matcher: make e.g. 'relpath:.' lead to fast paths
Martin von Zweigbergk <martinvonz@google.com>
parents: 23686
diff changeset
    93
32748
3e8eb6d84a5c match: allow pats to be None
Martin von Zweigbergk <martinvonz@google.com>
parents: 32673
diff changeset
    94
def match(root, cwd, patterns=None, include=None, exclude=None, default='glob',
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
    95
          exact=False, auditor=None, ctx=None, listsubrepos=False, warn=None,
32439
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
    96
          badfn=None, icasefs=False):
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
    97
    """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: 32365
diff changeset
    98
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
    99
    arguments:
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   100
    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: 32365
diff changeset
   101
    cwd - the current working directory, if relevant
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   102
    patterns - patterns to find
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   103
    include - patterns to include (unless they are excluded)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   104
    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: 32365
diff changeset
   105
    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: 32365
diff changeset
   106
    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: 32365
diff changeset
   107
    warn - optional function used for printing warnings
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   108
    badfn - optional bad() callback for this matcher instead of the default
32439
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   109
    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: 32438
diff changeset
   110
        normalizes the given patterns to the case in the filesystem
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   111
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   112
    a pattern is one of:
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   113
    'glob:<glob>' - a glob relative to cwd
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   114
    're:<regexp>' - a regular expression
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   115
    '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: 32365
diff changeset
   116
                    recursively
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   117
    '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: 32365
diff changeset
   118
                    matched non-recursively (will not match subdirectories)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   119
    '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: 32365
diff changeset
   120
    'relpath:<path>' - a path relative to cwd
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   121
    '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: 32365
diff changeset
   122
    'set:<fileset>' - a fileset expression
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   123
    '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: 32365
diff changeset
   124
    '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: 32365
diff changeset
   125
                          the same directory
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   126
    '<something>' - a pattern of the specified default type
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   127
    """
32439
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   128
    normalize = _donormalize
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   129
    if icasefs:
32453
9695aca1a3a0 match: catch attempts to create case-insenstive exact matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32444
diff changeset
   130
        if exact:
32482
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32453
diff changeset
   131
            raise error.ProgrammingError("a case-insensitive exact matcher "
57d6c0c74b1b match: use ProgrammingError where appropriate
Martin von Zweigbergk <martinvonz@google.com>
parents: 32453
diff changeset
   132
                                         "doesn't make sense")
32439
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   133
        dirstate = ctx.repo().dirstate
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   134
        dsnormalize = dirstate.normalize
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   135
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   136
        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: 32438
diff changeset
   137
            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: 32438
diff changeset
   138
            kindpats = []
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   139
            for kind, pats, source in kp:
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   140
                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: 32438
diff changeset
   141
                    p = pats
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   142
                    pats = dsnormalize(pats)
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   143
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   144
                    # 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: 32438
diff changeset
   145
                    if p != pats and p in dirstate:
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   146
                        kindpats.append((kind, p, source))
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   147
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   148
                kindpats.append((kind, pats, source))
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   149
            return kindpats
284b18303f61 match: replace icasefsmatch() function by flag to regular match()
Martin von Zweigbergk <martinvonz@google.com>
parents: 32438
diff changeset
   150
32532
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   151
    if exact:
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   152
        m = exactmatcher(root, cwd, patterns, badfn)
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   153
    elif patterns:
32589
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   154
        kindpats = normalize(patterns, default, root, cwd, auditor, warn)
32590
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   155
        if _kindpatsalwaysmatch(kindpats):
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   156
            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: 32589
diff changeset
   157
        else:
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   158
            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: 32589
diff changeset
   159
                               listsubrepos=listsubrepos, badfn=badfn)
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   160
    else:
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   161
        # It's a little strange that no patterns means to match everything.
32673
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32631
diff changeset
   162
        # Consider changing this to match nothing (probably using nevermatcher).
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   163
        m = alwaysmatcher(root, cwd, badfn)
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   164
32530
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   165
    if include:
32589
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   166
        kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   167
        im = includematcher(root, cwd, kindpats, ctx=ctx,
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   168
                            listsubrepos=listsubrepos, badfn=None)
32530
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   169
        m = intersectmatchers(m, im)
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   170
    if exclude:
32589
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   171
        kindpats = normalize(exclude, 'glob', root, cwd, auditor, warn)
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   172
        em = includematcher(root, cwd, kindpats, ctx=ctx,
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   173
                            listsubrepos=listsubrepos, badfn=None)
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   174
        m = differencematcher(m, em)
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   175
    return m
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   176
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   177
def exact(root, cwd, files, badfn=None):
32532
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   178
    return exactmatcher(root, cwd, files, badfn=badfn)
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   179
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   180
def always(root, cwd):
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   181
    return alwaysmatcher(root, cwd)
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   182
32631
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   183
def never(root, cwd):
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   184
    return nevermatcher(root, cwd)
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   185
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   186
def badmatch(match, badfn):
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   187
    """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: 32365
diff changeset
   188
    one.
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   189
    """
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   190
    m = copy.copy(match)
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   191
    m.bad = badfn
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   192
    return m
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   193
32435
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   194
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: 32434
diff changeset
   195
    '''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: 32434
diff changeset
   196
    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: 32434
diff changeset
   197
    kindpats = []
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   198
    for kind, pat in [_patsplit(p, default) for p in patterns]:
33710
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
   199
        if kind in cwdrelativepatternkinds:
32435
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   200
            pat = pathutil.canonpath(root, cwd, pat, auditor)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   201
        elif kind in ('relglob', 'path', 'rootfilesin'):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   202
            pat = util.normpath(pat)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   203
        elif kind in ('listfile', 'listfile0'):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   204
            try:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   205
                files = util.readfile(pat)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   206
                if kind == 'listfile0':
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   207
                    files = files.split('\0')
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   208
                else:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   209
                    files = files.splitlines()
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   210
                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: 32434
diff changeset
   211
            except EnvironmentError:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   212
                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: 32434
diff changeset
   213
            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: 32434
diff changeset
   214
                                             auditor, warn):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   215
                kindpats.append((k, p, pat))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   216
            continue
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   217
        elif kind == 'include':
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   218
            try:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   219
                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: 32434
diff changeset
   220
                includepats = readpatternfile(fullpath, warn)
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   221
                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: 32434
diff changeset
   222
                                                 root, cwd, auditor, warn):
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   223
                    kindpats.append((k, p, source or pat))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   224
            except error.Abort as inst:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   225
                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: 32434
diff changeset
   226
            except IOError as inst:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   227
                if warn:
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   228
                    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: 32434
diff changeset
   229
                         (pat, inst.strerror))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   230
            continue
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   231
        # 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: 32434
diff changeset
   232
        kindpats.append((kind, pat, ''))
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   233
    return kindpats
0ec4cd6fe051 match: move body of _normalize() to a static function
Martin von Zweigbergk <martinvonz@google.com>
parents: 32434
diff changeset
   234
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   235
class basematcher(object):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   236
32529
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   237
    def __init__(self, root, cwd, badfn=None, relativeuipath=True):
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   238
        self._root = root
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   239
        self._cwd = cwd
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   240
        if badfn is not None:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   241
            self.bad = badfn
32529
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   242
        self._relativeuipath = relativeuipath
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   243
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   244
    def __call__(self, fn):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   245
        return self.matchfn(fn)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   246
    def __iter__(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   247
        for f in self._files:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   248
            yield f
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   249
    # 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: 32482
diff changeset
   250
    # Subscribers to these events must monkeypatch the matcher object.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   251
    def bad(self, f, msg):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   252
        '''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: 32482
diff changeset
   253
        found/accessed, with an error message.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   254
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   255
    # 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: 32482
diff changeset
   256
    # directory is visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   257
    explicitdir = None
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   258
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   259
    # 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: 32482
diff changeset
   260
    # by recursive traversal is visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   261
    traversedir = None
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   262
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   263
    def abs(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   264
        '''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: 32482
diff changeset
   265
        matcher.'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   266
        return f
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   267
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   268
    def rel(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   269
        '''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: 32482
diff changeset
   270
        return util.pathto(self._root, self._cwd, f)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   271
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   272
    def uipath(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   273
        '''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: 32482
diff changeset
   274
        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: 32482
diff changeset
   275
        Otherwise it is relative to the root of the repo.'''
32529
ca77a243ffa7 match: move entire uipath() implementation to basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32500
diff changeset
   276
        return (self._relativeuipath and self.rel(f)) or self.abs(f)
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   277
32493
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32492
diff changeset
   278
    @propertycache
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32492
diff changeset
   279
    def _files(self):
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32492
diff changeset
   280
        return []
9f781f43f2ce match: make basematcher._files a @propertycache
Martin von Zweigbergk <martinvonz@google.com>
parents: 32492
diff changeset
   281
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   282
    def files(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   283
        '''Explicitly listed files or patterns or roots:
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   284
        if no patterns or .always(): empty list,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   285
        if exact: list exact files,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   286
        if not .anypats(): list all files and dirs,
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   287
        else: optimal roots'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   288
        return self._files
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   289
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   290
    @propertycache
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   291
    def _fileset(self):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   292
        return set(self._files)
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   293
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   294
    def exact(self, f):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   295
        '''Returns True if f is in .files().'''
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   296
        return f in self._fileset
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   297
32497
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32495
diff changeset
   298
    def matchfn(self, f):
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32495
diff changeset
   299
        return False
43e091847c4d match: make matchfn a method on the class
Martin von Zweigbergk <martinvonz@google.com>
parents: 32495
diff changeset
   300
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   301
    def visitdir(self, dir):
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   302
        '''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: 32482
diff changeset
   303
        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: 32482
diff changeset
   304
        based on the match's primary, included, and excluded patterns.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   305
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   306
        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: 32482
diff changeset
   307
        should be visited. Otherwise returns True or False indicating whether
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   308
        the given directory should be visited.
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   309
        '''
33478
cf15c3cc304c match: make base matcher return True for visitdir
Durham Goode <durham@fb.com>
parents: 33448
diff changeset
   310
        return True
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   311
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   312
    def always(self):
33379
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   313
        '''Matcher will match everything and .files() will be empty --
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   314
        optimization might be possible.'''
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   315
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   316
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   317
    def isexact(self):
33379
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   318
        '''Matcher will match exactly the list of files in .files() --
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   319
        optimization might be possible.'''
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   320
        return False
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   321
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   322
    def prefix(self):
33379
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   323
        '''Matcher will match the paths in .files() recursively --
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   324
        optimization might be possible.'''
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   325
        return False
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   326
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   327
    def anypats(self):
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   328
        '''None of .always(), .isexact(), and .prefix() is true --
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   329
        optimizations will be difficult.'''
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   330
        return not self.always() and not self.isexact() and not self.prefix()
32492
a04bc55201c3 match: extract base class for matchers
Martin von Zweigbergk <martinvonz@google.com>
parents: 32482
diff changeset
   331
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   332
class alwaysmatcher(basematcher):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   333
    '''Matches everything.'''
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   334
32590
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   335
    def __init__(self, root, cwd, badfn=None, relativeuipath=False):
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   336
        super(alwaysmatcher, self).__init__(root, cwd, badfn,
32590
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   337
                                            relativeuipath=relativeuipath)
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   338
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   339
    def always(self):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   340
        return True
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   341
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   342
    def matchfn(self, f):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   343
        return True
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   344
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   345
    def visitdir(self, dir):
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   346
        return 'all'
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   347
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   348
    def __repr__(self):
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   349
        return r'<alwaysmatcher>'
32586
20c9f3ecc192 match: handle everything-matching using new alwaysmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32585
diff changeset
   350
32631
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   351
class nevermatcher(basematcher):
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   352
    '''Matches nothing.'''
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   353
32673
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32631
diff changeset
   354
    def __init__(self, root, cwd, badfn=None):
783394c0c978 match: simplify nevermatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32631
diff changeset
   355
        super(nevermatcher, self).__init__(root, cwd, badfn)
32631
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   356
33378
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   357
    # It's a little weird to say that the nevermatcher is an exact matcher
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   358
    # or a prefix matcher, but it seems to make sense to let callers take
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   359
    # fast paths based on either. There will be no exact matches, nor any
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   360
    # prefixes (files() returns []), so fast paths iterating over them should
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   361
    # be efficient (and correct).
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   362
    def isexact(self):
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   363
        return True
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   364
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   365
    def prefix(self):
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   366
        return True
adf95bfb423a match: make nevermatcher an exact matcher and a prefix matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33358
diff changeset
   367
33582
44bc181b9835 match: override visitdir() in nevermatcher to return False
Martin von Zweigbergk <martinvonz@google.com>
parents: 33497
diff changeset
   368
    def visitdir(self, dir):
44bc181b9835 match: override visitdir() in nevermatcher to return False
Martin von Zweigbergk <martinvonz@google.com>
parents: 33497
diff changeset
   369
        return False
44bc181b9835 match: override visitdir() in nevermatcher to return False
Martin von Zweigbergk <martinvonz@google.com>
parents: 33497
diff changeset
   370
32631
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   371
    def __repr__(self):
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   372
        return r'<nevermatcher>'
32631
e6ff007e107e match: introduce nevermatcher for when no ignore files are present
Siddharth Agarwal <sid0@fb.com>
parents: 32590
diff changeset
   373
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   374
class patternmatcher(basematcher):
32433
24245b54aa8a match: replace match class by match function (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32365
diff changeset
   375
32589
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   376
    def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False,
32537
2ba4d3b74ba8 match: remove support for includes from patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32536
diff changeset
   377
                 badfn=None):
32588
b3083be7dcb9 match: drop support for empty pattern list in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32587
diff changeset
   378
        super(patternmatcher, self).__init__(root, cwd, badfn)
8581
101d305c1d0b match: fold _matcher into match.__init__
Matt Mackall <mpm@selenic.com>
parents: 8580
diff changeset
   379
32590
3fdcc34c0aba match: remove special-casing of always-matching patterns in patternmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32589
diff changeset
   380
        self._files = _explicitfiles(kindpats)
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   381
        self._prefix = _prefix(kindpats)
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   382
        self._pats, self.matchfn = _buildmatch(ctx, kindpats, '$', listsubrepos,
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   383
                                               root)
8587
8f15d54437b9 match: fold match into _match base class
Matt Mackall <mpm@selenic.com>
parents: 8586
diff changeset
   384
32362
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32352
diff changeset
   385
    @propertycache
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   386
    def _dirs(self):
32362
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32352
diff changeset
   387
        return set(util.dirs(self._fileset)) | {'.'}
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   388
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   389
    def visitdir(self, dir):
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   390
        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
   391
            return 'all'
32587
f44ea253ffe2 match: optimize visitdir() for when no explicit files are listed
Martin von Zweigbergk <martinvonz@google.com>
parents: 32586
diff changeset
   392
        return ('.' in self._fileset or
32362
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32352
diff changeset
   393
                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
   394
                dir in self._dirs or
32362
23c9a2a71c6e match: make _fileroots a @propertycache and rename it to _fileset
Martin von Zweigbergk <martinvonz@google.com>
parents: 32352
diff changeset
   395
                any(parentdir in self._fileset
25577
a410479c7ee7 match: drop optimization (?) of 'parentdirs' calculation
Martin von Zweigbergk <martinvonz@google.com>
parents: 25576
diff changeset
   396
                    for parentdir in util.finddirs(dir)))
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24452
diff changeset
   397
33379
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   398
    def prefix(self):
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   399
        return self._prefix
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   400
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   401
    @encoding.strmethod
32444
952017471f93 match: implement __repr__() and update users (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32439
diff changeset
   402
    def __repr__(self):
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   403
        return ('<patternmatcher patterns=%r>' % self._pats)
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   404
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   405
class includematcher(basematcher):
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   406
32589
5f08eca8f8d3 match: move normalize() call out of matcher constructors
Martin von Zweigbergk <martinvonz@google.com>
parents: 32588
diff changeset
   407
    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: 32588
diff changeset
   408
                 badfn=None):
32535
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32534
diff changeset
   409
        super(includematcher, self).__init__(root, cwd, badfn)
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   410
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   411
        self._pats, self.matchfn = _buildmatch(ctx, kindpats, '(?:/|$)',
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   412
                                               listsubrepos, root)
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   413
        self._prefix = _prefix(kindpats)
32535
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32534
diff changeset
   414
        roots, dirs = _rootsanddirs(kindpats)
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32534
diff changeset
   415
        # roots are directories which are recursively included.
32536
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   416
        self._roots = set(roots)
32535
3026f19b4b01 match: remove support for non-include patterns from includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32534
diff changeset
   417
        # dirs are directories which are non-recursively included.
32536
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   418
        self._dirs = set(dirs)
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   419
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   420
    def visitdir(self, dir):
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   421
        if self._prefix and dir in self._roots:
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   422
            return 'all'
32536
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   423
        return ('.' in self._roots or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   424
                dir in self._roots or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   425
                dir in self._dirs or
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   426
                any(parentdir in self._roots
361808a2b0b8 match: simplify includematcher a bit
Martin von Zweigbergk <martinvonz@google.com>
parents: 32535
diff changeset
   427
                    for parentdir in util.finddirs(dir)))
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   428
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   429
    @encoding.strmethod
32534
7095dbc266e3 match: split up main matcher into patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32533
diff changeset
   430
    def __repr__(self):
33306
a9808bd1449e match: minor cleanups to patternmatcher and includematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32748
diff changeset
   431
        return ('<includematcher includes=%r>' % self._pats)
32444
952017471f93 match: implement __repr__() and update users (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32439
diff changeset
   432
32532
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   433
class exactmatcher(basematcher):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   434
    '''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: 32530
diff changeset
   435
    patterns (so no kind-prefixes).
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   436
    '''
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   437
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   438
    def __init__(self, root, cwd, files, badfn=None):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   439
        super(exactmatcher, self).__init__(root, cwd, badfn)
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   440
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   441
        if isinstance(files, list):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   442
            self._files = files
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   443
        else:
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   444
            self._files = list(files)
32576
cf7c88986e9f match: define exactmatcher.matchfn statically
Yuya Nishihara <yuya@tcha.org>
parents: 32575
diff changeset
   445
cf7c88986e9f match: define exactmatcher.matchfn statically
Yuya Nishihara <yuya@tcha.org>
parents: 32575
diff changeset
   446
    matchfn = basematcher.exact
32532
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   447
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   448
    @propertycache
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   449
    def _dirs(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   450
        return set(util.dirs(self._fileset)) | {'.'}
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   451
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   452
    def visitdir(self, dir):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   453
        return dir in self._dirs
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   454
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   455
    def isexact(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   456
        return True
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   457
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   458
    @encoding.strmethod
32532
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   459
    def __repr__(self):
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   460
        return ('<exactmatcher files=%r>' % self._files)
a3583852861a match: handle exact matching using new exactmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32530
diff changeset
   461
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   462
class differencematcher(basematcher):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   463
    '''Composes two matchers by matching if the first matches and the second
35659
821d8a5ab4ff match: do not weirdly include explicit files excluded by -X option
Yuya Nishihara <yuya@tcha.org>
parents: 35185
diff changeset
   464
    does not.
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   465
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   466
    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: 32498
diff changeset
   467
    traversedir) are ignored.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   468
    '''
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   469
    def __init__(self, m1, m2):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   470
        super(differencematcher, self).__init__(m1._root, m1._cwd)
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   471
        self._m1 = m1
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   472
        self._m2 = m2
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   473
        self.bad = m1.bad
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   474
        self.explicitdir = m1.explicitdir
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   475
        self.traversedir = m1.traversedir
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   476
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   477
    def matchfn(self, f):
35659
821d8a5ab4ff match: do not weirdly include explicit files excluded by -X option
Yuya Nishihara <yuya@tcha.org>
parents: 35185
diff changeset
   478
        return self._m1(f) and not self._m2(f)
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   479
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   480
    @propertycache
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   481
    def _files(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   482
        if self.isexact():
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   483
            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: 32498
diff changeset
   484
        # 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: 32498
diff changeset
   485
        # 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: 32498
diff changeset
   486
        # 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: 32498
diff changeset
   487
        # 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: 32498
diff changeset
   488
        # because the "dir" in m1 may not be a file.
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   489
        return self._m1.files()
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   490
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   491
    def visitdir(self, dir):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   492
        if self._m2.visitdir(dir) == 'all':
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   493
            return False
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   494
        return bool(self._m1.visitdir(dir))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   495
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   496
    def isexact(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   497
        return self._m1.isexact()
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   498
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   499
    @encoding.strmethod
32499
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   500
    def __repr__(self):
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   501
        return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2))
a83a7d27911e match: handle excludes using new differencematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32498
diff changeset
   502
32530
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   503
def intersectmatchers(m1, m2):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   504
    '''Composes two matchers by matching if both of them match.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   505
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   506
    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: 32529
diff changeset
   507
    traversedir) are ignored.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   508
    '''
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   509
    if m1 is None or m2 is None:
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   510
        return m1 or m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   511
    if m1.always():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   512
        m = copy.copy(m2)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   513
        # 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: 32529
diff changeset
   514
        # one thing to copy from m1.
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   515
        m.bad = m1.bad
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   516
        m.explicitdir = m1.explicitdir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   517
        m.traversedir = m1.traversedir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   518
        m.abs = m1.abs
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   519
        m.rel = m1.rel
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   520
        m._relativeuipath |= m1._relativeuipath
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   521
        return m
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   522
    if m2.always():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   523
        m = copy.copy(m1)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   524
        m._relativeuipath |= m2._relativeuipath
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   525
        return m
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   526
    return intersectionmatcher(m1, m2)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   527
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   528
class intersectionmatcher(basematcher):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   529
    def __init__(self, m1, m2):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   530
        super(intersectionmatcher, self).__init__(m1._root, m1._cwd)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   531
        self._m1 = m1
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   532
        self._m2 = m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   533
        self.bad = m1.bad
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   534
        self.explicitdir = m1.explicitdir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   535
        self.traversedir = m1.traversedir
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   536
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   537
    @propertycache
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   538
    def _files(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   539
        if self.isexact():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   540
            m1, m2 = self._m1, self._m2
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   541
            if not m1.isexact():
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   542
                m1, m2 = m2, m1
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   543
            return [f for f in m1.files() if m2(f)]
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   544
        # 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: 32529
diff changeset
   545
        # 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: 32529
diff changeset
   546
        # 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: 32529
diff changeset
   547
        # "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: 32529
diff changeset
   548
        return self._m1.files() + self._m2.files()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   549
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   550
    def matchfn(self, f):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   551
        return self._m1(f) and self._m2(f)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   552
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   553
    def visitdir(self, dir):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   554
        visit1 = self._m1.visitdir(dir)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   555
        if visit1 == 'all':
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   556
            return self._m2.visitdir(dir)
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   557
        # bool() because visit1=True + visit2='all' should not be 'all'
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   558
        return bool(visit1 and self._m2.visitdir(dir))
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   559
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   560
    def always(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   561
        return self._m1.always() and self._m2.always()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   562
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   563
    def isexact(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   564
        return self._m1.isexact() or self._m2.isexact()
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   565
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   566
    @encoding.strmethod
32530
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   567
    def __repr__(self):
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   568
        return ('<intersectionmatcher m1=%r, m2=%r>' % (self._m1, self._m2))
9eccd559c592 match: handle includes using new intersectionmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32529
diff changeset
   569
32494
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   570
class subdirmatcher(basematcher):
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   571
    """Adapt a matcher to work on a subdirectory only.
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   572
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   573
    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
   574
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   575
    >>> from . import pycompat
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   576
    >>> m1 = match(b'root', b'', [b'a.txt', b'sub/b.txt'])
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   577
    >>> m2 = subdirmatcher(b'sub', m1)
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   578
    >>> bool(m2(b'a.txt'))
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   579
    False
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   580
    >>> bool(m2(b'b.txt'))
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   581
    True
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   582
    >>> bool(m2.matchfn(b'a.txt'))
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   583
    False
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   584
    >>> bool(m2.matchfn(b'b.txt'))
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   585
    True
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   586
    >>> m2.files()
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   587
    ['b.txt']
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   588
    >>> m2.exact(b'b.txt')
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   589
    True
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   590
    >>> util.pconvert(m2.rel(b'b.txt'))
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   591
    'sub/b.txt'
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   592
    >>> def bad(f, msg):
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   593
    ...     print(pycompat.sysstr(b"%s: %s" % (f, msg)))
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   594
    >>> m1.bad = bad
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   595
    >>> m2.bad(b'x.txt', b'No such file')
12268
83aaeba32b88 narrowmatcher: propagate bad method
Martin Geisler <mg@lazybytes.net>
parents: 12267
diff changeset
   596
    sub/x.txt: No such file
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   597
    >>> m2.abs(b'c.txt')
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   598
    'sub/c.txt'
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
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   601
    def __init__(self, path, matcher):
32494
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   602
        super(subdirmatcher, self).__init__(matcher._root, matcher._cwd)
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   603
        self._path = path
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   604
        self._matcher = matcher
32494
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   605
        self._always = matcher.always()
12165
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   606
b7fbf24c8a93 match: add narrowmatcher class
Martin Geisler <mg@lazybytes.net>
parents: 12163
diff changeset
   607
        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
   608
                       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
   609
32365
763d72925691 match: use match.prefix() in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32364
diff changeset
   610
        # 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: 32364
diff changeset
   611
        # a prefix matcher, this submatcher always matches.
763d72925691 match: use match.prefix() in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32364
diff changeset
   612
        if matcher.prefix():
25195
472a685a4961 merge with stable
Matt Mackall <mpm@selenic.com>
parents: 25189 25194
diff changeset
   613
            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
   614
32364
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   615
    def bad(self, f, msg):
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   616
        self._matcher.bad(self._path + "/" + f, msg)
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   617
23685
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   618
    def abs(self, f):
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   619
        return self._matcher.abs(self._path + "/" + f)
5b1eac343ccd match: add the abs() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23549
diff changeset
   620
23686
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   621
    def rel(self, f):
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   622
        return self._matcher.rel(self._path + "/" + f)
164915e8ef7b narrowmatcher: propagate the rel() method
Matt Harbison <matt_harbison@yahoo.com>
parents: 23685
diff changeset
   623
32364
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   624
    def uipath(self, f):
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   625
        return self._matcher.uipath(self._path + "/" + f)
77dac8fd30ee match: avoid accessing match._pathrestricted from subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32363
diff changeset
   626
32498
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   627
    def matchfn(self, f):
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   628
        # 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: 32497
diff changeset
   629
        # 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: 32497
diff changeset
   630
        # 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: 32497
diff changeset
   631
        # 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: 32497
diff changeset
   632
        return self._matcher.matchfn(self._path + "/" + f)
2e80a691e575 match: override matchfn() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32497
diff changeset
   633
32363
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   634
    def visitdir(self, dir):
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   635
        if dir == '.':
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   636
            dir = self._path
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   637
        else:
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   638
            dir = self._path + "/" + dir
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   639
        return self._matcher.visitdir(dir)
0aa4032a97e1 match: override visitdir() the usual way in subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32362
diff changeset
   640
32494
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   641
    def always(self):
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   642
        return self._always
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   643
33379
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   644
    def prefix(self):
7ddb2aa2b7af match: express anypats(), not prefix(), in terms of the others
Martin von Zweigbergk <martinvonz@google.com>
parents: 33378
diff changeset
   645
        return self._matcher.prefix() and not self._always
32494
f9445b528687 match: make subdirmatcher extend basematcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32493
diff changeset
   646
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   647
    @encoding.strmethod
32585
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32576
diff changeset
   648
    def __repr__(self):
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32576
diff changeset
   649
        return ('<subdirmatcher path=%r, matcher=%r>' %
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32576
diff changeset
   650
                (self._path, self._matcher))
e7aa11f3abcd match: add __repr__ for subdirmatcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 32576
diff changeset
   651
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   652
class unionmatcher(basematcher):
33448
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   653
    """A matcher that is the union of several matchers.
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   654
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   655
    The non-matching-attributes (root, cwd, bad, explicitdir, traversedir) are
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   656
    taken from the first matcher.
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   657
    """
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   658
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   659
    def __init__(self, matchers):
33448
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   660
        m1 = matchers[0]
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   661
        super(unionmatcher, self).__init__(m1._root, m1._cwd)
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   662
        self.explicitdir = m1.explicitdir
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   663
        self.traversedir = m1.traversedir
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   664
        self._matchers = matchers
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   665
33380
892d255ec2a1 match: override matchfn instead of __call__ for consistency
Martin von Zweigbergk <martinvonz@google.com>
parents: 33379
diff changeset
   666
    def matchfn(self, f):
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   667
        for match in self._matchers:
33380
892d255ec2a1 match: override matchfn instead of __call__ for consistency
Martin von Zweigbergk <martinvonz@google.com>
parents: 33379
diff changeset
   668
            if match(f):
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   669
                return True
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   670
        return False
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   671
33448
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   672
    def visitdir(self, dir):
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   673
        r = False
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   674
        for m in self._matchers:
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   675
            v = m.visitdir(dir)
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   676
            if v == 'all':
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   677
                return v
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   678
            r |= v
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   679
        return r
04be8aec44a8 match: make unionmatcher a proper matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 33447
diff changeset
   680
36088
c4fa47f880d3 py3: make sure we return str from __repr__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 35659
diff changeset
   681
    @encoding.strmethod
33319
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   682
    def __repr__(self):
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   683
        return ('<unionmatcher matchers=%r>' % self._matchers)
3c84591e7321 match: move matchers from sparse into core
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33306
diff changeset
   684
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   685
def patkind(pattern, default=None):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   686
    '''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
   687
    return _patsplit(pattern, default)[0]
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   688
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   689
def _patsplit(pattern, default):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   690
    """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
   691
    pattern."""
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   692
    if ':' in pattern:
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   693
        kind, pat = pattern.split(':', 1)
33710
2be0bf186950 match: expose some data and functionality to other modules
Kostia Balytskyi <ikostia@fb.com>
parents: 33582
diff changeset
   694
        if kind in allpatternkinds:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   695
            return kind, pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   696
    return default, pattern
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   697
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   698
def _globre(pat):
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   699
    r'''Convert an extended glob string to a regexp string.
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   700
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   701
    >>> from . import pycompat
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   702
    >>> def bprint(s):
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   703
    ...     print(pycompat.sysstr(s))
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   704
    >>> bprint(_globre(br'?'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   705
    .
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   706
    >>> bprint(_globre(br'*'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   707
    [^/]*
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   708
    >>> bprint(_globre(br'**'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   709
    .*
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   710
    >>> bprint(_globre(br'**/a'))
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   711
    (?:.*/)?a
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   712
    >>> bprint(_globre(br'a/**/b'))
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   713
    a\/(?:.*/)?b
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   714
    >>> bprint(_globre(br'[a*?!^][^b][!c]'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   715
    [a*?!^][\^b][^c]
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   716
    >>> bprint(_globre(br'{a,b}'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   717
    (?:a|b)
34152
a8994d08e4a2 doctest: use print_function and convert bytes to unicode where needed
Yuya Nishihara <yuya@tcha.org>
parents: 34146
diff changeset
   718
    >>> bprint(_globre(br'.\*\?'))
21112
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   719
    \.\*\?
03782d2fc776 match: _globre doctests
Mads Kiilerich <madski@unity3d.com>
parents: 21111
diff changeset
   720
    '''
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   721
    i, n = 0, len(pat)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   722
    res = ''
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   723
    group = 0
21915
d516b6de3821 match: use util.re.escape instead of re.escape
Siddharth Agarwal <sid0@fb.com>
parents: 21909
diff changeset
   724
    escape = util.re.escape
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   725
    def peek():
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   726
        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
   727
    while i < n:
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   728
        c = pat[i:i + 1]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   729
        i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   730
        if c not in '*?[{},\\':
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   731
            res += escape(c)
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   732
        elif c == '*':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   733
            if peek() == '*':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   734
                i += 1
21815
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   735
                if peek() == '/':
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   736
                    i += 1
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   737
                    res += '(?:.*/)?'
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   738
                else:
a4b67bf1f0a5 match: make glob '**/' match the empty string
Siddharth Agarwal <sid0@fb.com>
parents: 21191
diff changeset
   739
                    res += '.*'
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   740
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   741
                res += '[^/]*'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   742
        elif c == '?':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   743
            res += '.'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   744
        elif c == '[':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   745
            j = i
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   746
            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
   747
                j += 1
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   748
            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
   749
                j += 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   750
            if j >= n:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   751
                res += '\\['
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   752
            else:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   753
                stuff = pat[i:j].replace('\\','\\\\')
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   754
                i = j + 1
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   755
                if stuff[0:1] == '!':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   756
                    stuff = '^' + stuff[1:]
31430
5c9cda37d7f6 match: slice over bytes to get the byteschr instead of ascii value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31429
diff changeset
   757
                elif stuff[0:1] == '^':
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   758
                    stuff = '\\' + stuff
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   759
                res = '%s[%s]' % (res, stuff)
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   760
        elif c == '{':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   761
            group += 1
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
        elif c == '}' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   764
            res += ')'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   765
            group -= 1
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   766
        elif c == ',' and group:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   767
            res += '|'
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   768
        elif c == '\\':
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   769
            p = peek()
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   770
            if p:
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   771
                i += 1
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   772
                res += escape(p)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   773
            else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   774
                res += escape(c)
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   775
        else:
8583
19d1b2aec562 match: optimize escaping in _globre
Matt Mackall <mpm@selenic.com>
parents: 8582
diff changeset
   776
            res += escape(c)
8582
a4c199e12b5a match: remove head and tail args from _globre
Matt Mackall <mpm@selenic.com>
parents: 8581
diff changeset
   777
    return res
8570
7fe2012b3bd0 match: move util match functions over
Matt Mackall <mpm@selenic.com>
parents: 8568
diff changeset
   778
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   779
def _regex(kind, pat, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   780
    '''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
   781
    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
   782
    if not pat:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   783
        return ''
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   784
    if kind == 're':
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   785
        return pat
33358
38b6122df5c7 match: combine regex code for path: and relpath:
Martin von Zweigbergk <martinvonz@google.com>
parents: 33357
diff changeset
   786
    if kind in ('path', 'relpath'):
25636
bfe9ed85f27c match: let 'path:.' and 'path:' match everything (issue4687)
Matt Harbison <matt_harbison@yahoo.com>
parents: 25194
diff changeset
   787
        if pat == '.':
bfe9ed85f27c match: let 'path:.' and 'path:' match everything (issue4687)
Matt Harbison <matt_harbison@yahoo.com>
parents: 25194
diff changeset
   788
            return ''
33357
a21819f439fe match: remove unnecessary '^' from regexes
Martin von Zweigbergk <martinvonz@google.com>
parents: 33319
diff changeset
   789
        return util.re.escape(pat) + '(?:/|$)'
31032
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   790
    if kind == 'rootfilesin':
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   791
        if pat == '.':
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   792
            escaped = ''
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   793
        else:
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   794
            # Pattern is a directory name.
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   795
            escaped = util.re.escape(pat) + '/'
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   796
        # Anything after the pattern must be a non-directory.
33357
a21819f439fe match: remove unnecessary '^' from regexes
Martin von Zweigbergk <martinvonz@google.com>
parents: 33319
diff changeset
   797
        return escaped + '[^/]+$'
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   798
    if kind == 'relglob':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   799
        return '(?:|.*/)' + _globre(pat) + globsuffix
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   800
    if kind == 'relre':
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   801
        if pat.startswith('^'):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   802
            return pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   803
        return '.*' + pat
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   804
    return _globre(pat) + globsuffix
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   805
25238
5a55ad6e8e24 match: add root to _buildmatch
Durham Goode <durham@fb.com>
parents: 25233
diff changeset
   806
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
   807
    '''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
   808
    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
   809
    matchfuncs = []
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   810
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   811
    subincludes, kindpats = _expandsubinclude(kindpats, root)
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   812
    if subincludes:
32185
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   813
        submatchers = {}
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   814
        def matchsubinclude(f):
32185
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   815
            for prefix, matcherargs in subincludes:
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   816
                if f.startswith(prefix):
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   817
                    mf = submatchers.get(prefix)
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   818
                    if mf is None:
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   819
                        mf = match(*matcherargs)
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   820
                        submatchers[prefix] = mf
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   821
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   822
                    if mf(f[len(prefix):]):
6dea1701f170 match: make subinclude construction lazy
Durham Goode <durham@fb.com>
parents: 31442
diff changeset
   823
                        return True
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   824
            return False
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   825
        matchfuncs.append(matchsubinclude)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   826
25122
755d23a49170 match: resolve filesets in subrepos for commands given the '-S' argument
Matt Harbison <matt_harbison@yahoo.com>
parents: 25114
diff changeset
   827
    fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   828
    if fset:
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   829
        matchfuncs.append(fset.__contains__)
14675
cfc89398f710 match: introduce basic fileset support
Matt Mackall <mpm@selenic.com>
parents: 14674
diff changeset
   830
25239
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   831
    regex = ''
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   832
    if kindpats:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   833
        regex, mf = _buildregexmatch(kindpats, globsuffix)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   834
        matchfuncs.append(mf)
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   835
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   836
    if len(matchfuncs) == 1:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   837
        return regex, matchfuncs[0]
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   838
    else:
714f612f2afc match: allow unioning arbitrary match functions
Durham Goode <durham@fb.com>
parents: 25238
diff changeset
   839
        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
   840
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   841
def _buildregexmatch(kindpats, globsuffix):
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   842
    """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
   843
    return regexp string and a matcher function."""
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   844
    try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   845
        regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   846
                                     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
   847
        if len(regex) > 20000:
16687
e34106fa0dc3 cleanup: "raise SomeException()" -> "raise SomeException"
Brodie Rao <brodie@sf.io>
parents: 16645
diff changeset
   848
            raise OverflowError
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   849
        return regex, _rematcher(regex)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   850
    except OverflowError:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   851
        # 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
   852
        # 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
   853
        # until it works
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   854
        l = len(kindpats)
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   855
        if l < 2:
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   856
            raise
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   857
        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
   858
        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
   859
        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
   860
    except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   861
        for k, p, s in kindpats:
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   862
            try:
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   863
                _rematcher('(?:%s)' % _regex(k, p, globsuffix))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   864
            except re.error:
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   865
                if s:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
   866
                    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
   867
                                     (s, k, p))
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   868
                else:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
   869
                    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
   870
        raise error.Abort(_("invalid pattern"))
8574
63a7ed2128d5 match: unnest functions in _matcher
Matt Mackall <mpm@selenic.com>
parents: 8573
diff changeset
   871
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   872
def _patternrootsanddirs(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   873
    '''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
   874
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   875
    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: 31032
diff changeset
   876
    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: 31032
diff changeset
   877
    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: 31032
diff changeset
   878
    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
   879
    '''
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   880
    r = []
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   881
    d = []
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   882
    for kind, pat, source in kindpats:
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   883
        if kind == 'glob': # find the non-glob prefix
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   884
            root = []
21111
9d28fd795215 match: improve documentation - docstrings and more descriptive variable naming
Mads Kiilerich <madski@unity3d.com>
parents: 21079
diff changeset
   885
            for p in pat.split('/'):
8584
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   886
                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
   887
                    break
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   888
                root.append(p)
0f06e72abfdc match: fold _globprefix into _roots
Matt Mackall <mpm@selenic.com>
parents: 8583
diff changeset
   889
            r.append('/'.join(root) or '.')
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   890
        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
   891
            r.append(pat or '.')
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   892
        elif kind in ('rootfilesin',):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   893
            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
   894
        else: # relglob, re, relre
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   895
            r.append('.')
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   896
    return r, d
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   897
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   898
def _roots(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   899
    '''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: 31032
diff changeset
   900
    roots, dirs = _patternrootsanddirs(kindpats)
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   901
    return roots
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   902
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   903
def _rootsanddirs(kindpats):
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   904
    '''Returns roots and exact directories from patterns.
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   905
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   906
    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: 31032
diff changeset
   907
    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: 31032
diff changeset
   908
    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: 31032
diff changeset
   909
    parent directories.
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   910
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   911
    >>> _rootsanddirs(
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   912
    ...     [(b'glob', b'g/h/*', b''), (b'glob', b'g/h', b''),
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   913
    ...      (b'glob', b'g*', b'')])
32225
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32185
diff changeset
   914
    (['g/h', 'g/h', '.'], ['g', '.'])
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   915
    >>> _rootsanddirs(
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   916
    ...     [(b'rootfilesin', b'g/h', b''), (b'rootfilesin', b'', b'')])
32225
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32185
diff changeset
   917
    ([], ['g/h', '.', 'g', '.'])
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   918
    >>> _rootsanddirs(
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   919
    ...     [(b'relpath', b'r', b''), (b'path', b'p/p', b''),
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   920
    ...      (b'path', b'', b'')])
32225
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32185
diff changeset
   921
    (['r', 'p/p', '.'], ['p', '.'])
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   922
    >>> _rootsanddirs(
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   923
    ...     [(b'relglob', b'rg*', b''), (b're', b're/', b''),
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   924
    ...      (b'relre', b'rr', b'')])
32225
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32185
diff changeset
   925
    (['.', '.', '.'], ['.'])
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   926
    '''
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   927
    r, d = _patternrootsanddirs(kindpats)
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   928
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   929
    # 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: 31032
diff changeset
   930
    # 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: 31032
diff changeset
   931
    d.extend(util.dirs(d))
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   932
    d.extend(util.dirs(r))
32225
cf042543afa2 match: optimize visitdir() for patterns matching only root directory
Martin von Zweigbergk <martinvonz@google.com>
parents: 32185
diff changeset
   933
    # 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: 32185
diff changeset
   934
    d.append('.')
31033
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   935
693a5bb47854 match: making visitdir() deal with non-recursive entries
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 31032
diff changeset
   936
    return r, d
8576
ec4ed21db4b2 match: split up _normalizepats
Matt Mackall <mpm@selenic.com>
parents: 8575
diff changeset
   937
31032
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   938
def _explicitfiles(kindpats):
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   939
    '''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: 30409
diff changeset
   940
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   941
    >>> _explicitfiles([(b'path', b'foo/bar', b'')])
31032
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   942
    ['foo/bar']
34146
0fa781320203 doctest: bulk-replace string literals with b'' for Python 3
Yuya Nishihara <yuya@tcha.org>
parents: 33710
diff changeset
   943
    >>> _explicitfiles([(b'rootfilesin', b'foo/bar', b'')])
31032
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   944
    []
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   945
    '''
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   946
    # 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: 30409
diff changeset
   947
    # directory names).
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   948
    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: 30409
diff changeset
   949
    return _roots(filable)
88358446da16 match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 30409
diff changeset
   950
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   951
def _prefix(kindpats):
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   952
    '''Whether all the patterns match a prefix (i.e. recursively)'''
25213
08a8e9da0ae7 match: add source to kindpats list
Durham Goode <durham@fb.com>
parents: 25195
diff changeset
   953
    for kind, pat, source in kindpats:
33405
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   954
        if kind not in ('path', 'relpath'):
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   955
            return False
6aa643762641 match: inverse _anypats(), making it _prefix()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33380
diff changeset
   956
    return True
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   957
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   958
_commentre = None
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   959
27595
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   960
def readpatternfile(filepath, warn, sourceinfo=False):
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   961
    '''parse a pattern file, returning a list of
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   962
    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
   963
    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
   964
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   965
    trailing white space is dropped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   966
    the escape character is backslash.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   967
    comments start with #.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   968
    empty lines are skipped.
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   969
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   970
    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
   971
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   972
    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
   973
    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
   974
    re:pattern     # non-rooted regular expression
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   975
    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
   976
    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
   977
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
   978
    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
   979
    (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
   980
    '''
25216
dc562165044a ignore: use 'include:' rules instead of custom syntax
Durham Goode <durham@fb.com>
parents: 25215
diff changeset
   981
25215
4040e06e9b99 match: add 'include:' syntax
Durham Goode <durham@fb.com>
parents: 25214
diff changeset
   982
    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
25283
19d0e5efa6ca match: enable 'subinclude:' syntax
Durham Goode <durham@fb.com>
parents: 25250
diff changeset
   983
                'include': 'include', 'subinclude': 'subinclude'}
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   984
    syntax = 'relre:'
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   985
    patterns = []
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   986
31412
10c17f8bfcf3 py3: open file in rb mode
Rishabh Madan <rishabhmadan96@gmail.com>
parents: 31401
diff changeset
   987
    fp = open(filepath, 'rb')
30409
7f3593c29473 match: migrate to util.iterfile
Jun Wu <quark@fb.com>
parents: 29814
diff changeset
   988
    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
   989
        if "#" in line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   990
            global _commentre
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   991
            if not _commentre:
31429
40704098853f match: make regular expression bytes to prevent TypeError
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31412
diff changeset
   992
                _commentre = util.re.compile(br'((?:^|[^\\])(?:\\\\)*)#.*')
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   993
            # 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
   994
            m = _commentre.search(line)
d500341e4f55 match: use re2 in readpatternfile if possible
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
   995
            if m:
d500341e4f55 match: use re2 in readpatternfile if possible
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
   996
                line = line[:m.end(1)]
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   997
            # fixup properly escaped comments that survived the above
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   998
            line = line.replace("\\#", "#")
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
   999
        line = line.rstrip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1000
        if not line:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1001
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1002
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1003
        if line.startswith('syntax:'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1004
            s = line[7:].strip()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1005
            try:
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1006
                syntax = syntaxes[s]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1007
            except KeyError:
25214
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1008
                if warn:
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1009
                    warn(_("%s: ignoring invalid syntax '%s'\n") %
08703b10c3ae match: add optional warn argument
Durham Goode <durham@fb.com>
parents: 25213
diff changeset
  1010
                         (filepath, s))
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1011
            continue
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1012
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1013
        linesyntax = syntax
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1014
        for s, rels in syntaxes.iteritems():
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1015
            if line.startswith(rels):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1016
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1017
                line = line[len(rels):]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1018
                break
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1019
            elif line.startswith(s+':'):
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1020
                linesyntax = rels
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1021
                line = line[len(s) + 1:]
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1022
                break
27595
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1023
        if sourceinfo:
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1024
            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
  1025
        else:
9e2d01707e71 match: add option to return line and lineno from readpattern
Laurent Charignon <lcharignon@fb.com>
parents: 27343
diff changeset
  1026
            patterns.append(linesyntax + line)
25167
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1027
    fp.close()
6f7048cc2419 ignore: move readpatternfile to match.py
Durham Goode <durham@fb.com>
parents: 25122
diff changeset
  1028
    return patterns