mercurial/ignore.py
author Durham Goode <durham@fb.com>
Sat, 16 May 2015 15:45:06 -0700
changeset 25165 581e2066d802
parent 25164 1e86bb282c71
child 25166 7f53f305d4a6
permissions -rw-r--r--
ignore: combine readignorefile and _ignorefile _ignorefile did nothing except open the file. Let's combine it with readignorefile for simplicity. This will make it easier to rename and move to match.py in upcoming patches.
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
25165
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    14
def readignorefile(filepath, warn):
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    15
    '''parse a pattern file, returning a list of
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    16
    patterns. These patterns should be given to compile()
9091
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
25165
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    22
    fp = open(filepath)
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    23
    for line in fp:
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:
25165
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    41
                warn(_("%s: ignoring invalid syntax '%s'\n") % (filepath, s))
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    42
            continue
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    43
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    44
        linesyntax = syntax
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    45
        for s, rels in syntaxes.iteritems():
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    46
            if line.startswith(rels):
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    47
                linesyntax = rels
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    48
                line = line[len(rels):]
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    49
                break
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    50
            elif line.startswith(s+':'):
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    51
                linesyntax = rels
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    52
                line = line[len(s) + 1:]
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    53
                break
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
    54
        patterns.append(linesyntax + line)
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    55
25164
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    56
    fp.close()
25165
581e2066d802 ignore: combine readignorefile and _ignorefile
Durham Goode <durham@fb.com>
parents: 25164
diff changeset
    57
    return patterns
25065
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
    58
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    59
def readpats(root, files, warn):
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    60
    '''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
    61
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    62
    pats = {}
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    63
    for f in files:
18088
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
    64
        if f in pats:
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
    65
            continue
25164
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    66
        try:
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    67
            pats[f] = readignorefile(f, warn)
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    68
        except IOError, inst:
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    69
            warn(_("skipping unreadable ignore file '%s': %s\n") %
1e86bb282c71 ignore: move bad file handling out of readignorefile
Durham Goode <durham@fb.com>
parents: 25163
diff changeset
    70
                 (f, inst.strerror))
25065
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
    71
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
    72
    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
    73
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
def ignore(root, files, warn):
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
    75
    '''return matcher covering patterns in 'files'.
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
    the files parsed for patterns include:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    .hgignore in the repository root
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    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
    80
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
    trailing white space is dropped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    the escape character is backslash.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    comments start with #.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
    empty lines are skipped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
    lines can be of the following formats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
    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
    89
    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
    90
    re:pattern     # non-rooted regular expression
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
    glob:pattern   # non-rooted glob
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    92
    pattern        # pattern of the current default type'''
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    93
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
    94
    pats = readpats(root, files, warn)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
    allpats = []
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
    97
    for f, patlist in pats:
13412
58c497d0e44d remove unnecessary list comprehensions
Martin Geisler <mg@aragost.com>
parents: 10263
diff changeset
    98
        allpats.extend(patlist)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
    if not allpats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
        return util.never
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
    try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
   103
        ignorefunc = match.match(root, '', [], allpats)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
    except util.Abort:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        # 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
   106
        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
   107
            try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
   108
                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
   109
            except util.Abort, inst:
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
   110
                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
   111
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
    return ignorefunc