~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Gary van der Merwe
  • Date: 2010-08-02 19:56:52 UTC
  • mfrom: (5050.3.18 2.2)
  • mto: (5050.3.19 2.2)
  • mto: This revision was merged to the branch mainline in revision 5371.
  • Revision ID: garyvdm@gmail.com-20100802195652-o1ppjemhwrr98i61
MergeĀ lp:bzr/2.2.

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,
153
154
        """Get the users pop up editor."""
154
155
        raise NotImplementedError
155
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
 
156
166
    def get_mail_client(self):
157
167
        """Get a mail client to use"""
158
168
        selected_client = self.get_user_option('mail_client')
181
191
        """Get a generic option as a boolean - no special process, no default.
182
192
 
183
193
        :return None if the option doesn't exist or its value can't be
184
 
            interpreted as a boolean. Returns True or False ortherwise.
 
194
            interpreted as a boolean. Returns True or False otherwise.
185
195
        """
186
196
        s = self._get_user_option(option_name)
187
 
        return ui.bool_from_string(s)
 
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
188
218
 
189
219
    def gpg_signing_command(self):
190
220
        """What program should be used to sign signatures?"""
228
258
 
229
259
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
230
260
 
231
 
        $BZR_EMAIL can be set to override this (as well as the
232
 
        deprecated $BZREMAIL), then
 
261
        $BZR_EMAIL can be set to override this, then
233
262
        the concrete policy type is checked, and finally
234
263
        $EMAIL is examined.
235
 
        If none is found, a reasonable default is (hopefully)
236
 
        created.
 
264
        If no username can be found, errors.NoWhoami exception is raised.
237
265
 
238
266
        TODO: Check it's reasonably well-formed.
239
267
        """
249
277
        if v:
250
278
            return v.decode(osutils.get_user_encoding())
251
279
 
252
 
        name, email = _auto_user_id()
253
 
        if name:
254
 
            return '%s <%s>' % (name, email)
255
 
        else:
256
 
            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()
257
288
 
258
289
    def signature_checking(self):
259
290
        """What is the current policy for signature checking?."""
304
335
                path = 'bzr'
305
336
            return path
306
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
 
307
351
 
308
352
class IniBasedConfig(Config):
309
353
    """A configuration policy that draws from ini files."""
346
390
        """Return the policy for the given (section, option_name) pair."""
347
391
        return POLICY_NONE
348
392
 
 
393
    def _get_change_editor(self):
 
394
        return self.get_user_option('change_editor')
 
395
 
349
396
    def _get_signature_checking(self):
350
397
        """See Config._get_signature_checking."""
351
398
        policy = self._get_user_option('check_signatures')
431
478
    def _get_nickname(self):
432
479
        return self.get_user_option('nickname')
433
480
 
 
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
 
434
489
 
435
490
class GlobalConfig(IniBasedConfig):
436
491
    """The configuration that should be used for a specific location."""
472
527
        self._get_parser().setdefault(section, {})[option] = value
473
528
        self._write_config_file()
474
529
 
475
 
    def _write_config_file(self):
476
 
        f = open(self._get_filename(), 'wb')
477
 
        self._get_parser().write(f)
478
 
        f.close()
479
 
 
480
530
 
481
531
class LocationConfig(IniBasedConfig):
482
532
    """A configuration object that gives the policy for a location."""
616
666
        self._get_parser()[location][option]=value
617
667
        # the allowed values of store match the config policies
618
668
        self._set_option_policy(location, option, store)
619
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
669
        self._write_config_file()
620
670
 
621
671
 
622
672
class BranchConfig(Config):
679
729
 
680
730
        return self._get_best_value('_get_user_id')
681
731
 
 
732
    def _get_change_editor(self):
 
733
        return self._get_best_value('_get_change_editor')
 
734
 
682
735
    def _get_signature_checking(self):
683
736
        """See Config._get_signature_checking."""
684
737
        return self._get_best_value('_get_signature_checking')
770
823
            os.mkdir(parent_dir)
771
824
        trace.mutter('creating config directory: %r', path)
772
825
        os.mkdir(path)
 
826
        osutils.copy_ownership_from_path(path)
773
827
 
774
828
 
775
829
def config_dir():
790
844
                                  ' or HOME set')
791
845
        return osutils.pathjoin(base, 'bazaar', '2.0')
792
846
    else:
793
 
        # cygwin, linux, and darwin all have a $HOME directory
794
847
        if base is None:
795
848
            base = os.path.expanduser("~")
796
849
        return osutils.pathjoin(base, ".bazaar")
821
874
    return osutils.pathjoin(config_dir(), 'ignore')
822
875
 
823
876
 
824
 
def _auto_user_id():
825
 
    """Calculate automatic user identification.
826
 
 
827
 
    Returns (realname, email).
828
 
 
829
 
    Only used when none is set in the environment or the id file.
830
 
 
831
 
    This previously used the FQDN as the default domain, but that can
832
 
    be very slow on machines where DNS is broken.  So now we simply
833
 
    use the hostname.
 
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.
834
885
    """
835
 
    import socket
836
 
 
837
886
    if sys.platform == 'win32':
838
 
        name = win32utils.get_user_name_unicode()
839
 
        if name is None:
840
 
            raise errors.BzrError("Cannot autodetect user name.\n"
841
 
                                  "Please, set your name with command like:\n"
842
 
                                  'bzr whoami "Your Name <name@domain.com>"')
843
 
        host = win32utils.get_host_name_unicode()
844
 
        if host is None:
845
 
            host = socket.gethostname()
846
 
        return name, (name + '@' + host)
847
 
 
848
 
    try:
849
 
        import pwd
850
 
        uid = os.getuid()
851
 
        try:
852
 
            w = pwd.getpwuid(uid)
853
 
        except KeyError:
854
 
            raise errors.BzrCommandError('Unable to determine your name.  '
855
 
                'Please use "bzr whoami" to set it.')
856
 
 
857
 
        # we try utf-8 first, because on many variants (like Linux),
858
 
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
859
 
        # false positives.  (many users will have their user encoding set to
860
 
        # latin-1, which cannot raise UnicodeError.)
861
 
        try:
862
 
            gecos = w.pw_gecos.decode('utf-8')
863
 
            encoding = 'utf-8'
864
 
        except UnicodeError:
865
 
            try:
866
 
                encoding = osutils.get_user_encoding()
867
 
                gecos = w.pw_gecos.decode(encoding)
868
 
            except UnicodeError:
869
 
                raise errors.BzrCommandError('Unable to determine your name.  '
870
 
                   'Use "bzr whoami" to set it.')
871
 
        try:
872
 
            username = w.pw_name.decode(encoding)
873
 
        except UnicodeError:
874
 
            raise errors.BzrCommandError('Unable to determine your name.  '
875
 
                'Use "bzr whoami" to set it.')
876
 
 
877
 
        comma = gecos.find(',')
878
 
        if comma == -1:
879
 
            realname = gecos
880
 
        else:
881
 
            realname = gecos[:comma]
882
 
        if not realname:
883
 
            realname = username
884
 
 
885
 
    except ImportError:
886
 
        import getpass
887
 
        try:
888
 
            user_encoding = osutils.get_user_encoding()
889
 
            realname = username = getpass.getuser().decode(user_encoding)
890
 
        except UnicodeDecodeError:
891
 
            raise errors.BzrError("Can't decode username as %s." % \
892
 
                    user_encoding)
893
 
 
894
 
    return realname, (username + '@' + socket.gethostname())
 
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')
895
902
 
896
903
 
897
904
def parse_username(username):
985
992
        """Save the config file, only tests should use it for now."""
986
993
        conf_dir = os.path.dirname(self._filename)
987
994
        ensure_config_dir_exists(conf_dir)
988
 
        self._get_config().write(file(self._filename, 'wb'))
 
995
        f = file(self._filename, 'wb')
 
996
        try:
 
997
            self._get_config().write(f)
 
998
        finally:
 
999
            f.close()
989
1000
 
990
1001
    def _set_option(self, section_name, option_name, value):
991
1002
        """Set an authentication configuration option"""
1339
1350
 
1340
1351
 
1341
1352
class PlainTextCredentialStore(CredentialStore):
1342
 
    """Plain text credential store for the authentication.conf file."""
 
1353
    __doc__ = """Plain text credential store for the authentication.conf file"""
1343
1354
 
1344
1355
    def decode_password(self, credentials):
1345
1356
        """See CredentialStore.decode_password."""
1434
1445
 
1435
1446
    def _get_config_file(self):
1436
1447
        try:
1437
 
            return self._transport.get(self._filename)
 
1448
            return StringIO(self._transport.get_bytes(self._filename))
1438
1449
        except errors.NoSuchFile:
1439
1450
            return StringIO()
1440
1451
 
1441
1452
    def _get_configobj(self):
1442
 
        return ConfigObj(self._get_config_file(), encoding='utf-8')
 
1453
        f = self._get_config_file()
 
1454
        try:
 
1455
            return ConfigObj(f, encoding='utf-8')
 
1456
        finally:
 
1457
            f.close()
1443
1458
 
1444
1459
    def _set_configobj(self, configobj):
1445
1460
        out_file = StringIO()