~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Martin Pool
  • Date: 2010-01-29 14:09:05 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129140905-2uiarb6p8di1ywsr
Correction to url

from review: https://code.edge.launchpad.net/~mbp/bzr/doc/+merge/18250

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2007, 2008 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
74
74
 
75
75
import bzrlib
76
76
from bzrlib import (
77
 
    atomicfile,
78
77
    debug,
79
78
    errors,
80
79
    mail_client,
194
193
            interpreted as a boolean. Returns True or False otherwise.
195
194
        """
196
195
        s = self._get_user_option(option_name)
197
 
        if s is None:
198
 
            # The option doesn't exist
199
 
            return None
200
 
        val = ui.bool_from_string(s)
201
 
        if val is None:
202
 
            # The value can't be interpreted as a boolean
203
 
            trace.warning('Value "%s" is not a boolean for "%s"',
204
 
                          s, option_name)
205
 
        return val
 
196
        return ui.bool_from_string(s)
206
197
 
207
198
    def get_user_option_as_list(self, option_name):
208
199
        """Get a generic option as a list - no special process, no default.
258
249
 
259
250
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
260
251
 
261
 
        $BZR_EMAIL can be set to override this, then
 
252
        $BZR_EMAIL can be set to override this (as well as the
 
253
        deprecated $BZREMAIL), then
262
254
        the concrete policy type is checked, and finally
263
255
        $EMAIL is examined.
264
 
        If no username can be found, errors.NoWhoami exception is raised.
 
256
        If none is found, a reasonable default is (hopefully)
 
257
        created.
265
258
 
266
259
        TODO: Check it's reasonably well-formed.
267
260
        """
277
270
        if v:
278
271
            return v.decode(osutils.get_user_encoding())
279
272
 
280
 
        raise errors.NoWhoami()
281
 
 
282
 
    def ensure_username(self):
283
 
        """Raise errors.NoWhoami if username is not set.
284
 
 
285
 
        This method relies on the username() function raising the error.
286
 
        """
287
 
        self.username()
 
273
        name, email = _auto_user_id()
 
274
        if name:
 
275
            return '%s <%s>' % (name, email)
 
276
        else:
 
277
            return email
288
278
 
289
279
    def signature_checking(self):
290
280
        """What is the current policy for signature checking?."""
478
468
    def _get_nickname(self):
479
469
        return self.get_user_option('nickname')
480
470
 
481
 
    def _write_config_file(self):
482
 
        filename = self._get_filename()
483
 
        atomic_file = atomicfile.AtomicFile(filename)
484
 
        self._get_parser().write(atomic_file)
485
 
        atomic_file.commit()
486
 
        atomic_file.close()
487
 
        osutils.copy_ownership_from_path(filename)
488
 
 
489
471
 
490
472
class GlobalConfig(IniBasedConfig):
491
473
    """The configuration that should be used for a specific location."""
527
509
        self._get_parser().setdefault(section, {})[option] = value
528
510
        self._write_config_file()
529
511
 
 
512
    def _write_config_file(self):
 
513
        f = open(self._get_filename(), 'wb')
 
514
        self._get_parser().write(f)
 
515
        f.close()
 
516
 
530
517
 
531
518
class LocationConfig(IniBasedConfig):
532
519
    """A configuration object that gives the policy for a location."""
666
653
        self._get_parser()[location][option]=value
667
654
        # the allowed values of store match the config policies
668
655
        self._set_option_policy(location, option, store)
669
 
        self._write_config_file()
 
656
        self._get_parser().write(file(self._get_filename(), 'wb'))
670
657
 
671
658
 
672
659
class BranchConfig(Config):
823
810
            os.mkdir(parent_dir)
824
811
        trace.mutter('creating config directory: %r', path)
825
812
        os.mkdir(path)
826
 
        osutils.copy_ownership_from_path(path)
827
813
 
828
814
 
829
815
def config_dir():
844
830
                                  ' or HOME set')
845
831
        return osutils.pathjoin(base, 'bazaar', '2.0')
846
832
    else:
 
833
        # cygwin, linux, and darwin all have a $HOME directory
847
834
        if base is None:
848
835
            base = os.path.expanduser("~")
849
836
        return osutils.pathjoin(base, ".bazaar")
879
866
 
880
867
    This doesn't implicitly create it.
881
868
 
882
 
    On Windows it's in the config directory; elsewhere it's /var/crash
883
 
    which may be monitored by apport.  It can be overridden by
884
 
    $APPORT_CRASH_DIR.
 
869
    On Windows it's in the config directory; elsewhere in the XDG cache directory.
885
870
    """
886
871
    if sys.platform == 'win32':
887
872
        return osutils.pathjoin(config_dir(), 'Crash')
888
873
    else:
889
 
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
890
 
        # 2010-01-31
891
 
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
 
874
        return osutils.pathjoin(xdg_cache_dir(), 'crash')
892
875
 
893
876
 
894
877
def xdg_cache_dir():
901
884
        return os.path.expanduser('~/.cache')
902
885
 
903
886
 
 
887
def _auto_user_id():
 
888
    """Calculate automatic user identification.
 
889
 
 
890
    Returns (realname, email).
 
891
 
 
892
    Only used when none is set in the environment or the id file.
 
893
 
 
894
    This previously used the FQDN as the default domain, but that can
 
895
    be very slow on machines where DNS is broken.  So now we simply
 
896
    use the hostname.
 
897
    """
 
898
    import socket
 
899
 
 
900
    if sys.platform == 'win32':
 
901
        name = win32utils.get_user_name_unicode()
 
902
        if name is None:
 
903
            raise errors.BzrError("Cannot autodetect user name.\n"
 
904
                                  "Please, set your name with command like:\n"
 
905
                                  'bzr whoami "Your Name <name@domain.com>"')
 
906
        host = win32utils.get_host_name_unicode()
 
907
        if host is None:
 
908
            host = socket.gethostname()
 
909
        return name, (name + '@' + host)
 
910
 
 
911
    try:
 
912
        import pwd
 
913
        uid = os.getuid()
 
914
        try:
 
915
            w = pwd.getpwuid(uid)
 
916
        except KeyError:
 
917
            raise errors.BzrCommandError('Unable to determine your name.  '
 
918
                'Please use "bzr whoami" to set it.')
 
919
 
 
920
        # we try utf-8 first, because on many variants (like Linux),
 
921
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
922
        # false positives.  (many users will have their user encoding set to
 
923
        # latin-1, which cannot raise UnicodeError.)
 
924
        try:
 
925
            gecos = w.pw_gecos.decode('utf-8')
 
926
            encoding = 'utf-8'
 
927
        except UnicodeError:
 
928
            try:
 
929
                encoding = osutils.get_user_encoding()
 
930
                gecos = w.pw_gecos.decode(encoding)
 
931
            except UnicodeError:
 
932
                raise errors.BzrCommandError('Unable to determine your name.  '
 
933
                   'Use "bzr whoami" to set it.')
 
934
        try:
 
935
            username = w.pw_name.decode(encoding)
 
936
        except UnicodeError:
 
937
            raise errors.BzrCommandError('Unable to determine your name.  '
 
938
                'Use "bzr whoami" to set it.')
 
939
 
 
940
        comma = gecos.find(',')
 
941
        if comma == -1:
 
942
            realname = gecos
 
943
        else:
 
944
            realname = gecos[:comma]
 
945
        if not realname:
 
946
            realname = username
 
947
 
 
948
    except ImportError:
 
949
        import getpass
 
950
        try:
 
951
            user_encoding = osutils.get_user_encoding()
 
952
            realname = username = getpass.getuser().decode(user_encoding)
 
953
        except UnicodeDecodeError:
 
954
            raise errors.BzrError("Can't decode username as %s." % \
 
955
                    user_encoding)
 
956
 
 
957
    return realname, (username + '@' + socket.gethostname())
 
958
 
 
959
 
904
960
def parse_username(username):
905
961
    """Parse e-mail username and return a (name, address) tuple."""
906
962
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
992
1048
        """Save the config file, only tests should use it for now."""
993
1049
        conf_dir = os.path.dirname(self._filename)
994
1050
        ensure_config_dir_exists(conf_dir)
995
 
        f = file(self._filename, 'wb')
996
 
        try:
997
 
            self._get_config().write(f)
998
 
        finally:
999
 
            f.close()
 
1051
        self._get_config().write(file(self._filename, 'wb'))
1000
1052
 
1001
1053
    def _set_option(self, section_name, option_name, value):
1002
1054
        """Set an authentication configuration option"""
1350
1402
 
1351
1403
 
1352
1404
class PlainTextCredentialStore(CredentialStore):
1353
 
    __doc__ = """Plain text credential store for the authentication.conf file"""
 
1405
    """Plain text credential store for the authentication.conf file."""
1354
1406
 
1355
1407
    def decode_password(self, credentials):
1356
1408
        """See CredentialStore.decode_password."""
1450
1502
            return StringIO()
1451
1503
 
1452
1504
    def _get_configobj(self):
1453
 
        f = self._get_config_file()
1454
 
        try:
1455
 
            return ConfigObj(f, encoding='utf-8')
1456
 
        finally:
1457
 
            f.close()
 
1505
        return ConfigObj(self._get_config_file(), encoding='utf-8')
1458
1506
 
1459
1507
    def _set_configobj(self, configobj):
1460
1508
        out_file = StringIO()