mercurial/ignore.py
author Durham Goode <durham@fb.com>
Mon, 10 Nov 2014 10:44:42 -0800
branchstable
changeset 23246 643c58303fb0
parent 18089 0127366df8fe
child 25065 8cf7f0c4cb14
permissions -rw-r--r--
rebase: fix rebase with no common ancestors (issue4446) The new rebase revset didn't check for the case when there are no common ancestors. Now it does. The new behavior should be the same as the pre-3.2 behavior. Added a test.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# ignore.py - ignored file handling for mercurial
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2007 Matt Mackall <mpm@selenic.com>
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7622
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: 9091
diff changeset
     6
# GNU General Public License version 2 or any later version.
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
from i18n import _
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
     9
import util, match
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
    10
import re
5640
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    11
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    12
_commentre = None
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    14
def ignorepats(lines):
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    15
    '''parse lines (iterable) of .hgignore text, returning a tuple of
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    16
    (patterns, parse errors). These patterns should be given to compile()
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    17
    to be validated and converted into a match function.'''
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    18
    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    19
    syntax = 'relre:'
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    20
    patterns = []
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    21
    warnings = []
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    22
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    23
    for line in lines:
5640
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    24
        if "#" in line:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    25
            global _commentre
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    26
            if not _commentre:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    27
                _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    28
            # remove comments prefixed by an even number of escapes
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    29
            line = _commentre.sub(r'\1', line)
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    30
            # fixup properly escaped comments that survived the above
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    31
            line = line.replace("\\#", "#")
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    32
        line = line.rstrip()
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    33
        if not line:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    34
            continue
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    35
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    36
        if line.startswith('syntax:'):
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    37
            s = line[7:].strip()
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    38
            try:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    39
                syntax = syntaxes[s]
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    40
            except KeyError:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    41
                warnings.append(_("ignoring invalid syntax '%s'") % s)
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    42
            continue
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    43
        pat = syntax + line
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    44
        for s, rels in syntaxes.iteritems():
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    45
            if line.startswith(rels):
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    46
                pat = line
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    47
                break
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    48
            elif line.startswith(s+':'):
18054
b35e3364f94a check-code: there must also be whitespace between ')' and operator
Mads Kiilerich <madski@unity3d.com>
parents: 15407
diff changeset
    49
                pat = rels + line[len(s) + 1:]
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    50
                break
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    51
        patterns.append(pat)
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    52
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    53
    return patterns, warnings
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    55
def readpats(root, files, warn):
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    56
    '''return a dict mapping ignore-file-name to list-of-patterns'''
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    57
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    58
    pats = {}
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    59
    for f in files:
18088
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
    60
        if f in pats:
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
    61
            continue
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    62
        try:
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    63
            pats[f] = []
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    64
            fp = open(f)
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    65
            pats[f], warnings = ignorepats(fp)
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    66
            fp.close()
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    67
            for warning in warnings:
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    68
                warn("%s: %s\n" % (f, warning))
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    69
        except IOError, inst:
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    70
            if f != files[0]:
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    71
                warn(_("skipping unreadable ignore file '%s': %s\n") %
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    72
                     (f, inst.strerror))
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
    73
    return [(f, pats[f]) for f in files if f in pats]
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    74
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
def ignore(root, files, warn):
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    76
    '''return matcher covering patterns in 'files'.
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    the files parsed for patterns include:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    .hgignore in the repository root
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
    any additional files specified in the [ui] section of ~/.hgrc
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    trailing white space is dropped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    the escape character is backslash.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
    comments start with #.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    empty lines are skipped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
    lines can be of the following formats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
    syntax: regexp # defaults following lines to non-rooted regexps
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
    syntax: glob   # defaults following lines to non-rooted globs
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
    re:pattern     # non-rooted regular expression
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
    glob:pattern   # non-rooted glob
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
    pattern        # pattern of the current default type'''
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    94
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    95
    pats = readpats(root, files, warn)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
    allpats = []
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
    98
    for f, patlist in pats:
13412
58c497d0e44d remove unnecessary list comprehensions
Martin Geisler <mg@aragost.com>
parents: 10263
diff changeset
    99
        allpats.extend(patlist)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
    if not allpats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
        return util.never
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
    try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
   104
        ignorefunc = match.match(root, '', [], allpats)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
    except util.Abort:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
        # Re-raise an exception where the src is the right file
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
   107
        for f, patlist in pats:
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
   108
            try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
   109
                match.match(root, '', [], patlist)
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
   110
            except util.Abort, inst:
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
   111
                raise util.Abort('%s: %s' % (f, inst[0]))
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
    return ignorefunc