Rev 6405: More tests, a real implementation and some tweaks. in file:///home/vila/src/bzr/bugs/832046-globs-store-ordered/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Thu Dec 22 16:29:56 UTC 2011
At file:///home/vila/src/bzr/bugs/832046-globs-store-ordered/
------------------------------------------------------------
revno: 6405
revision-id: v.ladeuil+lp at free.fr-20111222162955-92fl4zgjn17rfk9v
parent: v.ladeuil+lp at free.fr-20111222102342-4nr90uruiej3jhqy
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 832046-globs-store-ordered
timestamp: Thu 2011-12-22 17:29:55 +0100
message:
More tests, a real implementation and some tweaks.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2011-12-22 10:23:42 +0000
+++ b/bzrlib/config.py 2011-12-22 16:29:55 +0000
@@ -3012,10 +3012,6 @@
class IniFileStore(Store):
"""A config Store using ConfigObj for storage.
- :ivar transport: The transport object where the config file is located.
-
- :ivar file_name: The config file basename in the transport directory.
-
:ivar _config_obj: Private member to hold the ConfigObj instance used to
serialize/deserialize the config file.
"""
@@ -3133,9 +3129,19 @@
value = self._config_obj._unquote(value)
return value
+ def external_url(self):
+ # Since an IniFileStore can be used without a file (at least in tests),
+ # it's better to provide something than raising a NotImplementedError.
+ # All daughter classes are supposed to provide an implementation
+ # anyway.
+ return 'In-Process Store, no URL'
class TransportIniFileStore(IniFileStore):
"""IniFileStore that loads files from a transport.
+
+ :ivar transport: The transport object where the config file is located.
+
+ :ivar file_name: The config file basename in the transport directory.
"""
def __init__(self, transport, file_name):
@@ -3355,8 +3361,15 @@
def get_sections(self):
"""Get all sections matching ``location``."""
store = self.store
- for _, section in store.get_sections():
- yield store, LocationSection(section, self.location)
+ sections = []
+ # Later sections are more specific, they should be returned first
+ for _, section in reversed(list(store.get_sections())):
+ section_path = section.id
+ if section_path.startswith('file://'):
+ section_path = urlutils.local_path_from_url(section)
+ if (self.location.startswith(section_path)
+ or fnmatch.fnmatch(self.location, section_path)):
+ yield store, LocationSection(section, self.location)
class LocationMatcher(SectionMatcher):
=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py 2011-12-22 10:23:42 +0000
+++ b/bzrlib/tests/test_config.py 2011-12-22 16:29:55 +0000
@@ -3255,7 +3255,7 @@
'/quux/quux'],
[section.id for _, section in store.get_sections()])
matcher = config.LocationMatcher(store, '/foo/bar/quux')
- sections = [section for s, section in matcher.get_sections()]
+ sections = [section for _, section in matcher.get_sections()]
self.assertEquals(['/foo/bar', '/foo'],
[section.id for section in sections])
self.assertEquals(['quux', 'bar/quux'],
@@ -3272,7 +3272,7 @@
self.assertEquals(['/foo', '/foo/bar'],
[section.id for _, section in store.get_sections()])
matcher = config.LocationMatcher(store, '/foo/bar/baz')
- sections = [section for s, section in matcher.get_sections()]
+ sections = [section for _, section in matcher.get_sections()]
self.assertEquals(['/foo/bar', '/foo'],
[section.id for section in sections])
self.assertEquals(['baz', 'bar/baz'],
@@ -3303,6 +3303,57 @@
self.assertEquals(expected_location, matcher.location)
+class TestGlobOrderedMatcher(TestStore):
+
+ def setUp(self):
+ super(TestGlobOrderedMatcher, self).setUp()
+ self.matcher = config.NameMatcher
+ # Any simple store is good enough
+ self.store = config.IniFileStore()
+
+ def assertSectionIDs(self, expected, location, content):
+ self.store._load_from_string(content)
+ matcher = config.GlobOrderedMatcher(self.store, location)
+ sections = list(matcher.get_sections())
+ self.assertLength(len(expected), sections)
+ self.assertEqual(expected, [section.id for _, section in sections])
+ return sections
+
+ def test_empty(self):
+ self.assertSectionIDs([], self.test_dir, '')
+
+ def test_order_reversed(self):
+ self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
+[/foo]
+[/foo/bar]
+''')
+
+ def test_unrelated_section_excluded(self):
+ self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', '''\
+[/foo]
+[/foo/qux]
+[/foo/bar]
+''')
+
+ def test_glob_included(self):
+ self.assertSectionIDs(['/foo/*/baz', '/foo/b*', '/foo'],
+ '/foo/bar/baz', '''\
+[/foo]
+[/foo/qux]
+[/foo/b*]
+[/foo/*/baz]
+''')
+
+ def test_respect_order(self):
+ self.assertSectionIDs(['/foo', '/foo/b*', '/foo/*/baz'],
+ '/foo/bar/baz', '''\
+[/foo/*/baz]
+[/foo/qux]
+[/foo/b*]
+[/foo]
+''')
+
+
class TestNameMatcher(TestStore):
def setUp(self):
@@ -3334,25 +3385,6 @@
self.assertLength(0, sections)
-class TestGlobOrderedMatcher(TestStore):
-
- def setUp(self):
- super(TestGlobOrderedMatcher, self).setUp()
- self.matcher = config.NameMatcher
- # Any simple store is good enough
- self.store = config.IniFileStore()
-
- def assertSections(self, expected, location, content):
- self.store._load_from_string(content)
- matcher = config.GlobOrderedMatcher(self.store, location)
- sections = list(matcher.get_sections())
- self.assertLength(len(expected), sections)
- self.assertEqual(expected, sections)
-
- def test_empty(self):
- self.assertSections([], self.test_dir, '')
-
-
class TestBaseStackGet(tests.TestCase):
def setUp(self):
More information about the bazaar-commits
mailing list