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
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
from bzrlib import errors
18
21
from bzrlib.globbing import (
22
27
from bzrlib.tests import (
33
37
glob = glob_prefix + glob
34
38
globster = Globster([glob])
35
39
for name in positive:
36
self.failUnless(globster.match(name), repr(
40
self.assertTrue(globster.match(name), repr(
37
41
u'name "%s" does not match glob "%s" (re=%s)' %
38
42
(name, glob, globster._regex_patterns[0][0].pattern)))
39
43
for name in negative:
40
self.failIf(globster.match(name), repr(
44
self.assertFalse(globster.match(name), repr(
41
45
u'name "%s" does match glob "%s" (re=%s)' %
42
46
(name, glob, globster._regex_patterns[0][0].pattern)))
50
54
def test_char_group_digit(self):
51
55
self.assertMatchBasenameAndFullpath([
52
56
# The definition of digit this uses includes arabic digits from
53
# non-latin scripts (arabic, indic, etc.) and subscript/superscript
54
# digits, but neither roman numerals nor vulgar fractions.
57
# non-latin scripts (arabic, indic, etc.) but neither roman
58
# numerals nor vulgar fractions. Some characters such as
59
# subscript/superscript digits may or may not match depending on
60
# the Python version used, see: <http://bugs.python.org/issue6561>
56
[u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
62
[u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21'],
57
63
[u'T', u'q', u' ', u'\u8336', u'.']),
59
65
[u'T', u'q', u' ', u'\u8336', u'.'],
60
[u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
66
[u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21']),
63
69
def test_char_group_space(self):
171
177
[u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
172
178
[u'foo/bar/bax']),
174
[u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x',
180
[u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x',
175
181
u'\u8336/.x', u'foo/.q.x'],
176
182
[u'foo/bar/bax']),
178
184
[u'foo', u'foo.bar'],
179
185
[u'.foo', u'foo/bar', u'foo/.bar']),
181
[u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
187
[u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
182
188
u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
191
197
[u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
193
199
[u'bar', u'foo/bar'],
194
[u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
200
[u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
195
201
u'.bar', u'foo/.bar']),
196
202
# check that we ignore extra *s, so *** is treated like ** not *.
199
205
[u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
201
207
[u'bar', u'foo/bar'],
202
[u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
208
[u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar',
203
209
u'.bar', u'foo/.bar']),
204
210
# the remaining tests check that ** is interpreted as *
205
211
# unless it is a whole path component
216
222
[u'foo', u'foo.bar'],
217
223
[u'.foo', u'foo/bar', u'foo/.bar']),
219
[u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
225
[u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar',
220
226
u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
257
263
def test_leading_asterisk_dot(self):
258
264
self.assertMatch([
260
[u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x',
266
[u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x',
261
267
u'bar/.foo.x', u'.x',],
293
299
def test_large_globset(self):
294
300
"""tests that the globster can handle a large set of patterns.
296
Large is defined as more than supported by python regex groups,
302
Large is defined as more than supported by python regex groups,
298
304
This test assumes the globs are broken into regexs containing 99
306
312
self.assertEqual(patterns[x],globster.match(filename))
307
313
self.assertEqual(None,globster.match('foobar.300'))
315
def test_bad_pattern(self):
316
"""Ensure that globster handles bad patterns cleanly."""
317
patterns = [u'RE:[', u'/home/foo', u'RE:*.cpp']
318
g = Globster(patterns)
319
e = self.assertRaises(errors.InvalidPattern, g.match, 'filename')
320
self.assertContainsRe(e.msg,
321
"File.*ignore.*contains error.*RE:\[.*RE:\*\.cpp", flags=re.DOTALL)
324
class TestExceptionGlobster(TestCase):
326
def test_exclusion_patterns(self):
327
"""test that exception patterns are not matched"""
328
patterns = [ u'*', u'!./local', u'!./local/**/*', u'!RE:\.z.*',u'!!./.zcompdump' ]
329
globster = ExceptionGlobster(patterns)
330
self.assertEqual(u'*', globster.match('tmp/foo.txt'))
331
self.assertEqual(None, globster.match('local'))
332
self.assertEqual(None, globster.match('local/bin/wombat'))
333
self.assertEqual(None, globster.match('.zshrc'))
334
self.assertEqual(None, globster.match('.zfunctions/fiddle/flam'))
335
self.assertEqual(u'!!./.zcompdump', globster.match('.zcompdump'))
337
def test_exclusion_order(self):
338
"""test that ordering of exclusion patterns does not matter"""
339
patterns = [ u'static/**/*.html', u'!static/**/versionable.html']
340
globster = ExceptionGlobster(patterns)
341
self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
342
self.assertEqual(None, globster.match('static/versionable.html'))
343
self.assertEqual(None, globster.match('static/bar/versionable.html'))
344
globster = ExceptionGlobster(reversed(patterns))
345
self.assertEqual(u'static/**/*.html', globster.match('static/foo.html'))
346
self.assertEqual(None, globster.match('static/versionable.html'))
347
self.assertEqual(None, globster.match('static/bar/versionable.html'))
310
349
class TestOrderedGlobster(TestCase):
318
357
globster = _OrderedGlobster(reversed(patterns))
319
358
self.assertEqual(u'bar.*', globster.match('bar.foo'))
320
359
self.assertEqual(None, globster.match('foo.bar'))
362
class TestNormalizePattern(TestCase):
364
def test_backslashes(self):
365
"""tests that backslashes are converted to forward slashes, multiple
366
backslashes are collapsed to single forward slashes and trailing
367
backslashes are removed"""
368
self.assertEqual(u'/', normalize_pattern(u'\\'))
369
self.assertEqual(u'/', normalize_pattern(u'\\\\'))
370
self.assertEqual(u'/foo/bar', normalize_pattern(u'\\foo\\bar'))
371
self.assertEqual(u'foo/bar', normalize_pattern(u'foo\\bar\\'))
372
self.assertEqual(u'/foo/bar', normalize_pattern(u'\\\\foo\\\\bar\\\\'))
374
def test_forward_slashes(self):
375
"""tests that multiple foward slashes are collapsed to single forward
376
slashes and trailing forward slashes are removed"""
377
self.assertEqual(u'/', normalize_pattern(u'/'))
378
self.assertEqual(u'/', normalize_pattern(u'//'))
379
self.assertEqual(u'/foo/bar', normalize_pattern(u'/foo/bar'))
380
self.assertEqual(u'foo/bar', normalize_pattern(u'foo/bar/'))
381
self.assertEqual(u'/foo/bar', normalize_pattern(u'//foo//bar//'))
383
def test_mixed_slashes(self):
384
"""tests that multiple mixed slashes are collapsed to single forward
385
slashes and trailing mixed slashes are removed"""
386
self.assertEqual(u'/foo/bar', normalize_pattern(u'\\/\\foo//\\///bar/\\\\/'))