~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/globbing.py

'bzr ignore' now fails on bad pattern.

Show diffs side-by-side

added added

removed removed

Lines of Context:
179
179
    so are matched first, then the basename patterns, then the fullpath
180
180
    patterns.
181
181
    """
 
182
    TYPE_FULLPATH = 1
 
183
    TYPE_BASENAME = 2
 
184
    TYPE_EXTENSION = 3
 
185
 
 
186
    translators = {
 
187
        TYPE_FULLPATH : _sub_fullpath,
 
188
        TYPE_BASENAME : _sub_basename,
 
189
        TYPE_EXTENSION : _sub_extension,
 
190
    }
 
191
 
 
192
    # Prefixes used to combine various patterns.
 
193
    # See: Globster._add_patterns
 
194
    PREFIX_EXTENSION = r'(?:.*/)?(?!.*/)(?:.*\.)'
 
195
    PREFIX_BASENAME = r'(?:.*/)?(?!.*/)'
 
196
    PREFIX_FULLPATH = r''
 
197
 
 
198
    prefixes = {
 
199
        TYPE_FULLPATH : PREFIX_FULLPATH,
 
200
        TYPE_BASENAME : PREFIX_BASENAME,
 
201
        TYPE_EXTENSION : PREFIX_EXTENSION,
 
202
    }
 
203
 
182
204
    def __init__(self, patterns):
183
205
        self._regex_patterns = []
184
206
        path_patterns = []
185
207
        base_patterns = []
186
208
        ext_patterns = []
 
209
        pattern_lists = {
 
210
            Globster.TYPE_FULLPATH : path_patterns,
 
211
            Globster.TYPE_EXTENSION : ext_patterns,
 
212
            Globster.TYPE_BASENAME : base_patterns,
 
213
        }
187
214
        for pat in patterns:
188
215
            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)
193
 
            else:
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)
 
216
            pattern_lists[Globster.identify(pat)].append(pat)
 
217
        for k, v in pattern_lists.iteritems():
 
218
            self._add_patterns(v, Globster.translators[k],
 
219
                Globster.prefixes[k])
200
220
 
201
221
    def _add_patterns(self, patterns, translator, prefix=''):
202
222
        while patterns:
225
245
            raise e
226
246
        return None
227
247
 
 
248
    @staticmethod
 
249
    def identify(pattern):
 
250
        """Returns pattern category.
 
251
 
 
252
        :param pattern: normalized pattern.
 
253
        Identify if a pattern is fullpath, basename or extension
 
254
        and returns the appropriate type.
 
255
        """
 
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
 
260
        else:
 
261
            return Globster.TYPE_BASENAME
 
262
 
 
263
    @staticmethod
 
264
    def is_pattern_valid(pattern):
 
265
        """Returns True if pattern is valid.
 
266
 
 
267
        :param pattern: Normalized pattern.
 
268
        is_pattern_valid() assumes pattern to be normalized.
 
269
        see: globbing.normalize_pattern
 
270
        """
 
271
        result = True
 
272
        translator = Globster.translators[Globster.identify(pattern)]
 
273
        tpattern = '(%s)' % translator(pattern)
 
274
        try:
 
275
            re_obj = re.compile(tpattern, re.UNICODE)
 
276
            re_obj.search("") # force compile
 
277
        except errors.InvalidPattern, e:
 
278
            result = False
 
279
        return result
 
280
 
 
281
 
 
282
 
228
283
class ExceptionGlobster(object):
229
284
    """A Globster that supports exception patterns.
230
285
    
272
327
        self._regex_patterns = []
273
328
        for pat in patterns:
274
329
            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'(?:.*/)?(?!.*/)(?:.*\.)')
280
 
            else:
281
 
                self._add_patterns([pat], _sub_basename,
282
 
                    prefix=r'(?:.*/)?(?!.*/)')
 
330
            pat_type = Globster.identify(pat)
 
331
            self._add_patterns([pat], Globster.translators[pat_type],
 
332
                Globster.prefixes[pat_type])
283
333
 
284
334
 
285
335
_slashes = re.compile(r'[\\/]+')