/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/globbing.py

  • Committer: Parth Malwankar
  • Date: 2010-07-19 14:25:37 UTC
  • mto: (5050.3.15 2.2)
  • mto: This revision was merged to the branch mainline in revision 5365.
  • Revision ID: parth.malwankar@gmail.com-20100719142537-djnb98492yri3k92
_add_patterns is now done in a specific order in Globster

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
177
179
    so are matched first, then the basename patterns, then the fullpath
178
180
    patterns.
179
181
    """
 
182
    TYPE_FULLPATH = 1
 
183
    TYPE_BASENAME = 2
 
184
    TYPE_EXTENSION = 3
 
185
    # We want to _add_patterns in a specific order (as per type_list below)
 
186
    # starting with the shortest and going to the longest.
 
187
    # As some Python version don't support ordered dicts the list below is
 
188
    # used to select inputs for _add_pattern in a specific order.
 
189
    type_list = [ TYPE_EXTENSION, TYPE_BASENAME, TYPE_FULLPATH ]
 
190
 
 
191
 
 
192
    translators = {
 
193
        TYPE_FULLPATH : _sub_fullpath,
 
194
        TYPE_BASENAME : _sub_basename,
 
195
        TYPE_EXTENSION : _sub_extension,
 
196
    }
 
197
 
 
198
    # Prefixes used to combine various patterns.
 
199
    # See: Globster._add_patterns
 
200
    prefixes = {
 
201
        TYPE_FULLPATH : r'',
 
202
        TYPE_BASENAME : r'(?:.*/)?(?!.*/)',
 
203
        TYPE_EXTENSION : r'(?:.*/)?(?!.*/)(?:.*\.)',
 
204
    }
 
205
 
180
206
    def __init__(self, patterns):
181
207
        self._regex_patterns = []
182
 
        path_patterns = []
183
 
        base_patterns = []
184
 
        ext_patterns = []
 
208
        pattern_lists = {
 
209
            Globster.TYPE_FULLPATH : [],
 
210
            Globster.TYPE_EXTENSION : [],
 
211
            Globster.TYPE_BASENAME : [],
 
212
        }
185
213
        for pat in patterns:
186
214
            pat = normalize_pattern(pat)
187
 
            if pat.startswith(u'RE:') or u'/' in pat:
188
 
                path_patterns.append(pat)
189
 
            elif pat.startswith(u'*.'):
190
 
                ext_patterns.append(pat)
191
 
            else:
192
 
                base_patterns.append(pat)
193
 
        self._add_patterns(ext_patterns,_sub_extension,
194
 
            prefix=r'(?:.*/)?(?!.*/)(?:.*\.)')
195
 
        self._add_patterns(base_patterns,_sub_basename,
196
 
            prefix=r'(?:.*/)?(?!.*/)')
197
 
        self._add_patterns(path_patterns,_sub_fullpath)
 
215
            pattern_lists[Globster.identify(pat)].append(pat)
 
216
        for t in Globster.type_list:
 
217
            self._add_patterns(pattern_lists[t], Globster.translators[t],
 
218
                Globster.prefixes[t])
198
219
 
199
220
    def _add_patterns(self, patterns, translator, prefix=''):
200
221
        while patterns:
209
230
 
210
231
        :return A matching pattern or None if there is no matching pattern.
211
232
        """
212
 
        for regex, patterns in self._regex_patterns:
213
 
            match = regex.match(filename)
214
 
            if match:
215
 
                return patterns[match.lastindex -1]
 
233
        try:
 
234
            for regex, patterns in self._regex_patterns:
 
235
                match = regex.match(filename)
 
236
                if match:
 
237
                    return patterns[match.lastindex -1]
 
238
        except errors.InvalidPattern, e:
 
239
            # We can't show the default e.msg to the user as thats for
 
240
            # the combined pattern we sent to regex. Instead we indicate to
 
241
            # the user that an ignore file needs fixing.
 
242
            mutter('Invalid pattern found in regex: %s.', e.msg)
 
243
            e.msg = "File ~/.bazaar/ignore or .bzrignore contains error(s)."
 
244
            bad_patterns = ''
 
245
            for _, patterns in self._regex_patterns:
 
246
                for p in patterns:
 
247
                    if not Globster.is_pattern_valid(p):
 
248
                        bad_patterns += ('\n  %s' % p)
 
249
            e.msg += bad_patterns
 
250
            raise e
216
251
        return None
217
252
 
 
253
    @staticmethod
 
254
    def identify(pattern):
 
255
        """Returns pattern category.
 
256
 
 
257
        :param pattern: normalized pattern.
 
258
        Identify if a pattern is fullpath, basename or extension
 
259
        and returns the appropriate type.
 
260
        """
 
261
        if pattern.startswith(u'RE:') or u'/' in pattern:
 
262
            return Globster.TYPE_FULLPATH
 
263
        elif pattern.startswith(u'*.'):
 
264
            return Globster.TYPE_EXTENSION
 
265
        else:
 
266
            return Globster.TYPE_BASENAME
 
267
 
 
268
    @staticmethod
 
269
    def is_pattern_valid(pattern):
 
270
        """Returns True if pattern is valid.
 
271
 
 
272
        :param pattern: Normalized pattern.
 
273
        is_pattern_valid() assumes pattern to be normalized.
 
274
        see: globbing.normalize_pattern
 
275
        """
 
276
        result = True
 
277
        translator = Globster.translators[Globster.identify(pattern)]
 
278
        tpattern = '(%s)' % translator(pattern)
 
279
        try:
 
280
            re_obj = re.compile(tpattern, re.UNICODE)
 
281
            re_obj.search("") # force compile
 
282
        except errors.InvalidPattern, e:
 
283
            result = False
 
284
        return result
 
285
 
 
286
 
218
287
class ExceptionGlobster(object):
219
288
    """A Globster that supports exception patterns.
220
289
    
262
331
        self._regex_patterns = []
263
332
        for pat in patterns:
264
333
            pat = normalize_pattern(pat)
265
 
            if pat.startswith(u'RE:') or u'/' in pat:
266
 
                self._add_patterns([pat], _sub_fullpath)
267
 
            elif pat.startswith(u'*.'):
268
 
                self._add_patterns([pat], _sub_extension,
269
 
                    prefix=r'(?:.*/)?(?!.*/)(?:.*\.)')
270
 
            else:
271
 
                self._add_patterns([pat], _sub_basename,
272
 
                    prefix=r'(?:.*/)?(?!.*/)')
 
334
            pat_type = Globster.identify(pat)
 
335
            self._add_patterns([pat], Globster.translators[pat_type],
 
336
                Globster.prefixes[pat_type])
273
337
 
274
338
 
275
339
_slashes = re.compile(r'[\\/]+')