ignore.py
122 lines
| 3.7 KiB
| text/x-python
|
PythonLexer
/ mercurial / ignore.py
|
r4609 | # ignore.py - ignored file handling for mercurial | ||
# | ||||
# Copyright 2007 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
|
r8225 | # This software may be used and distributed according to the terms of the | ||
|
r10263 | # GNU General Public License version 2 or any later version. | ||
|
r4609 | |||
from i18n import _ | ||||
|
r8566 | import util, match | ||
|
r8312 | import re | ||
|
r5640 | |||
_commentre = None | ||||
|
r4609 | |||
|
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: | ||||
|
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() | ||||
|
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 | ||||
|
r25066 | |||
linesyntax = syntax | ||||
|
r9091 | for s, rels in syntaxes.iteritems(): | ||
if line.startswith(rels): | ||||
|
r25066 | linesyntax = rels | ||
line = line[len(rels):] | ||||
|
r9091 | break | ||
elif line.startswith(s+':'): | ||||
|
r25066 | linesyntax = rels | ||
line = line[len(s) + 1:] | ||||
|
r9091 | break | ||
|
r25066 | patterns.append(linesyntax + line) | ||
|
r9091 | |||
return patterns, warnings | ||||
|
r4609 | |||
|
r25065 | def readignorefile(filepath, warn, skipwarning=False): | ||
try: | ||||
pats = [] | ||||
fp = open(filepath) | ||||
pats, warnings = ignorepats(fp) | ||||
fp.close() | ||||
for warning in warnings: | ||||
warn("%s: %s\n" % (filepath, warning)) | ||||
except IOError, inst: | ||||
if not skipwarning: | ||||
warn(_("skipping unreadable ignore file '%s': %s\n") % | ||||
(filepath, inst.strerror)) | ||||
return pats | ||||
|
r18087 | def readpats(root, files, warn): | ||
'''return a dict mapping ignore-file-name to list-of-patterns''' | ||||
pats = {} | ||||
for f in files: | ||||
|
r18088 | if f in pats: | ||
continue | ||||
|
r25065 | skipwarning = f == files[0] | ||
pats[f] = readignorefile(f, warn, skipwarning=skipwarning) | ||||
|
r18089 | return [(f, pats[f]) for f in files if f in pats] | ||
|
r18087 | |||
|
r4609 | def ignore(root, files, warn): | ||
|
r9091 | '''return matcher covering patterns in 'files'. | ||
|
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''' | ||||
|
r18087 | pats = readpats(root, files, warn) | ||
|
r4609 | |||
allpats = [] | ||||
|
r18089 | for f, patlist in pats: | ||
|
r13412 | allpats.extend(patlist) | ||
|
r4609 | if not allpats: | ||
return util.never | ||||
try: | ||||
|
r8567 | ignorefunc = match.match(root, '', [], allpats) | ||
|
r4609 | except util.Abort: | ||
# Re-raise an exception where the src is the right file | ||||
|
r18089 | for f, patlist in pats: | ||
|
r8566 | try: | ||
|
r8567 | match.match(root, '', [], patlist) | ||
|
r8566 | except util.Abort, inst: | ||
raise util.Abort('%s: %s' % (f, inst[0])) | ||||
|
r4609 | |||
return ignorefunc | ||||