~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_globbing.py

  • Committer: Jelmer Vernooij
  • Date: 2010-12-20 11:57:14 UTC
  • mto: This revision was merged to the branch mainline in revision 5577.
  • Revision ID: jelmer@samba.org-20101220115714-2ru3hfappjweeg7q
Don't use no-plugins.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 
 
18
import re
 
19
 
 
20
from bzrlib import errors
18
21
from bzrlib.globbing import (
19
22
    Globster,
 
23
    ExceptionGlobster,
 
24
    _OrderedGlobster,
 
25
    normalize_pattern
20
26
    )
21
27
from bzrlib.tests import (
22
 
    TestCase, 
 
28
    TestCase,
23
29
    TestCaseInTempDir,
24
30
    )
25
31
 
49
55
    def test_char_group_digit(self):
50
56
        self.assertMatchBasenameAndFullpath([
51
57
            # The definition of digit this uses includes arabic digits from
52
 
            # non-latin scripts (arabic, indic, etc.) and subscript/superscript
53
 
            # digits, but neither roman numerals nor vulgar fractions.
 
58
            # non-latin scripts (arabic, indic, etc.) but neither roman
 
59
            # numerals nor vulgar fractions. Some characters such as
 
60
            # subscript/superscript digits may or may not match depending on
 
61
            # the Python version used, see: <http://bugs.python.org/issue6561>
54
62
            (u'[[:digit:]]',
55
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
 
63
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21'],
56
64
             [u'T', u'q', u' ', u'\u8336', u'.']),
57
65
            (u'[^[:digit:]]',
58
66
             [u'T', u'q', u' ', u'\u8336', u'.'],
59
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
 
67
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21']),
60
68
            ])
61
69
 
62
70
    def test_char_group_space(self):
170
178
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
171
179
             [u'foo/bar/bax']),
172
180
            (u'*/*x',
173
 
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x', 
 
181
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x',
174
182
              u'\u8336/.x', u'foo/.q.x'],
175
183
             [u'foo/bar/bax']),
176
184
            (u'f*',
177
185
             [u'foo', u'foo.bar'],
178
186
             [u'.foo', u'foo/bar', u'foo/.bar']),
179
187
            (u'*bar',
180
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
188
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
181
189
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
182
190
             []),
183
191
            ])
190
198
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
191
199
            (u'**/bar',
192
200
             [u'bar', u'foo/bar'],
193
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
201
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
194
202
              u'.bar', u'foo/.bar']),
195
203
            # check that we ignore extra *s, so *** is treated like ** not *.
196
204
            (u'foo/***/x',
198
206
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
199
207
            (u'***/bar',
200
208
             [u'bar', u'foo/bar'],
201
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
 
209
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
202
210
              u'.bar', u'foo/.bar']),
203
211
            # the remaining tests check that ** is interpreted as *
204
212
            # unless it is a whole path component
215
223
             [u'foo', u'foo.bar'],
216
224
             [u'.foo', u'foo/bar', u'foo/.bar']),
217
225
            (u'**bar',
218
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
 
226
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
219
227
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
220
228
             []),
221
229
            ])
256
264
    def test_leading_asterisk_dot(self):
257
265
        self.assertMatch([
258
266
            (u'*.x',
259
 
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x', 
 
267
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x',
260
268
              u'bar/.foo.x', u'.x',],
261
269
             [u'foo.x.y']),
262
270
            (u'foo/*.bar',
292
300
    def test_large_globset(self):
293
301
        """tests that the globster can handle a large set of patterns.
294
302
 
295
 
        Large is defined as more than supported by python regex groups, 
 
303
        Large is defined as more than supported by python regex groups,
296
304
        i.e. 99.
297
305
        This test assumes the globs are broken into regexs containing 99
298
306
        groups.
305
313
            self.assertEqual(patterns[x],globster.match(filename))
306
314
        self.assertEqual(None,globster.match('foobar.300'))
307
315
 
 
316
    def test_bad_pattern(self):
 
317
        """Ensure that globster handles bad patterns cleanly."""
 
318
        patterns = [u'RE:[', u'/home/foo', u'RE:*.cpp']
 
319
        g = Globster(patterns)
 
320
        e = self.assertRaises(errors.InvalidPattern, g.match, 'filename')
 
321
        self.assertContainsRe(e.msg,
 
322
            "File.*ignore.*contains error.*RE:\[.*RE:\*\.cpp", flags=re.DOTALL)
 
323
 
 
324
 
 
325
class TestExceptionGlobster(TestCase):
 
326
 
 
327
    def test_exclusion_patterns(self):
 
328
        """test that exception patterns are not matched"""
 
329
        patterns = [ u'*', u'!./local', u'!./local/**/*', u'!RE:\.z.*',u'!!./.zcompdump' ]
 
330
        globster = ExceptionGlobster(patterns)
 
331
        self.assertEqual(u'*', globster.match('tmp/foo.txt'))
 
332
        self.assertEqual(None, globster.match('local'))
 
333
        self.assertEqual(None, globster.match('local/bin/wombat'))
 
334
        self.assertEqual(None, globster.match('.zshrc'))
 
335
        self.assertEqual(None, globster.match('.zfunctions/fiddle/flam'))
 
336
        self.assertEqual(u'!!./.zcompdump', globster.match('.zcompdump'))
 
337
 
 
338
    def test_exclusion_order(self):
 
339
        """test that ordering of exclusion patterns does not matter"""
 
340
        patterns = [ u'static/**/*.html', u'!static/**/versionable.html']
 
341
        globster = ExceptionGlobster(patterns)
 
342
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
343
        self.assertEqual(None, globster.match('static/versionable.html'))
 
344
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
345
        globster = ExceptionGlobster(reversed(patterns))
 
346
        self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
 
347
        self.assertEqual(None, globster.match('static/versionable.html'))
 
348
        self.assertEqual(None, globster.match('static/bar/versionable.html'))
 
349
 
 
350
class TestOrderedGlobster(TestCase):
 
351
 
 
352
    def test_ordered_globs(self):
 
353
        """test that the first match in a list is the one found"""
 
354
        patterns = [ u'*.foo', u'bar.*']
 
355
        globster = _OrderedGlobster(patterns)
 
356
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
 
357
        self.assertEqual(None, globster.match('foo.bar'))
 
358
        globster = _OrderedGlobster(reversed(patterns))
 
359
        self.assertEqual(u'bar.*', globster.match('bar.foo'))
 
360
        self.assertEqual(None, globster.match('foo.bar'))
 
361
 
 
362
 
 
363
class TestNormalizePattern(TestCase):
 
364
 
 
365
    def test_backslashes(self):
 
366
        """tests that backslashes are converted to forward slashes, multiple
 
367
        backslashes are collapsed to single forward slashes and trailing
 
368
        backslashes are removed"""
 
369
        self.assertEqual(u'/', normalize_pattern(u'\\'))
 
370
        self.assertEqual(u'/', normalize_pattern(u'\\\\'))
 
371
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\foo\\bar'))
 
372
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo\\bar\\'))
 
373
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\\\foo\\\\bar\\\\'))
 
374
 
 
375
    def test_forward_slashes(self):
 
376
        """tests that multiple foward slashes are collapsed to single forward
 
377
        slashes and trailing forward slashes are removed"""
 
378
        self.assertEqual(u'/', normalize_pattern(u'/'))
 
379
        self.assertEqual(u'/', normalize_pattern(u'//'))
 
380
        self.assertEqual(u'/foo/bar', normalize_pattern(u'/foo/bar'))
 
381
        self.assertEqual(u'foo/bar', normalize_pattern(u'foo/bar/'))
 
382
        self.assertEqual(u'/foo/bar', normalize_pattern(u'//foo//bar//'))
 
383
 
 
384
    def test_mixed_slashes(self):
 
385
        """tests that multiple mixed slashes are collapsed to single forward
 
386
        slashes and trailing mixed slashes are removed"""
 
387
        self.assertEqual(u'/foo/bar', normalize_pattern(u'\\/\\foo//\\///bar/\\\\/'))