mercurial/ignore.py
author Bryan O'Sullivan <bos@serpentine.com>
Thu, 26 Mar 2009 13:12:11 -0700
changeset 8327 aa25be1c2889
parent 8312 b87a50b7125c
child 8566 744d6322b05b
permissions -rw-r--r--
atomictempfile: delegate to posixfile instead of inheriting from it
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
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7622
diff changeset
     6
# GNU General Public License version 2, incorporated herein by reference.
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 _
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
     9
import util
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
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
def _parselines(fp):
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
    for line in fp:
5640
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    16
        if "#" in line:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    17
            global _commentre
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    18
            if not _commentre:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    19
                _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    20
            # remove comments prefixed by an even number of escapes
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    21
            line = _commentre.sub(r'\1', line)
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    22
            # fixup properly escaped comments that survived the above
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    23
            line = line.replace("\\#", "#")
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
    24
        line = line.rstrip()
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
        if line:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
            yield line
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
def ignore(root, files, warn):
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
    '''return the contents of .hgignore files as a list of patterns.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
    the files parsed for patterns include:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    .hgignore in the repository root
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
    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
    34
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
    trailing white space is dropped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
    the escape character is backslash.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
    comments start with #.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
    empty lines are skipped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
    lines can be of the following formats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
    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
    43
    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
    44
    re:pattern     # non-rooted regular expression
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
    glob:pattern   # non-rooted glob
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
    pattern        # pattern of the current default type'''
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
    syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
    pats = {}
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
    for f in files:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
        try:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
            pats[f] = []
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
            fp = open(f)
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
            syntax = 'relre:'
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
            for line in _parselines(fp):
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
                if line.startswith('syntax:'):
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
                    s = line[7:].strip()
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
                    try:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
                        syntax = syntaxes[s]
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
                    except KeyError:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
                        warn(_("%s: ignoring invalid syntax '%s'\n") % (f, s))
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
                    continue
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                pat = syntax + line
7622
4dd7b28003d2 use dict.iteritems() rather than dict.items()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5640
diff changeset
    64
                for s, rels in syntaxes.iteritems():
5029
ac97e065cfc7 Fix re: and glob: patterns in .hgignore (reported by Brad Schick)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4609
diff changeset
    65
                    if line.startswith(rels):
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
                        pat = line
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
                        break
5029
ac97e065cfc7 Fix re: and glob: patterns in .hgignore (reported by Brad Schick)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4609
diff changeset
    68
                    elif line.startswith(s+':'):
ac97e065cfc7 Fix re: and glob: patterns in .hgignore (reported by Brad Schick)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4609
diff changeset
    69
                        pat = rels + line[len(s)+1:]
ac97e065cfc7 Fix re: and glob: patterns in .hgignore (reported by Brad Schick)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4609
diff changeset
    70
                        break
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
                pats[f].append(pat)
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
        except IOError, inst:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
            if f != files[0]:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
                warn(_("skipping unreadable ignore file '%s': %s\n") %
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
                     (f, inst.strerror))
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
    allpats = []
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
    [allpats.extend(patlist) for patlist in pats.values()]
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
    if not allpats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
        return util.never
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
    try:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
        files, ignorefunc, anypats = (
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
            util.matcher(root, inc=allpats, src='.hgignore'))
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
    except util.Abort:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
        # Re-raise an exception where the src is the right file
7622
4dd7b28003d2 use dict.iteritems() rather than dict.items()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5640
diff changeset
    87
        for f, patlist in pats.iteritems():
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
            files, ignorefunc, anypats = (
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    89
                util.matcher(root, inc=patlist, src=f))
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    90
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    91
    return ignorefunc