~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

Use global osutils, otherwise it creates a local var.

Which works, but causes us to run the import on every call.

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
from bzrlib.decorators import needs_write_lock
71
71
from bzrlib.lazy_import import lazy_import
72
72
lazy_import(globals(), """
 
73
import errno
73
74
import fnmatch
74
75
import re
75
76
from cStringIO import StringIO
967
968
        super(LockableConfig, self).remove_user_option(option_name,
968
969
                                                       section_name)
969
970
 
970
 
def _iter_for_location_by_parts(sections, location):
971
 
    """Keep only the sessions matching the specified location.
972
 
 
973
 
    :param sections: An iterable of section names.
974
 
 
975
 
    :param location: An url or a local path to match against.
976
 
 
977
 
    :returns: An iterator of (section, extra_path, nb_parts) where nb is the
978
 
        number of path components in the section name, section is the section
979
 
        name and extra_path is the difference between location and the section
980
 
        name.
981
 
    """
982
 
    location_parts = location.rstrip('/').split('/')
983
 
 
984
 
    for section in sections:
985
 
        # location is a local path if possible, so we need
986
 
        # to convert 'file://' urls to local paths if necessary.
987
 
 
988
 
        # FIXME: I don't think the above comment is still up to date,
989
 
        # LocationConfig is always instantiated with an url -- vila 2011-04-07
990
 
 
991
 
        # This also avoids having file:///path be a more exact
992
 
        # match than '/path'.
993
 
 
994
 
        # FIXME: Not sure about the above either, but since the path components
995
 
        # are compared in sync, adding two empty components (//) is likely to
996
 
        # trick the comparison and also trick the check on the number of
997
 
        # components, so we *should* take only the relevant part of the url. On
998
 
        # the other hand, this means 'file://' urls *can't* be used in sections
999
 
        # so more work is probably needed -- vila 2011-04-07
1000
 
 
1001
 
        if section.startswith('file://'):
1002
 
            section_path = urlutils.local_path_from_url(section)
1003
 
        else:
1004
 
            section_path = section
1005
 
        section_parts = section_path.rstrip('/').split('/')
1006
 
 
1007
 
        matched = True
1008
 
        if len(section_parts) > len(location_parts):
1009
 
            # More path components in the section, they can't match
1010
 
            matched = False
1011
 
        else:
1012
 
            # Rely on zip truncating in length to the length of the shortest
1013
 
            # argument sequence.
1014
 
            names = zip(location_parts, section_parts)
1015
 
            for name in names:
1016
 
                if not fnmatch.fnmatch(name[0], name[1]):
1017
 
                    matched = False
1018
 
                    break
1019
 
        if not matched:
1020
 
            continue
1021
 
        # build the path difference between the section and the location
1022
 
        extra_path = '/'.join(location_parts[len(section_parts):])
1023
 
        yield section, extra_path, len(section_parts)
1024
 
 
1025
971
 
1026
972
class LocationConfig(LockableConfig):
1027
973
    """A configuration object that gives the policy for a location."""
1056
1002
 
1057
1003
    def _get_matching_sections(self):
1058
1004
        """Return an ordered list of section names matching this location."""
1059
 
        matches = list(_iter_for_location_by_parts(self._get_parser(),
1060
 
                                                   self.location))
 
1005
        sections = self._get_parser()
 
1006
        location_names = self.location.split('/')
 
1007
        if self.location.endswith('/'):
 
1008
            del location_names[-1]
 
1009
        matches=[]
 
1010
        for section in sections:
 
1011
            # location is a local path if possible, so we need
 
1012
            # to convert 'file://' urls to local paths if necessary.
 
1013
            # This also avoids having file:///path be a more exact
 
1014
            # match than '/path'.
 
1015
            if section.startswith('file://'):
 
1016
                section_path = urlutils.local_path_from_url(section)
 
1017
            else:
 
1018
                section_path = section
 
1019
            section_names = section_path.split('/')
 
1020
            if section.endswith('/'):
 
1021
                del section_names[-1]
 
1022
            names = zip(location_names, section_names)
 
1023
            matched = True
 
1024
            for name in names:
 
1025
                if not fnmatch.fnmatch(name[0], name[1]):
 
1026
                    matched = False
 
1027
                    break
 
1028
            if not matched:
 
1029
                continue
 
1030
            # so, for the common prefix they matched.
 
1031
            # if section is longer, no match.
 
1032
            if len(section_names) > len(location_names):
 
1033
                continue
 
1034
            matches.append((len(section_names), section,
 
1035
                            '/'.join(location_names[len(section_names):])))
1061
1036
        # put the longest (aka more specific) locations first
1062
 
        matches.sort(
1063
 
            key=lambda (section, extra_path, length): (length, section),
1064
 
            reverse=True)
1065
 
        for (section, extra_path, length) in matches:
1066
 
            yield section, extra_path
 
1037
        matches.sort(reverse=True)
 
1038
        sections = []
 
1039
        for (length, section, extra_path) in matches:
 
1040
            sections.append((section, extra_path))
1067
1041
            # should we stop looking for parent configs here?
1068
1042
            try:
1069
1043
                if self._get_parser()[section].as_bool('ignore_parents'):
1070
1044
                    break
1071
1045
            except KeyError:
1072
1046
                pass
 
1047
        return sections
1073
1048
 
1074
1049
    def _get_sections(self, name=None):
1075
1050
        """See IniBasedConfig._get_sections()."""