130
def ConfigObj(*args, **kwargs):
132
if _ConfigObj is None:
133
class ConfigObj(configobj.ConfigObj):
135
def get_bool(self, section, key):
136
return self[section].as_bool(key)
138
def get_value(self, section, name):
139
# Try [] for the old DEFAULT section.
140
if section == "DEFAULT":
145
return self[section][name]
146
_ConfigObj = ConfigObj
147
return _ConfigObj(*args, **kwargs)
125
class ConfigObj(configobj.ConfigObj):
127
def get_bool(self, section, key):
128
return self[section].as_bool(key)
130
def get_value(self, section, name):
131
# Try [] for the old DEFAULT section.
132
if section == "DEFAULT":
137
return self[section][name]
150
140
class Config(object):
151
141
"""A configuration policy - what username, editor, gpg needs etc."""
154
super(Config, self).__init__()
156
143
def get_editor(self):
157
144
"""Get the users pop up editor."""
158
145
raise NotImplementedError
160
def get_change_editor(self, old_tree, new_tree):
161
from bzrlib import diff
162
cmd = self._get_change_editor()
165
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
169
147
def get_mail_client(self):
170
148
"""Get a mail client to use"""
171
149
selected_client = self.get_user_option('mail_client')
172
_registry = mail_client.mail_client_registry
174
mail_client_class = _registry.get(selected_client)
151
mail_client_class = {
152
None: mail_client.DefaultMail,
154
'evolution': mail_client.Evolution,
155
'kmail': mail_client.KMail,
156
'mutt': mail_client.Mutt,
157
'thunderbird': mail_client.Thunderbird,
159
'default': mail_client.DefaultMail,
160
'editor': mail_client.Editor,
161
'mapi': mail_client.MAPIClient,
162
'xdg-email': mail_client.XDGEmail,
176
165
raise errors.UnknownMailClient(selected_client)
177
166
return mail_client_class(self)
341
def suppress_warning(self, warning):
342
"""Should the warning be suppressed or emitted.
344
:param warning: The name of the warning being tested.
346
:returns: True if the warning should be suppressed, False otherwise.
348
warnings = self.get_user_option_as_list('suppress_warnings')
349
if warnings is None or warning not in warnings:
355
304
class IniBasedConfig(Config):
356
305
"""A configuration policy that draws from ini files."""
358
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
360
"""Base class for configuration files using an ini-like syntax.
362
:param file_name: The configuration file path.
364
super(IniBasedConfig, self).__init__()
365
self.file_name = file_name
366
if symbol_versioning.deprecated_passed(get_filename):
367
symbol_versioning.warn(
368
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
369
' Use file_name instead.',
372
if get_filename is not None:
373
self.file_name = get_filename()
375
self.file_name = file_name
380
def from_string(cls, str_or_unicode, file_name=None, save=False):
381
"""Create a config object from a string.
383
:param str_or_unicode: A string representing the file content. This will
386
:param file_name: The configuration file path.
388
:param _save: Whether the file should be saved upon creation.
390
conf = cls(file_name=file_name)
391
conf._create_from_string(str_or_unicode, save)
394
def _create_from_string(self, str_or_unicode, save):
395
self._content = StringIO(str_or_unicode.encode('utf-8'))
396
# Some tests use in-memory configs, some other always need the config
397
# file to exist on disk.
399
self._write_config_file()
401
def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
307
def _get_parser(self, file=None):
402
308
if self._parser is not None:
403
309
return self._parser
404
if symbol_versioning.deprecated_passed(file):
405
symbol_versioning.warn(
406
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
407
' Use IniBasedConfig(_content=xxx) instead.',
410
if self._content is not None:
411
co_input = self._content
412
elif self.file_name is None:
413
raise AssertionError('We have no content to create the config')
311
input = self._get_filename()
415
co_input = self.file_name
417
self._parser = ConfigObj(co_input, encoding='utf-8')
315
self._parser = ConfigObj(input, encoding='utf-8')
418
316
except configobj.ConfigObjError, e:
419
317
raise errors.ParseConfigError(e.errors, e.config.filename)
420
# Make sure self.reload() will use the right file name
421
self._parser.filename = self.file_name
422
318
return self._parser
425
"""Reload the config file from disk."""
426
if self.file_name is None:
427
raise AssertionError('We need a file name to reload the config')
428
if self._parser is not None:
429
self._parser.reload()
431
320
def _get_matching_sections(self):
432
321
"""Return an ordered list of (section_name, extra_path) pairs.
536
427
def _get_nickname(self):
537
428
return self.get_user_option('nickname')
539
def _write_config_file(self):
540
if self.file_name is None:
541
raise AssertionError('We cannot save, self.file_name is None')
542
conf_dir = os.path.dirname(self.file_name)
543
ensure_config_dir_exists(conf_dir)
544
atomic_file = atomicfile.AtomicFile(self.file_name)
545
self._get_parser().write(atomic_file)
548
osutils.copy_ownership_from_path(self.file_name)
551
class LockableConfig(IniBasedConfig):
552
"""A configuration needing explicit locking for access.
554
If several processes try to write the config file, the accesses need to be
557
Daughter classes should decorate all methods that update a config with the
558
``@needs_write_lock`` decorator (they call, directly or indirectly, the
559
``_write_config_file()`` method. These methods (typically ``set_option()``
560
and variants must reload the config file from disk before calling
561
``_write_config_file()``), this can be achieved by calling the
562
``self.reload()`` method. Note that the lock scope should cover both the
563
reading and the writing of the config file which is why the decorator can't
564
be applied to ``_write_config_file()`` only.
566
This should be enough to implement the following logic:
567
- lock for exclusive write access,
568
- reload the config file from disk,
572
This logic guarantees that a writer can update a value without erasing an
573
update made by another writer.
578
def __init__(self, file_name):
579
super(LockableConfig, self).__init__(file_name=file_name)
580
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
581
self.transport = transport.get_transport(self.dir)
582
self._lock = lockdir.LockDir(self.transport, 'lock')
584
def _create_from_string(self, unicode_bytes, save):
585
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
587
# We need to handle the saving here (as opposed to IniBasedConfig)
590
self._write_config_file()
593
def lock_write(self, token=None):
594
"""Takes a write lock in the directory containing the config file.
596
If the directory doesn't exist it is created.
598
ensure_config_dir_exists(self.dir)
599
return self._lock.lock_write(token)
604
def break_lock(self):
605
self._lock.break_lock()
607
def _write_config_file(self):
608
if self._lock is None or not self._lock.is_held:
609
# NB: if the following exception is raised it probably means a
610
# missing @needs_write_lock decorator on one of the callers.
611
raise errors.ObjectNotLocked(self)
612
super(LockableConfig, self)._write_config_file()
615
class GlobalConfig(LockableConfig):
431
class GlobalConfig(IniBasedConfig):
616
432
"""The configuration that should be used for a specific location."""
619
super(GlobalConfig, self).__init__(file_name=config_filename())
622
def from_string(cls, str_or_unicode, save=False):
623
"""Create a config object from a string.
625
:param str_or_unicode: A string representing the file content. This
626
will be utf-8 encoded.
628
:param save: Whether the file should be saved upon creation.
631
conf._create_from_string(str_or_unicode, save)
634
434
def get_editor(self):
635
435
return self._get_user_option('editor')
438
super(GlobalConfig, self).__init__(config_filename)
638
440
def set_user_option(self, option, value):
639
441
"""Save option and its value in the configuration."""
640
self._set_option(option, value, 'DEFAULT')
642
def get_aliases(self):
643
"""Return the aliases section."""
644
if 'ALIASES' in self._get_parser():
645
return self._get_parser()['ALIASES']
650
def set_alias(self, alias_name, alias_command):
651
"""Save the alias in the configuration."""
652
self._set_option(alias_name, alias_command, 'ALIASES')
655
def unset_alias(self, alias_name):
656
"""Unset an existing alias."""
658
aliases = self._get_parser().get('ALIASES')
659
if not aliases or alias_name not in aliases:
660
raise errors.NoSuchAlias(alias_name)
661
del aliases[alias_name]
662
self._write_config_file()
664
def _set_option(self, option, value, section):
666
self._get_parser().setdefault(section, {})[option] = value
667
self._write_config_file()
670
class LocationConfig(LockableConfig):
442
# FIXME: RBC 20051029 This should refresh the parser and also take a
443
# file lock on bazaar.conf.
444
conf_dir = os.path.dirname(self._get_filename())
445
ensure_config_dir_exists(conf_dir)
446
if 'DEFAULT' not in self._get_parser():
447
self._get_parser()['DEFAULT'] = {}
448
self._get_parser()['DEFAULT'][option] = value
449
f = open(self._get_filename(), 'wb')
450
self._get_parser().write(f)
454
class LocationConfig(IniBasedConfig):
671
455
"""A configuration object that gives the policy for a location."""
673
457
def __init__(self, location):
674
super(LocationConfig, self).__init__(
675
file_name=locations_config_filename())
458
name_generator = locations_config_filename
459
if (not os.path.exists(name_generator()) and
460
os.path.exists(branches_config_filename())):
461
if sys.platform == 'win32':
462
trace.warning('Please rename %s to %s'
463
% (branches_config_filename(),
464
locations_config_filename()))
466
trace.warning('Please rename ~/.bazaar/branches.conf'
467
' to ~/.bazaar/locations.conf')
468
name_generator = branches_config_filename
469
super(LocationConfig, self).__init__(name_generator)
676
470
# local file locations are looked up by local path, rather than
677
471
# by file url. This is because the config file is a user
678
472
# file, and we would rather not expose the user to file urls.
788
567
if policy_key in self._get_parser()[section]:
789
568
del self._get_parser()[section][policy_key]
792
570
def set_user_option(self, option, value, store=STORE_LOCATION):
793
571
"""Save option and its value in the configuration."""
794
if store not in [STORE_LOCATION,
572
assert store in [STORE_LOCATION,
795
573
STORE_LOCATION_NORECURSE,
796
STORE_LOCATION_APPENDPATH]:
797
raise ValueError('bad storage policy %r for %r' %
574
STORE_LOCATION_APPENDPATH], 'bad storage policy'
575
# FIXME: RBC 20051029 This should refresh the parser and also take a
576
# file lock on locations.conf.
577
conf_dir = os.path.dirname(self._get_filename())
578
ensure_config_dir_exists(conf_dir)
800
579
location = self.location
801
580
if location.endswith('/'):
802
581
location = location[:-1]
803
parser = self._get_parser()
804
if not location in parser and not location + '/' in parser:
805
parser[location] = {}
806
elif location + '/' in parser:
582
if (not location in self._get_parser() and
583
not location + '/' in self._get_parser()):
584
self._get_parser()[location]={}
585
elif location + '/' in self._get_parser():
807
586
location = location + '/'
808
parser[location][option]=value
587
self._get_parser()[location][option]=value
809
588
# the allowed values of store match the config policies
810
589
self._set_option_policy(location, option, store)
811
self._write_config_file()
590
self._get_parser().write(file(self._get_filename(), 'wb'))
814
593
class BranchConfig(Config):
815
594
"""A configuration object giving the policy for a branch."""
817
def __init__(self, branch):
818
super(BranchConfig, self).__init__()
819
self._location_config = None
820
self._branch_data_config = None
821
self._global_config = None
823
self.option_sources = (self._get_location_config,
824
self._get_branch_data_config,
825
self._get_global_config)
827
596
def _get_branch_data_config(self):
828
597
if self._branch_data_config is None:
829
598
self._branch_data_config = TreeConfig(self.branch)
1011
794
return osutils.pathjoin(config_dir(), 'ignore')
1015
"""Return the directory name to store crash files.
1017
This doesn't implicitly create it.
1019
On Windows it's in the config directory; elsewhere it's /var/crash
1020
which may be monitored by apport. It can be overridden by
798
"""Calculate automatic user identification.
800
Returns (realname, email).
802
Only used when none is set in the environment or the id file.
804
This previously used the FQDN as the default domain, but that can
805
be very slow on machines where DNS is broken. So now we simply
1023
810
if sys.platform == 'win32':
1024
return osutils.pathjoin(config_dir(), 'Crash')
1026
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1028
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1031
def xdg_cache_dir():
1032
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1033
# Possibly this should be different on Windows?
1034
e = os.environ.get('XDG_CACHE_DIR', None)
1038
return os.path.expanduser('~/.cache')
811
name = win32utils.get_user_name_unicode()
813
raise errors.BzrError("Cannot autodetect user name.\n"
814
"Please, set your name with command like:\n"
815
'bzr whoami "Your Name <name@domain.com>"')
816
host = win32utils.get_host_name_unicode()
818
host = socket.gethostname()
819
return name, (name + '@' + host)
824
w = pwd.getpwuid(uid)
826
# we try utf-8 first, because on many variants (like Linux),
827
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
828
# false positives. (many users will have their user encoding set to
829
# latin-1, which cannot raise UnicodeError.)
831
gecos = w.pw_gecos.decode('utf-8')
835
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
836
encoding = bzrlib.user_encoding
838
raise errors.BzrCommandError('Unable to determine your name. '
839
'Use "bzr whoami" to set it.')
841
username = w.pw_name.decode(encoding)
843
raise errors.BzrCommandError('Unable to determine your name. '
844
'Use "bzr whoami" to set it.')
846
comma = gecos.find(',')
850
realname = gecos[:comma]
857
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
858
except UnicodeDecodeError:
859
raise errors.BzrError("Can't decode username as %s." % \
860
bzrlib.user_encoding)
862
return realname, (username + '@' + socket.gethostname())
1041
865
def parse_username(username):
1217
1051
if a_user is None:
1218
1052
# Can't find a user
1220
# Prepare a credentials dictionary with additional keys
1221
# for the credential providers
1222
1054
credentials = dict(name=auth_def_name,
1229
password=auth_def.get('password', None),
1055
user=a_user, password=auth_def['password'],
1230
1056
verify_certificates=a_verify_certificates)
1231
# Decode the password in the credentials (or get one)
1232
1057
self.decode_password(credentials,
1233
1058
auth_def.get('password_encoding', None))
1234
1059
if 'auth' in debug.debug_flags:
1235
1060
trace.mutter("Using authentication section: %r", auth_def_name)
1238
if credentials is None:
1239
# No credentials were found in authentication.conf, try the fallback
1240
# credentials stores.
1241
credentials = credential_store_registry.get_fallback_credentials(
1242
scheme, host, port, user, path, realm)
1244
1063
return credentials
1246
def set_credentials(self, name, host, user, scheme=None, password=None,
1247
port=None, path=None, verify_certificates=None,
1249
"""Set authentication credentials for a host.
1251
Any existing credentials with matching scheme, host, port and path
1252
will be deleted, regardless of name.
1254
:param name: An arbitrary name to describe this set of credentials.
1255
:param host: Name of the host that accepts these credentials.
1256
:param user: The username portion of these credentials.
1257
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1259
:param password: Password portion of these credentials.
1260
:param port: The IP port on the host that these credentials apply to.
1261
:param path: A filesystem path on the host that these credentials
1263
:param verify_certificates: On https, verify server certificates if
1265
:param realm: The http authentication realm (optional).
1267
values = {'host': host, 'user': user}
1268
if password is not None:
1269
values['password'] = password
1270
if scheme is not None:
1271
values['scheme'] = scheme
1272
if port is not None:
1273
values['port'] = '%d' % port
1274
if path is not None:
1275
values['path'] = path
1276
if verify_certificates is not None:
1277
values['verify_certificates'] = str(verify_certificates)
1278
if realm is not None:
1279
values['realm'] = realm
1280
config = self._get_config()
1282
for section, existing_values in config.items():
1283
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1284
if existing_values.get(key) != values.get(key):
1288
config.update({name: values})
1291
def get_user(self, scheme, host, port=None, realm=None, path=None,
1292
prompt=None, ask=False, default=None):
1065
def get_user(self, scheme, host, port=None,
1066
realm=None, path=None, prompt=None):
1293
1067
"""Get a user from authentication file.
1295
1069
:param scheme: protocol
1374
1124
return password
1376
1126
def decode_password(self, credentials, encoding):
1378
cs = credential_store_registry.get_credential_store(encoding)
1380
raise ValueError('%r is not a known password_encoding' % encoding)
1381
credentials['password'] = cs.decode_password(credentials)
1385
class CredentialStoreRegistry(registry.Registry):
1386
"""A class that registers credential stores.
1388
A credential store provides access to credentials via the password_encoding
1389
field in authentication.conf sections.
1391
Except for stores provided by bzr itself, most stores are expected to be
1392
provided by plugins that will therefore use
1393
register_lazy(password_encoding, module_name, member_name, help=help,
1394
fallback=fallback) to install themselves.
1396
A fallback credential store is one that is queried if no credentials can be
1397
found via authentication.conf.
1400
def get_credential_store(self, encoding=None):
1401
cs = self.get(encoding)
1406
def is_fallback(self, name):
1407
"""Check if the named credentials store should be used as fallback."""
1408
return self.get_info(name)
1410
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1411
path=None, realm=None):
1412
"""Request credentials from all fallback credentials stores.
1414
The first credentials store that can provide credentials wins.
1417
for name in self.keys():
1418
if not self.is_fallback(name):
1420
cs = self.get_credential_store(name)
1421
credentials = cs.get_credentials(scheme, host, port, user,
1423
if credentials is not None:
1424
# We found some credentials
1428
def register(self, key, obj, help=None, override_existing=False,
1430
"""Register a new object to a name.
1432
:param key: This is the key to use to request the object later.
1433
:param obj: The object to register.
1434
:param help: Help text for this entry. This may be a string or
1435
a callable. If it is a callable, it should take two
1436
parameters (registry, key): this registry and the key that
1437
the help was registered under.
1438
:param override_existing: Raise KeyErorr if False and something has
1439
already been registered for that key. If True, ignore if there
1440
is an existing key (always register the new value).
1441
:param fallback: Whether this credential store should be
1444
return super(CredentialStoreRegistry,
1445
self).register(key, obj, help, info=fallback,
1446
override_existing=override_existing)
1448
def register_lazy(self, key, module_name, member_name,
1449
help=None, override_existing=False,
1451
"""Register a new credential store to be loaded on request.
1453
:param module_name: The python path to the module. Such as 'os.path'.
1454
:param member_name: The member of the module to return. If empty or
1455
None, get() will return the module itself.
1456
:param help: Help text for this entry. This may be a string or
1458
:param override_existing: If True, replace the existing object
1459
with the new one. If False, if there is already something
1460
registered with the same key, raise a KeyError
1461
:param fallback: Whether this credential store should be
1464
return super(CredentialStoreRegistry, self).register_lazy(
1465
key, module_name, member_name, help,
1466
info=fallback, override_existing=override_existing)
1469
credential_store_registry = CredentialStoreRegistry()
1472
class CredentialStore(object):
1473
"""An abstract class to implement storage for credentials"""
1475
def decode_password(self, credentials):
1476
"""Returns a clear text password for the provided credentials."""
1477
raise NotImplementedError(self.decode_password)
1479
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1481
"""Return the matching credentials from this credential store.
1483
This method is only called on fallback credential stores.
1485
raise NotImplementedError(self.get_credentials)
1489
class PlainTextCredentialStore(CredentialStore):
1490
__doc__ = """Plain text credential store for the authentication.conf file"""
1492
def decode_password(self, credentials):
1493
"""See CredentialStore.decode_password."""
1494
return credentials['password']
1497
credential_store_registry.register('plain', PlainTextCredentialStore,
1498
help=PlainTextCredentialStore.__doc__)
1499
credential_store_registry.default_key = 'plain'
1502
class BzrDirConfig(object):
1504
def __init__(self, bzrdir):
1505
self._bzrdir = bzrdir
1506
self._config = bzrdir._get_config()
1508
def set_default_stack_on(self, value):
1509
"""Set the default stacking location.
1511
It may be set to a location, or None.
1513
This policy affects all branches contained by this bzrdir, except for
1514
those under repositories.
1516
if self._config is None:
1517
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
1519
self._config.set_option('', 'default_stack_on')
1521
self._config.set_option(value, 'default_stack_on')
1523
def get_default_stack_on(self):
1524
"""Return the default stacking location.
1526
This will either be a location, or None.
1528
This policy affects all branches contained by this bzrdir, except for
1529
those under repositories.
1531
if self._config is None:
1533
value = self._config.get_option('default_stack_on')
1539
class TransportConfig(object):
1540
"""A Config that reads/writes a config file on a Transport.
1542
It is a low-level object that considers config data to be name/value pairs
1543
that may be associated with a section. Assigning meaning to the these
1544
values is done at higher levels like TreeConfig.
1547
def __init__(self, transport, filename):
1548
self._transport = transport
1549
self._filename = filename
1551
def get_option(self, name, section=None, default=None):
1552
"""Return the value associated with a named option.
1554
:param name: The name of the value
1555
:param section: The section the option is in (if any)
1556
:param default: The value to return if the value is not set
1557
:return: The value or default value
1559
configobj = self._get_configobj()
1561
section_obj = configobj
1564
section_obj = configobj[section]
1567
return section_obj.get(name, default)
1569
def set_option(self, value, name, section=None):
1570
"""Set the value associated with a named option.
1572
:param value: The value to set
1573
:param name: The name of the value to set
1574
:param section: The section the option is in (if any)
1576
configobj = self._get_configobj()
1578
configobj[name] = value
1580
configobj.setdefault(section, {})[name] = value
1581
self._set_configobj(configobj)
1583
def _get_config_file(self):
1585
return StringIO(self._transport.get_bytes(self._filename))
1586
except errors.NoSuchFile:
1589
def _get_configobj(self):
1590
f = self._get_config_file()
1592
return ConfigObj(f, encoding='utf-8')
1596
def _set_configobj(self, configobj):
1597
out_file = StringIO()
1598
configobj.write(out_file)
1600
self._transport.put_file(self._filename, out_file)