/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/tests/test_globbing.py

  • Committer: Martin Pool
  • Date: 2010-08-13 08:09:53 UTC
  • mto: (5050.17.6 2.2)
  • mto: This revision was merged to the branch mainline in revision 5379.
  • Revision ID: mbp@sourcefrog.net-20100813080953-c00cm9l3qgu2flj9
Remove spuriously-resurrected test

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006-2010 Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 
 
18
import re
 
19
 
 
20
from bzrlib import errors
 
21
from bzrlib.globbing import (
 
22
    Globster,
 
23
    ExceptionGlobster,
 
24
    _OrderedGlobster,
 
25
    normalize_pattern
 
26
    )
 
27
from bzrlib.tests import (
 
28
    TestCase,
 
29
    TestCaseInTempDir,
 
30
    )
 
31
 
 
32
 
 
33
class TestGlobster(TestCase):
 
34
 
 
35
    def assertMatch(self, matchset, glob_prefix=None):
 
36
        for glob, positive, negative in matchset:
 
37
            if glob_prefix:
 
38
                glob = glob_prefix + glob
 
39
            globster = Globster([glob])
 
40
            for name in positive:
 
41
                self.failUnless(globster.match(name), repr(
 
42
                    u'name "%s" does not match glob "%s" (re=%s)' %
 
43
                    (name, glob, globster._regex_patterns[0][0].pattern)))
 
44
            for name in negative:
 
45
                self.failIf(globster.match(name), repr(
 
46
                    u'name "%s" does match glob "%s" (re=%s)' %
 
47
                    (name, glob, globster._regex_patterns[0][0].pattern)))
 
48
 
 
49
    def assertMatchBasenameAndFullpath(self, matchset):
 
50
        # test basename matcher
 
51
        self.assertMatch(matchset)
 
52
        # test fullpath matcher
 
53
        self.assertMatch(matchset, glob_prefix='./')
 
54
 
 
55
    def test_char_group_digit(self):
 
56
        self.assertMatchBasenameAndFullpath([
 
57
            # The definition of digit this uses includes arabic digits from
 
58
            # non-latin scripts (arabic, indic, etc.) and subscript/superscript
 
59
            # digits, but neither roman numerals nor vulgar fractions.
 
60
            (u'[[:digit:]]',
 
61
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
 
62
             [u'T', u'q', u' ', u'\u8336', u'.']),
 
63
            (u'[^[:digit:]]',
 
64
             [u'T', u'q', u' ', u'\u8336', u'.'],
 
65
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
 
66
            ])
 
67
 
 
68
    def test_char_group_space(self):
 
69
        self.assertMatchBasenameAndFullpath([
 
70
            (u'[[:space:]]',
 
71
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002'],
 
72
             [u'a', u'-', u'\u8336', u'.']),
 
73
            (u'[^[:space:]]',
 
74
             [u'a', u'-', u'\u8336', u'.'],
 
75
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002']),
 
76
            ])
 
77
 
 
78
    def test_char_group_alnum(self):
 
79
        self.assertMatchBasenameAndFullpath([
 
80
            (u'[[:alnum:]]',
 
81
             [u'a', u'Z', u'\u017e', u'\u8336'],
 
82
             [u':', u'-', u'\u25cf', u'.']),
 
83
            (u'[^[:alnum:]]',
 
84
             [u':', u'-', u'\u25cf', u'.'],
 
85
             [u'a']),
 
86
            ])
 
87
 
 
88
    def test_char_group_ascii(self):
 
89
        self.assertMatchBasenameAndFullpath([
 
90
            (u'[[:ascii:]]',
 
91
             [u'a', u'Q', u'^', u'.'],
 
92
             [u'\xcc', u'\u8336']),
 
93
            (u'[^[:ascii:]]',
 
94
             [u'\xcc', u'\u8336'],
 
95
             [u'a', u'Q', u'^', u'.']),
 
96
            ])
 
97
 
 
98
    def test_char_group_blank(self):
 
99
        self.assertMatchBasenameAndFullpath([
 
100
            (u'[[:blank:]]',
 
101
             [u'\t'],
 
102
             [u'x', u'y', u'z', u'.']),
 
103
            (u'[^[:blank:]]',
 
104
             [u'x', u'y', u'z', u'.'],
 
105
             [u'\t']),
 
106
            ])
 
107
 
 
108
    def test_char_group_cntrl(self):
 
109
        self.assertMatchBasenameAndFullpath([
 
110
            (u'[[:cntrl:]]',
 
111
             [u'\b', u'\t', '\x7f'],
 
112
             [u'a', u'Q', u'\u8336', u'.']),
 
113
            (u'[^[:cntrl:]]',
 
114
             [u'a', u'Q', u'\u8336', u'.'],
 
115
             [u'\b', u'\t', '\x7f']),
 
116
            ])
 
117
 
 
118
    def test_char_group_range(self):
 
119
        self.assertMatchBasenameAndFullpath([
 
120
            (u'[a-z]',
 
121
             [u'a', u'q', u'f'],
 
122
             [u'A', u'Q', u'F']),
 
123
            (u'[^a-z]',
 
124
             [u'A', u'Q', u'F'],
 
125
             [u'a', u'q', u'f']),
 
126
            (u'[!a-z]foo',
 
127
             [u'Afoo', u'.foo'],
 
128
             [u'afoo', u'ABfoo']),
 
129
            (u'foo[!a-z]bar',
 
130
             [u'fooAbar', u'foo.bar'],
 
131
             [u'foojbar']),
 
132
            (u'[\x20-\x30\u8336]',
 
133
             [u'\040', u'\044', u'\u8336'],
 
134
             [u'\x1f']),
 
135
            (u'[^\x20-\x30\u8336]',
 
136
             [u'\x1f'],
 
137
             [u'\040', u'\044', u'\u8336']),
 
138
            ])
 
139
 
 
140
    def test_regex(self):
 
141
        self.assertMatch([
 
142
            (u'RE:(a|b|c+)',
 
143
             [u'a', u'b', u'ccc'],
 
144
             [u'd', u'aa', u'c+', u'-a']),
 
145
            (u'RE:(?:a|b|c+)',
 
146
             [u'a', u'b', u'ccc'],
 
147
             [u'd', u'aa', u'c+', u'-a']),
 
148
            (u'RE:(?P<a>.)(?P=a)',
 
149
             [u'a'],
 
150
             [u'ab', u'aa', u'aaa']),
 
151
            # test we can handle odd numbers of trailing backslashes
 
152
            (u'RE:a\\\\\\',
 
153
             [u'a\\'],
 
154
             [u'a', u'ab', u'aa', u'aaa']),
 
155
            ])
 
156
 
 
157
    def test_question_mark(self):
 
158
        self.assertMatch([
 
159
            (u'?foo',
 
160
             [u'xfoo', u'bar/xfoo', u'bar/\u8336foo', u'.foo', u'bar/.foo'],
 
161
             [u'bar/foo', u'foo']),
 
162
            (u'foo?bar',
 
163
             [u'fooxbar', u'foo.bar', u'foo\u8336bar', u'qyzzy/foo.bar'],
 
164
             [u'foo/bar']),
 
165
            (u'foo/?bar',
 
166
             [u'foo/xbar', u'foo/\u8336bar', u'foo/.bar'],
 
167
             [u'foo/bar', u'bar/foo/xbar']),
 
168
            ])
 
169
 
 
170
    def test_asterisk(self):
 
171
        self.assertMatch([
 
172
            (u'x*x',
 
173
             [u'xx', u'x.x', u'x\u8336..x', u'\u8336/x.x', u'x.y.x'],
 
174
             [u'x/x', u'bar/x/bar/x', u'bax/abaxab']),
 
175
            (u'foo/*x',
 
176
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
 
177
             [u'foo/bar/bax']),
 
178
            (u'*/*x',
 
179
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x',
 
180
              u'\u8336/.x', u'foo/.q.x'],
 
181
             [u'foo/bar/bax']),
 
182
            (u'f*',
 
183
             [u'foo', u'foo.bar'],
 
184
             [u'.foo', u'foo/bar', u'foo/.bar']),
 
185
            (u'*bar',
 
186
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
 
187
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
 
188
             []),
 
189
            ])
 
190
 
 
191
    def test_double_asterisk(self):
 
192
        self.assertMatch([
 
193
            # expected uses of double asterisk
 
194
            (u'foo/**/x',
 
195
             [u'foo/x', u'foo/bar/x'],
 
196
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
197
            (u'**/bar',
 
198
             [u'bar', u'foo/bar'],
 
199
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
 
200
              u'.bar', u'foo/.bar']),
 
201
            # check that we ignore extra *s, so *** is treated like ** not *.
 
202
            (u'foo/***/x',
 
203
             [u'foo/x', u'foo/bar/x'],
 
204
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
205
            (u'***/bar',
 
206
             [u'bar', u'foo/bar'],
 
207
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
 
208
              u'.bar', u'foo/.bar']),
 
209
            # the remaining tests check that ** is interpreted as *
 
210
            # unless it is a whole path component
 
211
            (u'x**/x',
 
212
             [u'x\u8336/x', u'x/x'],
 
213
             [u'xx', u'x.x', u'bar/x/bar/x', u'x.y.x', u'x/y/x']),
 
214
            (u'x**x',
 
215
             [u'xx', u'x.x', u'x\u8336..x', u'foo/x.x', u'x.y.x'],
 
216
             [u'bar/x/bar/x', u'xfoo/bar/x', u'x/x', u'bax/abaxab']),
 
217
            (u'foo/**x',
 
218
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
 
219
             [u'foo/bar/bax']),
 
220
            (u'f**',
 
221
             [u'foo', u'foo.bar'],
 
222
             [u'.foo', u'foo/bar', u'foo/.bar']),
 
223
            (u'**bar',
 
224
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
 
225
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
 
226
             []),
 
227
            ])
 
228
 
 
229
    def test_leading_dot_slash(self):
 
230
        self.assertMatch([
 
231
            (u'./foo',
 
232
             [u'foo'],
 
233
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
234
            (u'./f*',
 
235
             [u'foo'],
 
236
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
 
237
            ])
 
238
 
 
239
    def test_backslash(self):
 
240
        self.assertMatch([
 
241
            (u'.\\foo',
 
242
             [u'foo'],
 
243
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
244
            (u'.\\f*',
 
245
             [u'foo'],
 
246
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
 
247
            (u'foo\\**\\x',
 
248
             [u'foo/x', u'foo/bar/x'],
 
249
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
 
250
            ])
 
251
 
 
252
    def test_trailing_slash(self):
 
253
        self.assertMatch([
 
254
            (u'./foo/',
 
255
             [u'foo'],
 
256
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
257
            (u'.\\foo\\',
 
258
             [u'foo'],
 
259
             [u'foo/', u'\u8336/foo', u'barfoo', u'x/y/foo']),
 
260
            ])
 
261
 
 
262
    def test_leading_asterisk_dot(self):
 
263
        self.assertMatch([
 
264
            (u'*.x',
 
265
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x',
 
266
              u'bar/.foo.x', u'.x',],
 
267
             [u'foo.x.y']),
 
268
            (u'foo/*.bar',
 
269
             [u'foo/b.bar', u'foo/a.b.bar', u'foo/.bar'],
 
270
             [u'foo/bar']),
 
271
            (u'*.~*',
 
272
             [u'foo.py.~1~', u'.foo.py.~1~'],
 
273
             []),
 
274
            ])
 
275
 
 
276
    def test_end_anchor(self):
 
277
        self.assertMatch([
 
278
            (u'*.333',
 
279
             [u'foo.333'],
 
280
             [u'foo.3']),
 
281
            (u'*.3',
 
282
             [u'foo.3'],
 
283
             [u'foo.333']),
 
284
            ])
 
285
 
 
286
    def test_mixed_globs(self):
 
287
        """tests handling of combinations of path type matches.
 
288
 
 
289
        The types being extension, basename and full path.
 
290
        """
 
291
        patterns = [ u'*.foo', u'.*.swp', u'./*.png']
 
292
        globster = Globster(patterns)
 
293
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
 
294
        self.assertEqual(u'./*.png', globster.match('foo.png'))
 
295
        self.assertEqual(None, globster.match('foo/bar.png'))
 
296
        self.assertEqual(u'.*.swp', globster.match('foo/.bar.py.swp'))
 
297
 
 
298
    def test_large_globset(self):
 
299
        """tests that the globster can handle a large set of patterns.
 
300
 
 
301
        Large is defined as more than supported by python regex groups,
 
302
        i.e. 99.
 
303
        This test assumes the globs are broken into regexs containing 99
 
304
        groups.
 
305
        """
 
306
        patterns = [ u'*.%03d' % i for i in xrange(0,300) ]
 
307
        globster = Globster(patterns)
 
308
        # test the fence posts
 
309
        for x in (0,98,99,197,198,296,297,299):
 
310
            filename = u'foo.%03d' % x
 
311
            self.assertEqual(patterns[x],globster.match(filename))
 
312
        self.assertEqual(None,globster.match('foobar.300'))
 
313
 
 
314
    def test_bad_pattern(self):
 
315
        """Ensure that globster handles bad patterns cleanly."""
 
316
        patterns = [u'RE:[', u'/home/foo', u'RE:*.cpp']
 
317
        g = Globster(patterns)
 
318
        e = self.assertRaises(errors.InvalidPattern, g.match, 'filename')
 
319
        self.assertContainsRe(e.msg,
 
320
            "File.*ignore.*contains error.*RE:\[.*RE:\*\.cpp", flags=re.DOTALL)
 
321
 
 
322
 
 
323
class TestExceptionGlobster(TestCase):
 
324
 
 
325
    def test_exclusion_patterns(self):
 
326
        """test that exception patterns are not matched"""
 
327
        patterns = [ u'*', u'!./local', u'!./local/**/*', u'!RE:\.z.*',u'!!./.zcompdump' ]
 
328
        globster = ExceptionGlobster(patterns)
 
329
        self.assertEqual(u'*', globster.match('tmp/foo.txt'))
 
330
        self.assertEqual(None, globster.match('local'))
 
331
        self.assertEqual(None, globster.match('local/bin/wombat'))
 
332
        self.assertEqual(None, globster.match('.zshrc'))
 
333
        self.assertEqual(None, globster.match('.zfunctions/fiddle/flam'))
 
334
        self.assertEqual(u'!!./.zcompdump', globster.match('.zcompdump'))
 
335
 
 
336
    def test_exclusion_order(self):
 
337
        """test that ordering of exclusion patterns does not matter"""
 
338
        patterns = [ u'static/**/*.html', u'!static/**/versionable.html']
 
339
        globster = ExceptionGlobster(patterns)
 
340
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
341
        self.assertEqual(None, globster.match('static/versionable.html'))
 
342
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
343
        globster = ExceptionGlobster(reversed(patterns))
 
344
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
345
        self.assertEqual(None, globster.match('static/versionable.html'))
 
346
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
347
 
 
348
class TestOrderedGlobster(TestCase):
 
349
 
 
350
    def test_ordered_globs(self):
 
351
        """test that the first match in a list is the one found"""
 
352
        patterns = [ u'*.foo', u'bar.*']
 
353
        globster = _OrderedGlobster(patterns)
 
354
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
 
355
        self.assertEqual(None, globster.match('foo.bar'))
 
356
        globster = _OrderedGlobster(reversed(patterns))
 
357
        self.assertEqual(u'bar.*', globster.match('bar.foo'))
 
358
        self.assertEqual(None, globster.match('foo.bar'))
 
359
 
 
360
 
 
361
class TestNormalizePattern(TestCase):
 
362
 
 
363
    def test_backslashes(self):
 
364
        """tests that backslashes are converted to forward slashes, multiple
 
365
        backslashes are collapsed to single forward slashes and trailing
 
366
        backslashes are removed"""
 
367
        self.assertEqual(u'/', normalize_pattern(u'\\'))
 
368
        self.assertEqual(u'/', normalize_pattern(u'\\\\'))
 
369
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\foo\\bar'))
 
370
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo\\bar\\'))
 
371
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\\\foo\\\\bar\\\\'))
 
372
 
 
373
    def test_forward_slashes(self):
 
374
        """tests that multiple foward slashes are collapsed to single forward
 
375
        slashes and trailing forward slashes are removed"""
 
376
        self.assertEqual(u'/', normalize_pattern(u'/'))
 
377
        self.assertEqual(u'/', normalize_pattern(u'//'))
 
378
        self.assertEqual(u'/foo/bar', normalize_pattern(u'/foo/bar'))
 
379
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo/bar/'))
 
380
        self.assertEqual(u'/foo/bar', normalize_pattern(u'//foo//bar//'))
 
381
 
 
382
    def test_mixed_slashes(self):
 
383
        """tests that multiple mixed slashes are collapsed to single forward
 
384
        slashes and trailing mixed slashes are removed"""
 
385
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\/\\foo//\\///bar/\\\\/'))