~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: John Arbash Meinel
  • Date: 2010-08-02 17:16:12 UTC
  • mto: This revision was merged to the branch mainline in revision 5369.
  • Revision ID: john@arbash-meinel.com-20100802171612-rdh5ods70w2bl3j7
We also have to re-implement it for _simple_set_pyx.pyx

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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,
77
78
    debug,
78
79
    errors,
79
80
    mail_client,
146
147
class Config(object):
147
148
    """A configuration policy - what username, editor, gpg needs etc."""
148
149
 
 
150
    def __init__(self):
 
151
        super(Config, self).__init__()
 
152
 
149
153
    def get_editor(self):
150
154
        """Get the users pop up editor."""
151
155
        raise NotImplementedError
152
156
 
 
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
 
153
166
    def get_mail_client(self):
154
167
        """Get a mail client to use"""
155
168
        selected_client = self.get_user_option('mail_client')
174
187
        """Get a generic option - no special process, no default."""
175
188
        return self._get_user_option(option_name)
176
189
 
 
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
 
177
219
    def gpg_signing_command(self):
178
220
        """What program should be used to sign signatures?"""
179
221
        result = self._gpg_signing_command()
196
238
        """See log_format()."""
197
239
        return None
198
240
 
199
 
    def __init__(self):
200
 
        super(Config, self).__init__()
201
 
 
202
241
    def post_commit(self):
203
242
        """An ordered list of python functions to call.
204
243
 
219
258
 
220
259
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
221
260
 
222
 
        $BZR_EMAIL can be set to override this (as well as the
223
 
        deprecated $BZREMAIL), then
 
261
        $BZR_EMAIL can be set to override this, then
224
262
        the concrete policy type is checked, and finally
225
263
        $EMAIL is examined.
226
 
        If none is found, a reasonable default is (hopefully)
227
 
        created.
 
264
        If no username can be found, errors.NoWhoami exception is raised.
228
265
 
229
266
        TODO: Check it's reasonably well-formed.
230
267
        """
240
277
        if v:
241
278
            return v.decode(osutils.get_user_encoding())
242
279
 
243
 
        name, email = _auto_user_id()
244
 
        if name:
245
 
            return '%s <%s>' % (name, email)
246
 
        else:
247
 
            return email
 
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()
248
288
 
249
289
    def signature_checking(self):
250
290
        """What is the current policy for signature checking?."""
295
335
                path = 'bzr'
296
336
            return path
297
337
 
 
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
 
298
351
 
299
352
class IniBasedConfig(Config):
300
353
    """A configuration policy that draws from ini files."""
301
354
 
 
355
    def __init__(self, get_filename):
 
356
        super(IniBasedConfig, self).__init__()
 
357
        self._get_filename = get_filename
 
358
        self._parser = None
 
359
 
302
360
    def _get_parser(self, file=None):
303
361
        if self._parser is not None:
304
362
            return self._parser
332
390
        """Return the policy for the given (section, option_name) pair."""
333
391
        return POLICY_NONE
334
392
 
 
393
    def _get_change_editor(self):
 
394
        return self.get_user_option('change_editor')
 
395
 
335
396
    def _get_signature_checking(self):
336
397
        """See Config._get_signature_checking."""
337
398
        policy = self._get_user_option('check_signatures')
381
442
        """See Config.log_format."""
382
443
        return self._get_user_option('log_format')
383
444
 
384
 
    def __init__(self, get_filename):
385
 
        super(IniBasedConfig, self).__init__()
386
 
        self._get_filename = get_filename
387
 
        self._parser = None
388
 
 
389
445
    def _post_commit(self):
390
446
        """See Config.post_commit."""
391
447
        return self._get_user_option('post_commit')
422
478
    def _get_nickname(self):
423
479
        return self.get_user_option('nickname')
424
480
 
 
481
    def _write_config_file(self):
 
482
        atomic_file = atomicfile.AtomicFile(self._get_filename())
 
483
        self._get_parser().write(atomic_file)
 
484
        atomic_file.commit()
 
485
        atomic_file.close()
 
486
 
425
487
 
426
488
class GlobalConfig(IniBasedConfig):
427
489
    """The configuration that should be used for a specific location."""
463
525
        self._get_parser().setdefault(section, {})[option] = value
464
526
        self._write_config_file()
465
527
 
466
 
    def _write_config_file(self):
467
 
        f = open(self._get_filename(), 'wb')
468
 
        self._get_parser().write(f)
469
 
        f.close()
470
 
 
471
528
 
472
529
class LocationConfig(IniBasedConfig):
473
530
    """A configuration object that gives the policy for a location."""
607
664
        self._get_parser()[location][option]=value
608
665
        # the allowed values of store match the config policies
609
666
        self._set_option_policy(location, option, store)
610
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
667
        self._write_config_file()
611
668
 
612
669
 
613
670
class BranchConfig(Config):
670
727
 
671
728
        return self._get_best_value('_get_user_id')
672
729
 
 
730
    def _get_change_editor(self):
 
731
        return self._get_best_value('_get_change_editor')
 
732
 
673
733
    def _get_signature_checking(self):
674
734
        """See Config._get_signature_checking."""
675
735
        return self._get_best_value('_get_signature_checking')
761
821
            os.mkdir(parent_dir)
762
822
        trace.mutter('creating config directory: %r', path)
763
823
        os.mkdir(path)
 
824
        osutils.copy_ownership_from_path(path)
764
825
 
765
826
 
766
827
def config_dir():
781
842
                                  ' or HOME set')
782
843
        return osutils.pathjoin(base, 'bazaar', '2.0')
783
844
    else:
784
 
        # cygwin, linux, and darwin all have a $HOME directory
785
845
        if base is None:
786
846
            base = os.path.expanduser("~")
787
847
        return osutils.pathjoin(base, ".bazaar")
812
872
    return osutils.pathjoin(config_dir(), 'ignore')
813
873
 
814
874
 
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.
 
875
def crash_dir():
 
876
    """Return the directory name to store crash files.
 
877
 
 
878
    This doesn't implicitly create it.
 
879
 
 
880
    On Windows it's in the config directory; elsewhere it's /var/crash
 
881
    which may be monitored by apport.  It can be overridden by
 
882
    $APPORT_CRASH_DIR.
825
883
    """
826
 
    import socket
827
 
 
828
884
    if sys.platform == 'win32':
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())
 
885
        return osutils.pathjoin(config_dir(), 'Crash')
 
886
    else:
 
887
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
 
888
        # 2010-01-31
 
889
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
 
890
 
 
891
 
 
892
def xdg_cache_dir():
 
893
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
 
894
    # Possibly this should be different on Windows?
 
895
    e = os.environ.get('XDG_CACHE_DIR', None)
 
896
    if e:
 
897
        return e
 
898
    else:
 
899
        return os.path.expanduser('~/.cache')
886
900
 
887
901
 
888
902
def parse_username(username):
976
990
        """Save the config file, only tests should use it for now."""
977
991
        conf_dir = os.path.dirname(self._filename)
978
992
        ensure_config_dir_exists(conf_dir)
979
 
        self._get_config().write(file(self._filename, 'wb'))
 
993
        f = file(self._filename, 'wb')
 
994
        try:
 
995
            self._get_config().write(f)
 
996
        finally:
 
997
            f.close()
980
998
 
981
999
    def _set_option(self, section_name, option_name, value):
982
1000
        """Set an authentication configuration option"""
1330
1348
 
1331
1349
 
1332
1350
class PlainTextCredentialStore(CredentialStore):
1333
 
    """Plain text credential store for the authentication.conf file."""
 
1351
    __doc__ = """Plain text credential store for the authentication.conf file"""
1334
1352
 
1335
1353
    def decode_password(self, credentials):
1336
1354
        """See CredentialStore.decode_password."""
1425
1443
 
1426
1444
    def _get_config_file(self):
1427
1445
        try:
1428
 
            return self._transport.get(self._filename)
 
1446
            return StringIO(self._transport.get_bytes(self._filename))
1429
1447
        except errors.NoSuchFile:
1430
1448
            return StringIO()
1431
1449
 
1432
1450
    def _get_configobj(self):
1433
 
        return ConfigObj(self._get_config_file(), encoding='utf-8')
 
1451
        f = self._get_config_file()
 
1452
        try:
 
1453
            return ConfigObj(f, encoding='utf-8')
 
1454
        finally:
 
1455
            f.close()
1434
1456
 
1435
1457
    def _set_configobj(self, configobj):
1436
1458
        out_file = StringIO()