~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Aaron Bentley
  • Date: 2009-06-29 15:07:51 UTC
  • mto: This revision was merged to the branch mainline in revision 4490.
  • Revision ID: aaron@aaronbentley.com-20090629150751-gpdjzontba589vxf
Move test_inconsistency_fatal to test_repository

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,
147
146
class Config(object):
148
147
    """A configuration policy - what username, editor, gpg needs etc."""
149
148
 
150
 
    def __init__(self):
151
 
        super(Config, self).__init__()
152
 
 
153
149
    def get_editor(self):
154
150
        """Get the users pop up editor."""
155
151
        raise NotImplementedError
156
152
 
157
 
    def get_change_editor(self, old_tree, new_tree):
158
 
        from bzrlib import diff
159
 
        cmd = self._get_change_editor()
160
 
        if cmd is None:
161
 
            return None
162
 
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
163
 
                                             sys.stdout)
164
 
 
165
 
 
166
153
    def get_mail_client(self):
167
154
        """Get a mail client to use"""
168
155
        selected_client = self.get_user_option('mail_client')
187
174
        """Get a generic option - no special process, no default."""
188
175
        return self._get_user_option(option_name)
189
176
 
190
 
    def get_user_option_as_bool(self, option_name):
191
 
        """Get a generic option as a boolean - no special process, no default.
192
 
 
193
 
        :return None if the option doesn't exist or its value can't be
194
 
            interpreted as a boolean. Returns True or False otherwise.
195
 
        """
196
 
        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
206
 
 
207
 
    def get_user_option_as_list(self, option_name):
208
 
        """Get a generic option as a list - no special process, no default.
209
 
 
210
 
        :return None if the option doesn't exist. Returns the value as a list
211
 
            otherwise.
212
 
        """
213
 
        l = self._get_user_option(option_name)
214
 
        if isinstance(l, (str, unicode)):
215
 
            # A single value, most probably the user forgot the final ','
216
 
            l = [l]
217
 
        return l
218
 
 
219
177
    def gpg_signing_command(self):
220
178
        """What program should be used to sign signatures?"""
221
179
        result = self._gpg_signing_command()
238
196
        """See log_format()."""
239
197
        return None
240
198
 
 
199
    def __init__(self):
 
200
        super(Config, self).__init__()
 
201
 
241
202
    def post_commit(self):
242
203
        """An ordered list of python functions to call.
243
204
 
258
219
 
259
220
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
260
221
 
261
 
        $BZR_EMAIL can be set to override this, then
 
222
        $BZR_EMAIL can be set to override this (as well as the
 
223
        deprecated $BZREMAIL), then
262
224
        the concrete policy type is checked, and finally
263
225
        $EMAIL is examined.
264
 
        If no username can be found, errors.NoWhoami exception is raised.
 
226
        If none is found, a reasonable default is (hopefully)
 
227
        created.
265
228
 
266
229
        TODO: Check it's reasonably well-formed.
267
230
        """
277
240
        if v:
278
241
            return v.decode(osutils.get_user_encoding())
279
242
 
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()
 
243
        name, email = _auto_user_id()
 
244
        if name:
 
245
            return '%s <%s>' % (name, email)
 
246
        else:
 
247
            return email
288
248
 
289
249
    def signature_checking(self):
290
250
        """What is the current policy for signature checking?."""
335
295
                path = 'bzr'
336
296
            return path
337
297
 
338
 
    def suppress_warning(self, warning):
339
 
        """Should the warning be suppressed or emitted.
340
 
 
341
 
        :param warning: The name of the warning being tested.
342
 
 
343
 
        :returns: True if the warning should be suppressed, False otherwise.
344
 
        """
345
 
        warnings = self.get_user_option_as_list('suppress_warnings')
346
 
        if warnings is None or warning not in warnings:
347
 
            return False
348
 
        else:
349
 
            return True
350
 
 
351
298
 
352
299
class IniBasedConfig(Config):
353
300
    """A configuration policy that draws from ini files."""
354
301
 
355
 
    def __init__(self, get_filename):
356
 
        super(IniBasedConfig, self).__init__()
357
 
        self._get_filename = get_filename
358
 
        self._parser = None
359
 
 
360
302
    def _get_parser(self, file=None):
361
303
        if self._parser is not None:
362
304
            return self._parser
390
332
        """Return the policy for the given (section, option_name) pair."""
391
333
        return POLICY_NONE
392
334
 
393
 
    def _get_change_editor(self):
394
 
        return self.get_user_option('change_editor')
395
 
 
396
335
    def _get_signature_checking(self):
397
336
        """See Config._get_signature_checking."""
398
337
        policy = self._get_user_option('check_signatures')
442
381
        """See Config.log_format."""
443
382
        return self._get_user_option('log_format')
444
383
 
 
384
    def __init__(self, get_filename):
 
385
        super(IniBasedConfig, self).__init__()
 
386
        self._get_filename = get_filename
 
387
        self._parser = None
 
388
 
445
389
    def _post_commit(self):
446
390
        """See Config.post_commit."""
447
391
        return self._get_user_option('post_commit')
478
422
    def _get_nickname(self):
479
423
        return self.get_user_option('nickname')
480
424
 
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
425
 
490
426
class GlobalConfig(IniBasedConfig):
491
427
    """The configuration that should be used for a specific location."""
527
463
        self._get_parser().setdefault(section, {})[option] = value
528
464
        self._write_config_file()
529
465
 
 
466
    def _write_config_file(self):
 
467
        f = open(self._get_filename(), 'wb')
 
468
        self._get_parser().write(f)
 
469
        f.close()
 
470
 
530
471
 
531
472
class LocationConfig(IniBasedConfig):
532
473
    """A configuration object that gives the policy for a location."""
666
607
        self._get_parser()[location][option]=value
667
608
        # the allowed values of store match the config policies
668
609
        self._set_option_policy(location, option, store)
669
 
        self._write_config_file()
 
610
        self._get_parser().write(file(self._get_filename(), 'wb'))
670
611
 
671
612
 
672
613
class BranchConfig(Config):
729
670
 
730
671
        return self._get_best_value('_get_user_id')
731
672
 
732
 
    def _get_change_editor(self):
733
 
        return self._get_best_value('_get_change_editor')
734
 
 
735
673
    def _get_signature_checking(self):
736
674
        """See Config._get_signature_checking."""
737
675
        return self._get_best_value('_get_signature_checking')
823
761
            os.mkdir(parent_dir)
824
762
        trace.mutter('creating config directory: %r', path)
825
763
        os.mkdir(path)
826
 
        osutils.copy_ownership_from_path(path)
827
764
 
828
765
 
829
766
def config_dir():
844
781
                                  ' or HOME set')
845
782
        return osutils.pathjoin(base, 'bazaar', '2.0')
846
783
    else:
 
784
        # cygwin, linux, and darwin all have a $HOME directory
847
785
        if base is None:
848
786
            base = os.path.expanduser("~")
849
787
        return osutils.pathjoin(base, ".bazaar")
874
812
    return osutils.pathjoin(config_dir(), 'ignore')
875
813
 
876
814
 
877
 
def crash_dir():
878
 
    """Return the directory name to store crash files.
879
 
 
880
 
    This doesn't implicitly create it.
881
 
 
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.
 
815
def _auto_user_id():
 
816
    """Calculate automatic user identification.
 
817
 
 
818
    Returns (realname, email).
 
819
 
 
820
    Only used when none is set in the environment or the id file.
 
821
 
 
822
    This previously used the FQDN as the default domain, but that can
 
823
    be very slow on machines where DNS is broken.  So now we simply
 
824
    use the hostname.
885
825
    """
 
826
    import socket
 
827
 
886
828
    if sys.platform == 'win32':
887
 
        return osutils.pathjoin(config_dir(), 'Crash')
888
 
    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')
892
 
 
893
 
 
894
 
def xdg_cache_dir():
895
 
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
896
 
    # Possibly this should be different on Windows?
897
 
    e = os.environ.get('XDG_CACHE_DIR', None)
898
 
    if e:
899
 
        return e
900
 
    else:
901
 
        return os.path.expanduser('~/.cache')
 
829
        name = win32utils.get_user_name_unicode()
 
830
        if name is None:
 
831
            raise errors.BzrError("Cannot autodetect user name.\n"
 
832
                                  "Please, set your name with command like:\n"
 
833
                                  'bzr whoami "Your Name <name@domain.com>"')
 
834
        host = win32utils.get_host_name_unicode()
 
835
        if host is None:
 
836
            host = socket.gethostname()
 
837
        return name, (name + '@' + host)
 
838
 
 
839
    try:
 
840
        import pwd
 
841
        uid = os.getuid()
 
842
        try:
 
843
            w = pwd.getpwuid(uid)
 
844
        except KeyError:
 
845
            raise errors.BzrCommandError('Unable to determine your name.  '
 
846
                'Please use "bzr whoami" to set it.')
 
847
 
 
848
        # we try utf-8 first, because on many variants (like Linux),
 
849
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
850
        # false positives.  (many users will have their user encoding set to
 
851
        # latin-1, which cannot raise UnicodeError.)
 
852
        try:
 
853
            gecos = w.pw_gecos.decode('utf-8')
 
854
            encoding = 'utf-8'
 
855
        except UnicodeError:
 
856
            try:
 
857
                encoding = osutils.get_user_encoding()
 
858
                gecos = w.pw_gecos.decode(encoding)
 
859
            except UnicodeError:
 
860
                raise errors.BzrCommandError('Unable to determine your name.  '
 
861
                   'Use "bzr whoami" to set it.')
 
862
        try:
 
863
            username = w.pw_name.decode(encoding)
 
864
        except UnicodeError:
 
865
            raise errors.BzrCommandError('Unable to determine your name.  '
 
866
                'Use "bzr whoami" to set it.')
 
867
 
 
868
        comma = gecos.find(',')
 
869
        if comma == -1:
 
870
            realname = gecos
 
871
        else:
 
872
            realname = gecos[:comma]
 
873
        if not realname:
 
874
            realname = username
 
875
 
 
876
    except ImportError:
 
877
        import getpass
 
878
        try:
 
879
            user_encoding = osutils.get_user_encoding()
 
880
            realname = username = getpass.getuser().decode(user_encoding)
 
881
        except UnicodeDecodeError:
 
882
            raise errors.BzrError("Can't decode username as %s." % \
 
883
                    user_encoding)
 
884
 
 
885
    return realname, (username + '@' + socket.gethostname())
902
886
 
903
887
 
904
888
def parse_username(username):
992
976
        """Save the config file, only tests should use it for now."""
993
977
        conf_dir = os.path.dirname(self._filename)
994
978
        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()
 
979
        self._get_config().write(file(self._filename, 'wb'))
1000
980
 
1001
981
    def _set_option(self, section_name, option_name, value):
1002
982
        """Set an authentication configuration option"""
1350
1330
 
1351
1331
 
1352
1332
class PlainTextCredentialStore(CredentialStore):
1353
 
    __doc__ = """Plain text credential store for the authentication.conf file"""
 
1333
    """Plain text credential store for the authentication.conf file."""
1354
1334
 
1355
1335
    def decode_password(self, credentials):
1356
1336
        """See CredentialStore.decode_password."""
1445
1425
 
1446
1426
    def _get_config_file(self):
1447
1427
        try:
1448
 
            return StringIO(self._transport.get_bytes(self._filename))
 
1428
            return self._transport.get(self._filename)
1449
1429
        except errors.NoSuchFile:
1450
1430
            return StringIO()
1451
1431
 
1452
1432
    def _get_configobj(self):
1453
 
        f = self._get_config_file()
1454
 
        try:
1455
 
            return ConfigObj(f, encoding='utf-8')
1456
 
        finally:
1457
 
            f.close()
 
1433
        return ConfigObj(self._get_config_file(), encoding='utf-8')
1458
1434
 
1459
1435
    def _set_configobj(self, configobj):
1460
1436
        out_file = StringIO()