##// END OF EJS Templates
ignore: only read an ignore file once
Bryan O'Sullivan -
r18088:52620e5d default
parent child Browse files
Show More
@@ -1,111 +1,113 b''
1 1 # ignore.py - ignored file handling for mercurial
2 2 #
3 3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from i18n import _
9 9 import util, match
10 10 import re
11 11
12 12 _commentre = None
13 13
14 14 def ignorepats(lines):
15 15 '''parse lines (iterable) of .hgignore text, returning a tuple of
16 16 (patterns, parse errors). These patterns should be given to compile()
17 17 to be validated and converted into a match function.'''
18 18 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
19 19 syntax = 'relre:'
20 20 patterns = []
21 21 warnings = []
22 22
23 23 for line in lines:
24 24 if "#" in line:
25 25 global _commentre
26 26 if not _commentre:
27 27 _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
28 28 # remove comments prefixed by an even number of escapes
29 29 line = _commentre.sub(r'\1', line)
30 30 # fixup properly escaped comments that survived the above
31 31 line = line.replace("\\#", "#")
32 32 line = line.rstrip()
33 33 if not line:
34 34 continue
35 35
36 36 if line.startswith('syntax:'):
37 37 s = line[7:].strip()
38 38 try:
39 39 syntax = syntaxes[s]
40 40 except KeyError:
41 41 warnings.append(_("ignoring invalid syntax '%s'") % s)
42 42 continue
43 43 pat = syntax + line
44 44 for s, rels in syntaxes.iteritems():
45 45 if line.startswith(rels):
46 46 pat = line
47 47 break
48 48 elif line.startswith(s+':'):
49 49 pat = rels + line[len(s) + 1:]
50 50 break
51 51 patterns.append(pat)
52 52
53 53 return patterns, warnings
54 54
55 55 def readpats(root, files, warn):
56 56 '''return a dict mapping ignore-file-name to list-of-patterns'''
57 57
58 58 pats = {}
59 59 for f in files:
60 if f in pats:
61 continue
60 62 try:
61 63 pats[f] = []
62 64 fp = open(f)
63 65 pats[f], warnings = ignorepats(fp)
64 66 fp.close()
65 67 for warning in warnings:
66 68 warn("%s: %s\n" % (f, warning))
67 69 except IOError, inst:
68 70 if f != files[0]:
69 71 warn(_("skipping unreadable ignore file '%s': %s\n") %
70 72 (f, inst.strerror))
71 73 return pats
72 74
73 75 def ignore(root, files, warn):
74 76 '''return matcher covering patterns in 'files'.
75 77
76 78 the files parsed for patterns include:
77 79 .hgignore in the repository root
78 80 any additional files specified in the [ui] section of ~/.hgrc
79 81
80 82 trailing white space is dropped.
81 83 the escape character is backslash.
82 84 comments start with #.
83 85 empty lines are skipped.
84 86
85 87 lines can be of the following formats:
86 88
87 89 syntax: regexp # defaults following lines to non-rooted regexps
88 90 syntax: glob # defaults following lines to non-rooted globs
89 91 re:pattern # non-rooted regular expression
90 92 glob:pattern # non-rooted glob
91 93 pattern # pattern of the current default type'''
92 94
93 95 pats = readpats(root, files, warn)
94 96
95 97 allpats = []
96 98 for patlist in pats.values():
97 99 allpats.extend(patlist)
98 100 if not allpats:
99 101 return util.never
100 102
101 103 try:
102 104 ignorefunc = match.match(root, '', [], allpats)
103 105 except util.Abort:
104 106 # Re-raise an exception where the src is the right file
105 107 for f, patlist in pats.iteritems():
106 108 try:
107 109 match.match(root, '', [], patlist)
108 110 except util.Abort, inst:
109 111 raise util.Abort('%s: %s' % (f, inst[0]))
110 112
111 113 return ignorefunc
General Comments 0
You need to be logged in to leave comments. Login now