/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 breezy/globbing.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-08 23:30:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170608233031-3qavls2o7a1pqllj
Update imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
expressions.
21
21
"""
22
22
 
 
23
from __future__ import absolute_import
 
24
 
23
25
import re
24
26
 
25
27
from . import (
 
28
    errors,
26
29
    lazy_regex,
27
30
    )
28
31
from .trace import (
40
43
    must not contain capturing groups.
41
44
    """
42
45
 
43
 
    _expand = lazy_regex.lazy_compile(u'\\\\&')
 
46
    _expand = lazy_regex.lazy_compile(ur'\\&')
44
47
 
45
48
    def __init__(self, source=None):
46
49
        self._pat = None
77
80
    def __call__(self, text):
78
81
        if not self._pat:
79
82
            self._pat = lazy_regex.lazy_compile(
80
 
                u'|'.join([u'(%s)' % p for p in self._pats]),
81
 
                re.UNICODE)
 
83
                    u'|'.join([u'(%s)' % p for p in self._pats]),
 
84
                    re.UNICODE)
82
85
        return self._pat.sub(self._do_sub, text)
83
86
 
84
87
    def _do_sub(self, m):
90
93
 
91
94
 
92
95
_sub_named = Replacer()
93
 
_sub_named.add(r'\[:digit:\]', r'\d')
94
 
_sub_named.add(r'\[:space:\]', r'\s')
95
 
_sub_named.add(r'\[:alnum:\]', r'\w')
96
 
_sub_named.add(r'\[:ascii:\]', r'\0-\x7f')
97
 
_sub_named.add(r'\[:blank:\]', r' \t')
98
 
_sub_named.add(r'\[:cntrl:\]', r'\0-\x1f\x7f-\x9f')
 
96
_sub_named.add(ur'\[:digit:\]', ur'\d')
 
97
_sub_named.add(ur'\[:space:\]', ur'\s')
 
98
_sub_named.add(ur'\[:alnum:\]', ur'\w')
 
99
_sub_named.add(ur'\[:ascii:\]', ur'\0-\x7f')
 
100
_sub_named.add(ur'\[:blank:\]', ur' \t')
 
101
_sub_named.add(ur'\[:cntrl:\]', ur'\0-\x1f\x7f-\x9f')
99
102
 
100
103
 
101
104
def _sub_group(m):
127
130
 
128
131
_sub_re = Replacer()
129
132
_sub_re.add(u'^RE:', u'')
130
 
_sub_re.add(u'\\((?!\\?)', u'(?:')
131
 
_sub_re.add(u'\\(\\?P<.*>', _invalid_regex(u'(?:'))
132
 
_sub_re.add(u'\\(\\?P=[^)]*\\)', _invalid_regex(u''))
133
 
_sub_re.add(r'\\+$', _trailing_backslashes_regex)
 
133
_sub_re.add(u'\((?!\?)', u'(?:')
 
134
_sub_re.add(u'\(\?P<.*>', _invalid_regex(u'(?:'))
 
135
_sub_re.add(u'\(\?P=[^)]*\)', _invalid_regex(u''))
 
136
_sub_re.add(ur'\\+$', _trailing_backslashes_regex)
134
137
 
135
138
 
136
139
_sub_fullpath = Replacer()
137
 
_sub_fullpath.add(r'^RE:.*', _sub_re)  # RE:<anything> is a regex
138
 
_sub_fullpath.add(r'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]',
139
 
                  _sub_group)  # char group
140
 
_sub_fullpath.add(r'(?:(?<=/)|^)(?:\.?/)+', u'')  # canonicalize path
141
 
_sub_fullpath.add(r'\\.', r'\&')  # keep anything backslashed
142
 
_sub_fullpath.add(r'[(){}|^$+.]', r'\\&')  # escape specials
143
 
_sub_fullpath.add(r'(?:(?<=/)|^)\*\*+/', r'(?:.*/)?')  # **/ after ^ or /
144
 
_sub_fullpath.add(r'\*+', r'[^/]*')  # * elsewhere
145
 
_sub_fullpath.add(r'\?', r'[^/]')  # ? everywhere
 
140
_sub_fullpath.add(ur'^RE:.*', _sub_re) # RE:<anything> is a regex
 
141
_sub_fullpath.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', _sub_group) # char group
 
142
_sub_fullpath.add(ur'(?:(?<=/)|^)(?:\.?/)+', u'') # canonicalize path
 
143
_sub_fullpath.add(ur'\\.', ur'\&') # keep anything backslashed
 
144
_sub_fullpath.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
 
145
_sub_fullpath.add(ur'(?:(?<=/)|^)\*\*+/', ur'(?:.*/)?') # **/ after ^ or /
 
146
_sub_fullpath.add(ur'\*+', ur'[^/]*') # * elsewhere
 
147
_sub_fullpath.add(ur'\?', ur'[^/]') # ? everywhere
146
148
 
147
149
 
148
150
_sub_basename = Replacer()
149
 
_sub_basename.add(r'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]',
150
 
                  _sub_group)  # char group
151
 
_sub_basename.add(r'\\.', r'\&')  # keep anything backslashed
152
 
_sub_basename.add(r'[(){}|^$+.]', r'\\&')  # escape specials
153
 
_sub_basename.add(r'\*+', r'.*')  # * everywhere
154
 
_sub_basename.add(r'\?', r'.')  # ? everywhere
 
151
_sub_basename.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', _sub_group) # char group
 
152
_sub_basename.add(ur'\\.', ur'\&') # keep anything backslashed
 
153
_sub_basename.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
 
154
_sub_basename.add(ur'\*+', ur'.*') # * everywhere
 
155
_sub_basename.add(ur'\?', ur'.') # ? everywhere
155
156
 
156
157
 
157
158
def _sub_extension(pattern):
187
188
    # starting with the shortest and going to the longest.
188
189
    # As some Python version don't support ordered dicts the list below is
189
190
    # used to select inputs for _add_pattern in a specific order.
190
 
    pattern_types = ["extension", "basename", "fullpath"]
 
191
    pattern_types = [ "extension", "basename", "fullpath" ]
191
192
 
192
193
    pattern_info = {
193
 
        "extension": {
194
 
            "translator": _sub_extension,
195
 
            "prefix": r'(?:.*/)?(?!.*/)(?:.*\.)'
196
 
        },
197
 
        "basename": {
198
 
            "translator": _sub_basename,
199
 
            "prefix": r'(?:.*/)?(?!.*/)'
200
 
        },
201
 
        "fullpath": {
202
 
            "translator": _sub_fullpath,
203
 
            "prefix": r''
 
194
        "extension" : {
 
195
            "translator" : _sub_extension,
 
196
            "prefix" : r'(?:.*/)?(?!.*/)(?:.*\.)'
 
197
        },
 
198
        "basename" : {
 
199
            "translator" : _sub_basename,
 
200
            "prefix" : r'(?:.*/)?(?!.*/)'
 
201
        },
 
202
        "fullpath" : {
 
203
            "translator" : _sub_fullpath,
 
204
            "prefix" : r''
204
205
        },
205
206
    }
206
207
 
207
208
    def __init__(self, patterns):
208
209
        self._regex_patterns = []
209
210
        pattern_lists = {
210
 
            "extension": [],
211
 
            "basename": [],
212
 
            "fullpath": [],
 
211
            "extension" : [],
 
212
            "basename" : [],
 
213
            "fullpath" : [],
213
214
        }
214
215
        for pat in patterns:
215
216
            pat = normalize_pattern(pat)
217
218
        pi = Globster.pattern_info
218
219
        for t in Globster.pattern_types:
219
220
            self._add_patterns(pattern_lists[t], pi[t]["translator"],
220
 
                               pi[t]["prefix"])
 
221
                pi[t]["prefix"])
221
222
 
222
223
    def _add_patterns(self, patterns, translator, prefix=''):
223
224
        while patterns:
240
241
            for regex, patterns in self._regex_patterns:
241
242
                match = regex.match(filename)
242
243
                if match:
243
 
                    return patterns[match.lastindex - 1]
244
 
        except lazy_regex.InvalidPattern as e:
 
244
                    return patterns[match.lastindex -1]
 
245
        except errors.InvalidPattern as e:
245
246
            # We can't show the default e.msg to the user as thats for
246
247
            # the combined pattern we sent to regex. Instead we indicate to
247
248
            # the user that an ignore file needs fixing.
248
249
            mutter('Invalid pattern found in regex: %s.', e.msg)
249
 
            e.msg = (
250
 
                "File ~/.config/breezy/ignore or "
251
 
                ".bzrignore contains error(s).")
 
250
            e.msg = "File ~/.bazaar/ignore or .bzrignore contains error(s)."
252
251
            bad_patterns = ''
253
252
            for _, patterns in self._regex_patterns:
254
253
                for p in patterns:
282
281
        see: globbing.normalize_pattern
283
282
        """
284
283
        result = True
285
 
        translator = Globster.pattern_info[Globster.identify(
286
 
            pattern)]["translator"]
 
284
        translator = Globster.pattern_info[Globster.identify(pattern)]["translator"]
287
285
        tpattern = '(%s)' % translator(pattern)
288
286
        try:
289
287
            re_obj = lazy_regex.lazy_compile(tpattern, re.UNICODE)
290
 
            re_obj.search("")  # force compile
291
 
        except lazy_regex.InvalidPattern:
 
288
            re_obj.search("") # force compile
 
289
        except errors.InvalidPattern as e:
292
290
            result = False
293
291
        return result
294
292
 
295
293
 
296
294
class ExceptionGlobster(object):
297
295
    """A Globster that supports exception patterns.
298
 
 
 
296
    
299
297
    Exceptions are ignore patterns prefixed with '!'.  Exception
300
 
    patterns take precedence over regular patterns and cause a
301
 
    matching filename to return None from the match() function.
302
 
    Patterns using a '!!' prefix are highest precedence, and act
 
298
    patterns take precedence over regular patterns and cause a 
 
299
    matching filename to return None from the match() function.  
 
300
    Patterns using a '!!' prefix are highest precedence, and act 
303
301
    as regular ignores. '!!' patterns are useful to establish ignores
304
302
    that apply under paths specified by '!' exception patterns.
305
303
    """
306
 
 
307
 
    def __init__(self, patterns):
 
304
    
 
305
    def __init__(self,patterns):
308
306
        ignores = [[], [], []]
309
307
        for p in patterns:
310
308
            if p.startswith(u'!!'):
314
312
            else:
315
313
                ignores[0].append(p)
316
314
        self._ignores = [Globster(i) for i in ignores]
317
 
 
 
315
        
318
316
    def match(self, filename):
319
317
        """Searches for a pattern that matches the given filename.
320
318
 
328
326
        else:
329
327
            return self._ignores[0].match(filename)
330
328
 
331
 
 
332
329
class _OrderedGlobster(Globster):
333
330
    """A Globster that keeps pattern order."""
334
331
 
343
340
            pat = normalize_pattern(pat)
344
341
            t = Globster.identify(pat)
345
342
            self._add_patterns([pat], Globster.pattern_info[t]["translator"],
346
 
                               Globster.pattern_info[t]["prefix"])
 
343
                Globster.pattern_info[t]["prefix"])
347
344
 
348
345
 
349
346
_slashes = lazy_regex.lazy_compile(r'[\\/]+')
350
 
 
351
 
 
352
347
def normalize_pattern(pattern):
353
348
    """Converts backslashes in path patterns to forward slashes.
354
349