~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-08-13 18:51:45 UTC
  • mfrom: (4595.5.3 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090813185145-ta4t40a5t8z05amk
(Neil Martinsen-Burrell) Include bazaar-vcs.org/BzrGivingBack in
        HACKING.txt

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,
154
153
        """Get the users pop up editor."""
155
154
        raise NotImplementedError
156
155
 
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
156
    def get_mail_client(self):
167
157
        """Get a mail client to use"""
168
158
        selected_client = self.get_user_option('mail_client')
191
181
        """Get a generic option as a boolean - no special process, no default.
192
182
 
193
183
        :return None if the option doesn't exist or its value can't be
194
 
            interpreted as a boolean. Returns True or False otherwise.
 
184
            interpreted as a boolean. Returns True or False ortherwise.
195
185
        """
196
186
        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
 
187
        return ui.bool_from_string(s)
218
188
 
219
189
    def gpg_signing_command(self):
220
190
        """What program should be used to sign signatures?"""
258
228
 
259
229
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
260
230
 
261
 
        $BZR_EMAIL can be set to override this, then
 
231
        $BZR_EMAIL can be set to override this (as well as the
 
232
        deprecated $BZREMAIL), then
262
233
        the concrete policy type is checked, and finally
263
234
        $EMAIL is examined.
264
 
        If no username can be found, errors.NoWhoami exception is raised.
 
235
        If none is found, a reasonable default is (hopefully)
 
236
        created.
265
237
 
266
238
        TODO: Check it's reasonably well-formed.
267
239
        """
277
249
        if v:
278
250
            return v.decode(osutils.get_user_encoding())
279
251
 
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()
 
252
        name, email = _auto_user_id()
 
253
        if name:
 
254
            return '%s <%s>' % (name, email)
 
255
        else:
 
256
            return email
288
257
 
289
258
    def signature_checking(self):
290
259
        """What is the current policy for signature checking?."""
335
304
                path = 'bzr'
336
305
            return path
337
306
 
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
307
 
352
308
class IniBasedConfig(Config):
353
309
    """A configuration policy that draws from ini files."""
390
346
        """Return the policy for the given (section, option_name) pair."""
391
347
        return POLICY_NONE
392
348
 
393
 
    def _get_change_editor(self):
394
 
        return self.get_user_option('change_editor')
395
 
 
396
349
    def _get_signature_checking(self):
397
350
        """See Config._get_signature_checking."""
398
351
        policy = self._get_user_option('check_signatures')
478
431
    def _get_nickname(self):
479
432
        return self.get_user_option('nickname')
480
433
 
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
434
 
490
435
class GlobalConfig(IniBasedConfig):
491
436
    """The configuration that should be used for a specific location."""
527
472
        self._get_parser().setdefault(section, {})[option] = value
528
473
        self._write_config_file()
529
474
 
 
475
    def _write_config_file(self):
 
476
        f = open(self._get_filename(), 'wb')
 
477
        self._get_parser().write(f)
 
478
        f.close()
 
479
 
530
480
 
531
481
class LocationConfig(IniBasedConfig):
532
482
    """A configuration object that gives the policy for a location."""
666
616
        self._get_parser()[location][option]=value
667
617
        # the allowed values of store match the config policies
668
618
        self._set_option_policy(location, option, store)
669
 
        self._write_config_file()
 
619
        self._get_parser().write(file(self._get_filename(), 'wb'))
670
620
 
671
621
 
672
622
class BranchConfig(Config):
729
679
 
730
680
        return self._get_best_value('_get_user_id')
731
681
 
732
 
    def _get_change_editor(self):
733
 
        return self._get_best_value('_get_change_editor')
734
 
 
735
682
    def _get_signature_checking(self):
736
683
        """See Config._get_signature_checking."""
737
684
        return self._get_best_value('_get_signature_checking')
823
770
            os.mkdir(parent_dir)
824
771
        trace.mutter('creating config directory: %r', path)
825
772
        os.mkdir(path)
826
 
        osutils.copy_ownership_from_path(path)
827
773
 
828
774
 
829
775
def config_dir():
844
790
                                  ' or HOME set')
845
791
        return osutils.pathjoin(base, 'bazaar', '2.0')
846
792
    else:
 
793
        # cygwin, linux, and darwin all have a $HOME directory
847
794
        if base is None:
848
795
            base = os.path.expanduser("~")
849
796
        return osutils.pathjoin(base, ".bazaar")
874
821
    return osutils.pathjoin(config_dir(), 'ignore')
875
822
 
876
823
 
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.
 
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.
885
834
    """
 
835
    import socket
 
836
 
886
837
    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')
 
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())
902
895
 
903
896
 
904
897
def parse_username(username):
992
985
        """Save the config file, only tests should use it for now."""
993
986
        conf_dir = os.path.dirname(self._filename)
994
987
        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()
 
988
        self._get_config().write(file(self._filename, 'wb'))
1000
989
 
1001
990
    def _set_option(self, section_name, option_name, value):
1002
991
        """Set an authentication configuration option"""
1350
1339
 
1351
1340
 
1352
1341
class PlainTextCredentialStore(CredentialStore):
1353
 
    __doc__ = """Plain text credential store for the authentication.conf file"""
 
1342
    """Plain text credential store for the authentication.conf file."""
1354
1343
 
1355
1344
    def decode_password(self, credentials):
1356
1345
        """See CredentialStore.decode_password."""
1445
1434
 
1446
1435
    def _get_config_file(self):
1447
1436
        try:
1448
 
            return StringIO(self._transport.get_bytes(self._filename))
 
1437
            return self._transport.get(self._filename)
1449
1438
        except errors.NoSuchFile:
1450
1439
            return StringIO()
1451
1440
 
1452
1441
    def _get_configobj(self):
1453
 
        f = self._get_config_file()
1454
 
        try:
1455
 
            return ConfigObj(f, encoding='utf-8')
1456
 
        finally:
1457
 
            f.close()
 
1442
        return ConfigObj(self._get_config_file(), encoding='utf-8')
1458
1443
 
1459
1444
    def _set_configobj(self, configobj):
1460
1445
        out_file = StringIO()