ignore.py
105 lines
| 3.3 KiB
| text/x-python
|
PythonLexer
/ mercurial / ignore.py
Matt Mackall
|
r4609 | # ignore.py - ignored file handling for mercurial | ||
# | ||||
# Copyright 2007 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Matt Mackall
|
r4609 | |||
from i18n import _ | ||||
Matt Mackall
|
r8566 | import util, match | ||
Simon Heimberg
|
r8312 | import re | ||
Matt Mackall
|
r5640 | |||
_commentre = None | ||||
Matt Mackall
|
r4609 | |||
Brendan Cully
|
r9091 | def ignorepats(lines): | ||
'''parse lines (iterable) of .hgignore text, returning a tuple of | ||||
(patterns, parse errors). These patterns should be given to compile() | ||||
to be validated and converted into a match function.''' | ||||
syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'} | ||||
syntax = 'relre:' | ||||
patterns = [] | ||||
warnings = [] | ||||
for line in lines: | ||||
Matt Mackall
|
r5640 | if "#" in line: | ||
global _commentre | ||||
if not _commentre: | ||||
_commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*') | ||||
# remove comments prefixed by an even number of escapes | ||||
line = _commentre.sub(r'\1', line) | ||||
# fixup properly escaped comments that survived the above | ||||
line = line.replace("\\#", "#") | ||||
line = line.rstrip() | ||||
Brendan Cully
|
r9091 | if not line: | ||
continue | ||||
if line.startswith('syntax:'): | ||||
s = line[7:].strip() | ||||
try: | ||||
syntax = syntaxes[s] | ||||
except KeyError: | ||||
warnings.append(_("ignoring invalid syntax '%s'") % s) | ||||
continue | ||||
pat = syntax + line | ||||
for s, rels in syntaxes.iteritems(): | ||||
if line.startswith(rels): | ||||
pat = line | ||||
break | ||||
elif line.startswith(s+':'): | ||||
pat = rels + line[len(s)+1:] | ||||
break | ||||
patterns.append(pat) | ||||
return patterns, warnings | ||||
Matt Mackall
|
r4609 | |||
def ignore(root, files, warn): | ||||
Brendan Cully
|
r9091 | '''return matcher covering patterns in 'files'. | ||
Matt Mackall
|
r4609 | |||
the files parsed for patterns include: | ||||
.hgignore in the repository root | ||||
any additional files specified in the [ui] section of ~/.hgrc | ||||
trailing white space is dropped. | ||||
the escape character is backslash. | ||||
comments start with #. | ||||
empty lines are skipped. | ||||
lines can be of the following formats: | ||||
syntax: regexp # defaults following lines to non-rooted regexps | ||||
syntax: glob # defaults following lines to non-rooted globs | ||||
re:pattern # non-rooted regular expression | ||||
glob:pattern # non-rooted glob | ||||
pattern # pattern of the current default type''' | ||||
pats = {} | ||||
for f in files: | ||||
try: | ||||
pats[f] = [] | ||||
fp = open(f) | ||||
Brendan Cully
|
r9091 | pats[f], warnings = ignorepats(fp) | ||
Matt Mackall
|
r15407 | fp.close() | ||
Brendan Cully
|
r9091 | for warning in warnings: | ||
warn("%s: %s\n" % (f, warning)) | ||||
Matt Mackall
|
r4609 | except IOError, inst: | ||
if f != files[0]: | ||||
warn(_("skipping unreadable ignore file '%s': %s\n") % | ||||
(f, inst.strerror)) | ||||
allpats = [] | ||||
Martin Geisler
|
r13412 | for patlist in pats.values(): | ||
allpats.extend(patlist) | ||||
Matt Mackall
|
r4609 | if not allpats: | ||
return util.never | ||||
try: | ||||
Matt Mackall
|
r8567 | ignorefunc = match.match(root, '', [], allpats) | ||
Matt Mackall
|
r4609 | except util.Abort: | ||
# Re-raise an exception where the src is the right file | ||||
Dirkjan Ochtman
|
r7622 | for f, patlist in pats.iteritems(): | ||
Matt Mackall
|
r8566 | try: | ||
Matt Mackall
|
r8567 | match.match(root, '', [], patlist) | ||
Matt Mackall
|
r8566 | except util.Abort, inst: | ||
raise util.Abort('%s: %s' % (f, inst[0])) | ||||
Matt Mackall
|
r4609 | |||
return ignorefunc | ||||