~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/glob.py

  • Committer: Kent Gibson
  • Date: 2006-11-28 17:01:36 UTC
  • mto: (2178.1.1 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 2179.
  • Revision ID: warthog618@gmail.com-20061128170136-b11d15f1de7992af
Ignore pattern matcher (glob.py) patches:
 - '*' now matches leading '.' as per fnmatch.
 - Support '**' extension as per zsh.  
 - fixed case-insensitive match on case-insensitive platforms.
 - Updated NEWS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
"""
22
22
 
23
23
import re
 
24
import os.path
24
25
 
25
26
from bzrlib.trace import (
26
27
    mutter, 
95
96
_sub_named.add(ur'\[:cntrl:\]', ur'\0-\x1f\x7f-\x9f')
96
97
 
97
98
 
98
 
_sub_leading_named = Replacer()
99
 
_sub_leading_named.add(ur'\[:ascii:\]', ur'\0-\x2d\x2f-\x7f')
100
 
_sub_leading_named.add_replacer(_sub_named)
101
 
 
102
 
 
103
99
def _sub_group(m):
104
100
    if m[1] in (u'!', u'^'):
105
101
        return u'[^' + _sub_named(m[2:-1]) + u']'
106
102
    return u'[' + _sub_named(m[1:-1]) + u']'
107
103
 
108
104
 
109
 
def _sub_leading_group(m):
110
 
    if m[1] in (u'!', u'^'):
111
 
        return u'[^.' + _sub_named(m[2:-1]) + u']'
112
 
    return u'[' + _sub_leading_named(m[1:-1]) + u']'
113
 
        
114
 
 
115
105
def _invalid_regex(repl):
116
106
    def _(m):
117
107
        warning(u"'%s' not allowed withing regexp. Replacing with '%s'" %
127
117
_sub_re.add(u'\(\?P=[^)]*\)', _invalid_regex(u''))
128
118
 
129
119
 
130
 
_sub_shell = Replacer()
131
 
_sub_shell.add(ur'^RE:.*', _sub_re) # RE:<anything> is a regex
132
 
_sub_shell.add(ur'(?:(?<=/)|^)\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', 
133
 
    _sub_leading_group) # char group
134
 
_sub_shell.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', _sub_group) # char group
135
 
_sub_shell.add(ur'(?:(?<=/)|^)(?:\.?/)+', u'') # canonicalize path
136
 
_sub_shell.add(ur'\\.', ur'\&') # keep anything backslashed
137
 
_sub_shell.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
138
 
_sub_shell.add(ur'(?:(?<=/)|^)\*\.', ur'[^./][^/]*\.') # *. after /|^
139
 
_sub_shell.add(ur'(?:(?<=/)|^)\*', ur'(?:[^./][^/]*)?') # * after /|^
140
 
_sub_shell.add(ur'\*', ur'[^/]*') # * elsewhere
141
 
_sub_shell.add(ur'(?:(?<=/)|^)\?', ur'[^./]') # ? after /|^
142
 
_sub_shell.add(ur'\?', ur'[^/]') # ? elsewhere
143
 
 
144
 
 
145
 
_sub_shell_basename = Replacer()
146
 
_sub_shell_basename.add(ur'^\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]',
147
 
    _sub_leading_group) # char group
148
 
_sub_shell_basename.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]',
149
 
    _sub_group) # char group
150
 
_sub_shell_basename.add(ur'\\.', ur'\&') # keep anything backslashed
151
 
_sub_shell_basename.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
152
 
_sub_shell_basename.add(ur'^\*\.', ur'[^.].*\.') # *. after ^
153
 
_sub_shell_basename.add(ur'^\*', ur'(?:[^.].*)?') # * after ^
154
 
_sub_shell_basename.add(ur'\*', ur'.*') # * elsewhere
155
 
_sub_shell_basename.add(ur'^\?', ur'[^.]') # ? after ^
156
 
_sub_shell_basename.add(ur'\?', ur'.') # ? elsewhere
157
 
 
158
 
 
159
 
def _sub_shell_extension(pattern):
160
 
    return _sub_shell_basename(pattern[2:])
 
120
_sub_fullpath = Replacer()
 
121
_sub_fullpath.add(ur'^RE:.*', _sub_re) # RE:<anything> is a regex
 
122
_sub_fullpath.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', _sub_group) # char group
 
123
_sub_fullpath.add(ur'(?:(?<=/)|^)(?:\.?/)+', u'') # canonicalize path
 
124
_sub_fullpath.add(ur'\\.', ur'\&') # keep anything backslashed
 
125
_sub_fullpath.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
 
126
_sub_fullpath.add(ur'(?:(?<=/)|^)\*\*+/', ur'(?:.*/)?') # **/ after ^ or /
 
127
_sub_fullpath.add(ur'\*+', ur'[^/]*') # * elsewhere
 
128
_sub_fullpath.add(ur'\?', ur'[^/]') # ? everywhere
 
129
 
 
130
 
 
131
_sub_basename = Replacer()
 
132
_sub_basename.add(ur'\[\^?\]?(?:[^][]|\[:[^]]+:\])+\]', _sub_group) # char group
 
133
_sub_basename.add(ur'\\.', ur'\&') # keep anything backslashed
 
134
_sub_basename.add(ur'[(){}|^$+.]', ur'\\&') # escape specials
 
135
_sub_basename.add(ur'\*+', ur'.*') # * everywhere
 
136
_sub_basename.add(ur'\?', ur'.') # ? everywhere
 
137
 
 
138
 
 
139
def _sub_extension(pattern):
 
140
    return _sub_basename(pattern[2:])
161
141
 
162
142
 
163
143
class Globster(object):
178
158
    (those that match against a file extension), basename patterns
179
159
    (those that match against the basename of the filename),
180
160
    and fullpath patterns (those that match against the full path).
181
 
    The regexs used for extensions and basenames are relatively simpler 
 
161
    The translations used for extensions and basenames are relatively simpler 
182
162
    and therefore faster to perform than the fullpath patterns.
183
163
 
184
164
    Also, the extension patterns are more likely to find a match and 
186
166
    patterns.
187
167
    """
188
168
    def __init__(self, patterns):
 
169
        self._flags = re.UNICODE
 
170
        if os.path.normcase('Ab') != 'Ab':
 
171
            self._flags |= re.IGNORECASE
189
172
        self._regex_patterns = []
190
173
        path_patterns = []
191
174
        base_patterns = []
197
180
                ext_patterns.append(pat)
198
181
            else:
199
182
                base_patterns.append(pat)
200
 
        self._add_patterns(ext_patterns,_sub_shell_extension,
201
 
            prefix=r'(?:.*/)?(?!.*/)(?:[^.].*\.)')
202
 
        self._add_patterns(base_patterns,_sub_shell_basename, 
 
183
        self._add_patterns(ext_patterns,_sub_extension,
 
184
            prefix=r'(?:.*/)?(?!.*/)(?:.*\.)')
 
185
        self._add_patterns(base_patterns,_sub_basename, 
203
186
            prefix=r'(?:.*/)?(?!.*/)')
204
 
        self._add_patterns(path_patterns,_sub_shell) 
 
187
        self._add_patterns(path_patterns,_sub_fullpath) 
205
188
 
206
189
    def _add_patterns(self, patterns, translator, prefix=''):
207
190
        while patterns:
208
191
            grouped_rules = ['(%s)' % translator(pat) for pat in patterns[:99]]
209
192
            joined_rule = '%s(?:%s)$' % (prefix, '|'.join(grouped_rules))
210
 
            self._regex_patterns.append((re.compile(joined_rule, re.UNICODE), 
 
193
            self._regex_patterns.append((re.compile(joined_rule, self._flags), 
211
194
                patterns[:99]))
212
195
            patterns = patterns[99:]
213
196