179
179
so are matched first, then the basename patterns, then the fullpath
187
TYPE_FULLPATH : _sub_fullpath,
188
TYPE_BASENAME : _sub_basename,
189
TYPE_EXTENSION : _sub_extension,
192
# Prefixes used to combine various patterns.
193
# See: Globster._add_patterns
196
TYPE_BASENAME : r'(?:.*/)?(?!.*/)',
197
TYPE_EXTENSION : r'(?:.*/)?(?!.*/)(?:.*\.)',
182
200
def __init__(self, patterns):
183
201
self._regex_patterns = []
203
Globster.TYPE_FULLPATH : [],
204
Globster.TYPE_EXTENSION : [],
205
Globster.TYPE_BASENAME : [],
187
207
for pat in patterns:
188
208
pat = normalize_pattern(pat)
189
if pat.startswith(u'RE:') or u'/' in pat:
190
path_patterns.append(pat)
191
elif pat.startswith(u'*.'):
192
ext_patterns.append(pat)
194
base_patterns.append(pat)
195
self._add_patterns(ext_patterns,_sub_extension,
196
prefix=r'(?:.*/)?(?!.*/)(?:.*\.)')
197
self._add_patterns(base_patterns,_sub_basename,
198
prefix=r'(?:.*/)?(?!.*/)')
199
self._add_patterns(path_patterns,_sub_fullpath)
209
pattern_lists[Globster.identify(pat)].append(pat)
210
for pattern_type, patterns in pattern_lists.iteritems():
211
self._add_patterns(patterns,
212
Globster.translators[pattern_type],
213
Globster.prefixes[pattern_type])
201
215
def _add_patterns(self, patterns, translator, prefix=''):
221
235
# the combined pattern we sent to regex. Instead we indicate to
222
236
# the user that an ignore file needs fixing.
223
237
mutter('Invalid pattern found in regex: %s.', e.msg)
224
e.msg = "File ~/.bazaar/ignore or .bzrignore contains errors."
238
e.msg = "File ~/.bazaar/ignore or .bzrignore contains error(s)."
240
for _, patterns in self._regex_patterns:
242
if not Globster.is_pattern_valid(p):
243
bad_patterns += ('\n %s' % p)
244
e.msg += bad_patterns
249
def identify(pattern):
250
"""Returns pattern category.
252
:param pattern: normalized pattern.
253
Identify if a pattern is fullpath, basename or extension
254
and returns the appropriate type.
256
if pattern.startswith(u'RE:') or u'/' in pattern:
257
return Globster.TYPE_FULLPATH
258
elif pattern.startswith(u'*.'):
259
return Globster.TYPE_EXTENSION
261
return Globster.TYPE_BASENAME
264
def is_pattern_valid(pattern):
265
"""Returns True if pattern is valid.
267
:param pattern: Normalized pattern.
268
is_pattern_valid() assumes pattern to be normalized.
269
see: globbing.normalize_pattern
272
translator = Globster.translators[Globster.identify(pattern)]
273
tpattern = '(%s)' % translator(pattern)
275
re_obj = re.compile(tpattern, re.UNICODE)
276
re_obj.search("") # force compile
277
except errors.InvalidPattern, e:
228
282
class ExceptionGlobster(object):
229
283
"""A Globster that supports exception patterns.
272
326
self._regex_patterns = []
273
327
for pat in patterns:
274
328
pat = normalize_pattern(pat)
275
if pat.startswith(u'RE:') or u'/' in pat:
276
self._add_patterns([pat], _sub_fullpath)
277
elif pat.startswith(u'*.'):
278
self._add_patterns([pat], _sub_extension,
279
prefix=r'(?:.*/)?(?!.*/)(?:.*\.)')
281
self._add_patterns([pat], _sub_basename,
282
prefix=r'(?:.*/)?(?!.*/)')
329
pat_type = Globster.identify(pat)
330
self._add_patterns([pat], Globster.translators[pat_type],
331
Globster.prefixes[pat_type])
285
334
_slashes = re.compile(r'[\\/]+')