~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2011-03-10 13:52:27 UTC
  • mto: (5712.4.5 bzrdir-weave)
  • mto: This revision was merged to the branch mainline in revision 5716.
  • Revision ID: jelmer@samba.org-20110310135227-ufcw0utlwsp8r6k6
Revert registry changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
"""
64
64
 
65
65
import os
66
 
import string
67
66
import sys
68
67
 
69
68
from bzrlib import commands
70
69
from bzrlib.decorators import needs_write_lock
71
70
from bzrlib.lazy_import import lazy_import
72
71
lazy_import(globals(), """
 
72
import errno
73
73
import fnmatch
74
74
import re
75
75
from cStringIO import StringIO
279
279
        # We need to iterate until no more refs appear ({{foo}} will need two
280
280
        # iterations for example).
281
281
        while True:
282
 
            raw_chunks = self.option_ref_re.split(result)
 
282
            try:
 
283
                raw_chunks = self.option_ref_re.split(result)
 
284
            except TypeError:
 
285
                import pdb; pdb.set_trace()
283
286
            if len(raw_chunks) == 1:
284
287
                # Shorcut the trivial case: no refs
285
288
                return result
441
444
        the concrete policy type is checked, and finally
442
445
        $EMAIL is examined.
443
446
        If no username can be found, errors.NoWhoami exception is raised.
 
447
 
 
448
        TODO: Check it's reasonably well-formed.
444
449
        """
445
450
        v = os.environ.get('BZR_EMAIL')
446
451
        if v:
447
452
            return v.decode(osutils.get_user_encoding())
 
453
 
448
454
        v = self._get_user_id()
449
455
        if v:
450
456
            return v
 
457
 
451
458
        v = os.environ.get('EMAIL')
452
459
        if v:
453
460
            return v.decode(osutils.get_user_encoding())
454
 
        name, email = _auto_user_id()
455
 
        if name and email:
456
 
            return '%s <%s>' % (name, email)
457
 
        elif email:
458
 
            return email
 
461
 
459
462
        raise errors.NoWhoami()
460
463
 
461
464
    def ensure_username(self):
967
970
        super(LockableConfig, self).remove_user_option(option_name,
968
971
                                                       section_name)
969
972
 
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
973
 
1026
974
class LocationConfig(LockableConfig):
1027
975
    """A configuration object that gives the policy for a location."""
1056
1004
 
1057
1005
    def _get_matching_sections(self):
1058
1006
        """Return an ordered list of section names matching this location."""
1059
 
        matches = list(_iter_for_location_by_parts(self._get_parser(),
1060
 
                                                   self.location))
 
1007
        sections = self._get_parser()
 
1008
        location_names = self.location.split('/')
 
1009
        if self.location.endswith('/'):
 
1010
            del location_names[-1]
 
1011
        matches=[]
 
1012
        for section in sections:
 
1013
            # location is a local path if possible, so we need
 
1014
            # to convert 'file://' urls to local paths if necessary.
 
1015
            # This also avoids having file:///path be a more exact
 
1016
            # match than '/path'.
 
1017
            if section.startswith('file://'):
 
1018
                section_path = urlutils.local_path_from_url(section)
 
1019
            else:
 
1020
                section_path = section
 
1021
            section_names = section_path.split('/')
 
1022
            if section.endswith('/'):
 
1023
                del section_names[-1]
 
1024
            names = zip(location_names, section_names)
 
1025
            matched = True
 
1026
            for name in names:
 
1027
                if not fnmatch.fnmatch(name[0], name[1]):
 
1028
                    matched = False
 
1029
                    break
 
1030
            if not matched:
 
1031
                continue
 
1032
            # so, for the common prefix they matched.
 
1033
            # if section is longer, no match.
 
1034
            if len(section_names) > len(location_names):
 
1035
                continue
 
1036
            matches.append((len(section_names), section,
 
1037
                            '/'.join(location_names[len(section_names):])))
1061
1038
        # 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
 
1039
        matches.sort(reverse=True)
 
1040
        sections = []
 
1041
        for (length, section, extra_path) in matches:
 
1042
            sections.append((section, extra_path))
1067
1043
            # should we stop looking for parent configs here?
1068
1044
            try:
1069
1045
                if self._get_parser()[section].as_bool('ignore_parents'):
1070
1046
                    break
1071
1047
            except KeyError:
1072
1048
                pass
 
1049
        return sections
1073
1050
 
1074
1051
    def _get_sections(self, name=None):
1075
1052
        """See IniBasedConfig._get_sections()."""
1433
1410
        return os.path.expanduser('~/.cache')
1434
1411
 
1435
1412
 
1436
 
def _get_default_mail_domain():
1437
 
    """If possible, return the assumed default email domain.
1438
 
 
1439
 
    :returns: string mail domain, or None.
1440
 
    """
1441
 
    if sys.platform == 'win32':
1442
 
        # No implementation yet; patches welcome
1443
 
        return None
1444
 
    try:
1445
 
        f = open('/etc/mailname')
1446
 
    except (IOError, OSError), e:
1447
 
        return None
1448
 
    try:
1449
 
        domain = f.read().strip()
1450
 
        return domain
1451
 
    finally:
1452
 
        f.close()
1453
 
 
1454
 
 
1455
 
def _auto_user_id():
1456
 
    """Calculate automatic user identification.
1457
 
 
1458
 
    :returns: (realname, email), either of which may be None if they can't be
1459
 
    determined.
1460
 
 
1461
 
    Only used when none is set in the environment or the id file.
1462
 
 
1463
 
    This only returns an email address if we can be fairly sure the 
1464
 
    address is reasonable, ie if /etc/mailname is set on unix.
1465
 
 
1466
 
    This doesn't use the FQDN as the default domain because that may be 
1467
 
    slow, and it doesn't use the hostname alone because that's not normally 
1468
 
    a reasonable address.
1469
 
    """
1470
 
    if sys.platform == 'win32':
1471
 
        # No implementation to reliably determine Windows default mail
1472
 
        # address; please add one.
1473
 
        return None, None
1474
 
 
1475
 
    default_mail_domain = _get_default_mail_domain()
1476
 
    if not default_mail_domain:
1477
 
        return None, None
1478
 
 
1479
 
    import pwd
1480
 
    uid = os.getuid()
1481
 
    try:
1482
 
        w = pwd.getpwuid(uid)
1483
 
    except KeyError:
1484
 
        mutter('no passwd entry for uid %d?' % uid)
1485
 
        return None, None
1486
 
 
1487
 
    # we try utf-8 first, because on many variants (like Linux),
1488
 
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
1489
 
    # false positives.  (many users will have their user encoding set to
1490
 
    # latin-1, which cannot raise UnicodeError.)
1491
 
    try:
1492
 
        gecos = w.pw_gecos.decode('utf-8')
1493
 
        encoding = 'utf-8'
1494
 
    except UnicodeError:
1495
 
        try:
1496
 
            encoding = osutils.get_user_encoding()
1497
 
            gecos = w.pw_gecos.decode(encoding)
1498
 
        except UnicodeError, e:
1499
 
            mutter("cannot decode passwd entry %s" % w)
1500
 
            return None, None
1501
 
    try:
1502
 
        username = w.pw_name.decode(encoding)
1503
 
    except UnicodeError, e:
1504
 
        mutter("cannot decode passwd entry %s" % w)
1505
 
        return None, None
1506
 
 
1507
 
    comma = gecos.find(',')
1508
 
    if comma == -1:
1509
 
        realname = gecos
1510
 
    else:
1511
 
        realname = gecos[:comma]
1512
 
 
1513
 
    return realname, (username + '@' + default_mail_domain)
1514
 
 
1515
 
 
1516
1413
def parse_username(username):
1517
1414
    """Parse e-mail username and return a (name, address) tuple."""
1518
1415
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)