~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/globbing.py

  • Committer: Martin Pool
  • Date: 2010-07-16 15:20:17 UTC
  • mfrom: (5346.3.1 pathnotchild)
  • mto: This revision was merged to the branch mainline in revision 5351.
  • Revision ID: mbp@canonical.com-20100716152017-t4c73h9y1uoih7fb
PathNotChild should not give a traceback.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
22
22
 
23
23
import re
24
24
 
 
25
from bzrlib import errors
25
26
from bzrlib.trace import (
26
 
    warning
 
27
    mutter,
 
28
    warning,
27
29
    )
28
30
 
29
31
 
209
211
 
210
212
        :return A matching pattern or None if there is no matching pattern.
211
213
        """
212
 
        for regex, patterns in self._regex_patterns:
213
 
            match = regex.match(filename)
214
 
            if match:
215
 
                return patterns[match.lastindex -1]
 
214
        try:
 
215
            for regex, patterns in self._regex_patterns:
 
216
                match = regex.match(filename)
 
217
                if match:
 
218
                    return patterns[match.lastindex -1]
 
219
        except errors.InvalidPattern, e:
 
220
            # We can't show the default e.msg to the user as thats for
 
221
            # the combined pattern we sent to regex. Instead we indicate to
 
222
            # the user that an ignore file needs fixing.
 
223
            mutter('Invalid pattern found in regex: %s.', e.msg)
 
224
            e.msg = "File ~/.bazaar/ignore or .bzrignore contains errors."
 
225
            raise e
216
226
        return None
217
227
 
 
228
class ExceptionGlobster(object):
 
229
    """A Globster that supports exception patterns.
 
230
    
 
231
    Exceptions are ignore patterns prefixed with '!'.  Exception
 
232
    patterns take precedence over regular patterns and cause a 
 
233
    matching filename to return None from the match() function.  
 
234
    Patterns using a '!!' prefix are highest precedence, and act 
 
235
    as regular ignores. '!!' patterns are useful to establish ignores
 
236
    that apply under paths specified by '!' exception patterns.
 
237
    """
 
238
    
 
239
    def __init__(self,patterns):
 
240
        ignores = [[], [], []]
 
241
        for p in patterns:
 
242
            if p.startswith(u'!!'):
 
243
                ignores[2].append(p[2:])
 
244
            elif p.startswith(u'!'):
 
245
                ignores[1].append(p[1:])
 
246
            else:
 
247
                ignores[0].append(p)
 
248
        self._ignores = [Globster(i) for i in ignores]
 
249
        
 
250
    def match(self, filename):
 
251
        """Searches for a pattern that matches the given filename.
 
252
 
 
253
        :return A matching pattern or None if there is no matching pattern.
 
254
        """
 
255
        double_neg = self._ignores[2].match(filename)
 
256
        if double_neg:
 
257
            return "!!%s" % double_neg
 
258
        elif self._ignores[1].match(filename):
 
259
            return None
 
260
        else:
 
261
            return self._ignores[0].match(filename)
218
262
 
219
263
class _OrderedGlobster(Globster):
220
264
    """A Globster that keeps pattern order."""
238
282
                    prefix=r'(?:.*/)?(?!.*/)')
239
283
 
240
284
 
 
285
_slashes = re.compile(r'[\\/]+')
241
286
def normalize_pattern(pattern):
242
287
    """Converts backslashes in path patterns to forward slashes.
243
288
 
244
289
    Doesn't normalize regular expressions - they may contain escapes.
245
290
    """
246
 
    if not pattern.startswith('RE:'):
247
 
        pattern = pattern.replace('\\','/')
248
 
    return pattern.rstrip('/')
 
291
    if not (pattern.startswith('RE:') or pattern.startswith('!RE:')):
 
292
        pattern = _slashes.sub('/', pattern)
 
293
    if len(pattern) > 1:
 
294
        pattern = pattern.rstrip('/')
 
295
    return pattern