Rev 5765: Extract _match_section_by_parts from LocationConfig._get_matching_sections and more comments to explain the behavior. in file:///home/vila/src/bzr/experimental/config/
v.ladeuil+lp at free.fr
Thu Apr 7 15:05:13 UTC 2011
revision-id: v.ladeuil+lp at free.fr-20110407150513-rshmyf6a1c2jkbgs
parent: pqm at pqm.ubuntu.com-20110406110717-u00w5z9lcww3o6xs
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: refactor-locationconfig-matching
timestamp: Thu 2011-04-07 17:05:13 +0200
Extract _match_section_by_parts from LocationConfig._get_matching_sections and more comments to explain the behavior.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2011-04-05 14:47:26 +0000
+++ b/bzrlib/config.py 2011-04-07 15:05:13 +0000
@@ -967,6 +967,47 @@
+def _match_section_by_parts(section, location, location_parts):
+ # location is a local path if possible, so we need
+ # to convert 'file://' urls to local paths if necessary.
+ # FIXME: I don't think the above comment is still up to date,
+ # LocationConfig is always instantiated with an url -- vila 2011-04-07
+ # This also avoids having file:///path be a more exact
+ # match than '/path'.
+ # FIXME: Not sure about the above either, but since the path components are
+ # compared in sync, adding two empty components (//) is likely to trick the
+ # comparison and also trick the check on the number of components, so we
+ # *should* take only the relevant part of the url. On the other hand, this
+ # means 'file://' urls *can't* be used in sections -- vila 2011-04-07
+ if section.startswith('file://'):
+ section_path = urlutils.local_path_from_url(section)
+ section_path = section
+ section_parts = section_path.rstrip('/').split('/')
+ matched = True
+ if len(section_parts) > len(location_parts):
+ # More path components in the section, they can't match
+ matched = False
+ # Rely on zip truncating in length to the length of the shortest
+ # argument sequence.
+ names = zip(location_parts, section_parts)
+ for name in names:
+ if not fnmatch.fnmatch(name, name):
+ matched = False
+ if not matched:
+ return None
+ # build the path difference between the section and the location
+ relpath = '/'.join(location_parts[len(section_parts):])
+ return len(section_parts), relpath
"""A configuration object that gives the policy for a location."""
@@ -1002,36 +1043,16 @@
"""Return an ordered list of section names matching this location."""
sections = self._get_parser()
- location_names = self.location.split('/')
- if self.location.endswith('/'):
- del location_names[-1]
+ location_parts = self.location.rstrip('/').split('/')
+ matches = 
for section in sections:
- # location is a local path if possible, so we need
- # to convert 'file://' urls to local paths if necessary.
- # This also avoids having file:///path be a more exact
- # match than '/path'.
- if section.startswith('file://'):
- section_path = urlutils.local_path_from_url(section)
- section_path = section
- section_names = section_path.split('/')
- if section.endswith('/'):
- del section_names[-1]
- names = zip(location_names, section_names)
- matched = True
- for name in names:
- if not fnmatch.fnmatch(name, name):
- matched = False
- if not matched:
- # so, for the common prefix they matched.
- # if section is longer, no match.
- if len(section_names) > len(location_names):
- matches.append((len(section_names), section,
+ match = _match_section_by_parts(section, self.location,
+ if match is None:
+ nb_parts, relpath = match
+ matches.append((nb_parts, section, relpath))
# put the longest (aka more specific) locations first
sections = 
More information about the bazaar-commits