152
135
return self[section][name]
156
138
class Config(object):
157
139
"""A configuration policy - what username, editor, gpg needs etc."""
160
super(Config, self).__init__()
163
"""Returns a unique ID for the config."""
164
raise NotImplementedError(self.config_id)
166
141
def get_editor(self):
167
142
"""Get the users pop up editor."""
168
143
raise NotImplementedError
170
def get_change_editor(self, old_tree, new_tree):
171
from bzrlib import diff
172
cmd = self._get_change_editor()
175
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
179
def get_mail_client(self):
180
"""Get a mail client to use"""
181
selected_client = self.get_user_option('mail_client')
182
_registry = mail_client.mail_client_registry
184
mail_client_class = _registry.get(selected_client)
186
raise errors.UnknownMailClient(selected_client)
187
return mail_client_class(self)
189
145
def _get_signature_checking(self):
190
146
"""Template method to override signature checking policy."""
192
148
def _get_signing_policy(self):
193
149
"""Template method to override signature creation policy."""
197
def interpolate(self, string, env=None):
198
"""Interpolate the string in the configuration context.
200
:param string: The string to interpolate
202
:param env: An option dict defining additional configuration options or
203
overriding existing ones.
205
:returns: The interpolated string.
207
return self._interpolate_string(string, env)
209
def _interpolate_list(self, slist, env=None, _ref_stack=None):
210
"""Interpolate a list of strings in the configuration context.
212
:param slist: A list of strings.
214
:param env: An option dict defining additional configuration options or
215
overriding existing ones.
217
:param _ref_stack: Private list containing the options being
218
interpolated to detect loops.
220
:returns: The flatten list of interpolated strings.
222
# interpolate each value separately flattening lists
225
value = self._interpolate_string(s, env, _ref_stack)
226
if isinstance(value, list):
232
def _interpolate_string(self, string, env=None, _ref_stack=None):
233
"""Interpolate the string in the configuration context.
235
:param string: The string to interpolate
237
:param env: An option dict defining additional configuration options or
238
overriding existing ones.
240
:param _ref_stack: Private list containing the options being
241
interpolated to detect loops.
243
:returns: The interpolated string.
246
# Not much to interpolate there
248
if _ref_stack is None:
249
# What references are currently resolved (to detect loops)
251
if self.option_ref_re is None:
252
# We want to match the most embedded reference first (i.e. for
253
# '{{foo}}' we will get '{foo}',
254
# for '{bar{baz}}' we will get '{baz}'
255
self.option_ref_re = re.compile('({[^{}]+})')
257
# We need to iterate until no more refs appear ({{foo}} will need two
258
# iterations for example).
261
raw_chunks = self.option_ref_re.split(result)
263
import pdb; pdb.set_trace()
264
if len(raw_chunks) == 1:
265
# Shorcut the trivial case: no refs
269
# Split will isolate refs so that every other chunk is a ref
271
for chunk in raw_chunks:
274
# Keep only non-empty strings
279
if name in _ref_stack:
280
raise errors.InterpolationLoop(string, _ref_stack)
281
_ref_stack.append(name)
282
value = self._interpolate_option(name, env, _ref_stack)
284
raise errors.InterpolationUnknownOption(name, string)
285
if isinstance(value, list):
293
# Once a list appears as the result of an interpolation, all
294
# callers will get a list result. This allows a consistent
295
# behavior even when some options in the interpolation chain
296
# may be seen defined as strings even if their interpolated
298
return self._interpolate_list(chunks, env, _ref_stack)
300
result = ''.join(chunks)
303
def _interpolate_option(self, name, env, _ref_stack):
304
if env is not None and name in env:
305
# Special case, values provided in env takes precedence over
309
# FIXME: This is a limited implementation, what we really need
310
# is a way to query the bzr config for the value of an option,
311
# respecting the scope rules -- vila 20101222
312
value = self.get_user_option(name, interpolate=False)
313
if isinstance(value, list):
314
value = self._interpolate_list(value, env, _ref_stack)
316
value = self._interpolate_string(value, env, _ref_stack)
319
151
def _get_user_option(self, option_name):
320
152
"""Template method to provide a user option."""
323
def get_user_option(self, option_name, interpolate=True):
155
def get_user_option(self, option_name):
324
156
"""Get a generic option - no special process, no default."""
325
value = self._get_user_option(option_name)
327
if isinstance(value, list):
328
value = self._interpolate_list(value)
329
elif isinstance(value, dict):
330
trace.warning('Cannot expand "%s":'
331
' Dicts do not support option expansion'
334
value = self._interpolate_string(value)
337
def get_user_option_as_bool(self, option_name):
338
"""Get a generic option as a boolean - no special process, no default.
340
:return None if the option doesn't exist or its value can't be
341
interpreted as a boolean. Returns True or False otherwise.
343
s = self._get_user_option(option_name)
345
# The option doesn't exist
347
val = ui.bool_from_string(s)
349
# The value can't be interpreted as a boolean
350
trace.warning('Value "%s" is not a boolean for "%s"',
354
def get_user_option_as_list(self, option_name):
355
"""Get a generic option as a list - no special process, no default.
357
:return None if the option doesn't exist. Returns the value as a list
360
l = self._get_user_option(option_name)
361
if isinstance(l, (str, unicode)):
362
# A single value, most probably the user forgot (or didn't care to
157
return self._get_user_option(option_name)
367
159
def gpg_signing_command(self):
368
160
"""What program should be used to sign signatures?"""
749
399
def _get_nickname(self):
750
400
return self.get_user_option('nickname')
752
def remove_user_option(self, option_name, section_name=None):
753
"""Remove a user option and save the configuration file.
755
:param option_name: The option to be removed.
757
:param section_name: The section the option is defined in, default to
761
parser = self._get_parser()
762
if section_name is None:
765
section = parser[section_name]
767
del section[option_name]
769
raise errors.NoSuchConfigOption(option_name)
770
self._write_config_file()
772
def _write_config_file(self):
773
if self.file_name is None:
774
raise AssertionError('We cannot save, self.file_name is None')
775
conf_dir = os.path.dirname(self.file_name)
776
ensure_config_dir_exists(conf_dir)
777
atomic_file = atomicfile.AtomicFile(self.file_name)
778
self._get_parser().write(atomic_file)
781
osutils.copy_ownership_from_path(self.file_name)
784
class LockableConfig(IniBasedConfig):
785
"""A configuration needing explicit locking for access.
787
If several processes try to write the config file, the accesses need to be
790
Daughter classes should decorate all methods that update a config with the
791
``@needs_write_lock`` decorator (they call, directly or indirectly, the
792
``_write_config_file()`` method. These methods (typically ``set_option()``
793
and variants must reload the config file from disk before calling
794
``_write_config_file()``), this can be achieved by calling the
795
``self.reload()`` method. Note that the lock scope should cover both the
796
reading and the writing of the config file which is why the decorator can't
797
be applied to ``_write_config_file()`` only.
799
This should be enough to implement the following logic:
800
- lock for exclusive write access,
801
- reload the config file from disk,
805
This logic guarantees that a writer can update a value without erasing an
806
update made by another writer.
811
def __init__(self, file_name):
812
super(LockableConfig, self).__init__(file_name=file_name)
813
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
814
# FIXME: It doesn't matter that we don't provide possible_transports
815
# below since this is currently used only for local config files ;
816
# local transports are not shared. But if/when we start using
817
# LockableConfig for other kind of transports, we will need to reuse
818
# whatever connection is already established -- vila 20100929
819
self.transport = transport.get_transport(self.dir)
820
self._lock = lockdir.LockDir(self.transport, 'lock')
822
def _create_from_string(self, unicode_bytes, save):
823
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
825
# We need to handle the saving here (as opposed to IniBasedConfig)
828
self._write_config_file()
831
def lock_write(self, token=None):
832
"""Takes a write lock in the directory containing the config file.
834
If the directory doesn't exist it is created.
836
ensure_config_dir_exists(self.dir)
837
return self._lock.lock_write(token)
842
def break_lock(self):
843
self._lock.break_lock()
846
def remove_user_option(self, option_name, section_name=None):
847
super(LockableConfig, self).remove_user_option(option_name,
850
def _write_config_file(self):
851
if self._lock is None or not self._lock.is_held:
852
# NB: if the following exception is raised it probably means a
853
# missing @needs_write_lock decorator on one of the callers.
854
raise errors.ObjectNotLocked(self)
855
super(LockableConfig, self)._write_config_file()
858
class GlobalConfig(LockableConfig):
403
class GlobalConfig(IniBasedConfig):
859
404
"""The configuration that should be used for a specific location."""
862
super(GlobalConfig, self).__init__(file_name=config_filename())
868
def from_string(cls, str_or_unicode, save=False):
869
"""Create a config object from a string.
871
:param str_or_unicode: A string representing the file content. This
872
will be utf-8 encoded.
874
:param save: Whether the file should be saved upon creation.
877
conf._create_from_string(str_or_unicode, save)
880
406
def get_editor(self):
881
407
return self._get_user_option('editor')
410
super(GlobalConfig, self).__init__(config_filename)
884
412
def set_user_option(self, option, value):
885
413
"""Save option and its value in the configuration."""
886
self._set_option(option, value, 'DEFAULT')
888
def get_aliases(self):
889
"""Return the aliases section."""
890
if 'ALIASES' in self._get_parser():
891
return self._get_parser()['ALIASES']
896
def set_alias(self, alias_name, alias_command):
897
"""Save the alias in the configuration."""
898
self._set_option(alias_name, alias_command, 'ALIASES')
901
def unset_alias(self, alias_name):
902
"""Unset an existing alias."""
904
aliases = self._get_parser().get('ALIASES')
905
if not aliases or alias_name not in aliases:
906
raise errors.NoSuchAlias(alias_name)
907
del aliases[alias_name]
908
self._write_config_file()
910
def _set_option(self, option, value, section):
912
self._get_parser().setdefault(section, {})[option] = value
913
self._write_config_file()
916
def _get_sections(self, name=None):
917
"""See IniBasedConfig._get_sections()."""
918
parser = self._get_parser()
919
# We don't give access to options defined outside of any section, we
920
# used the DEFAULT section by... default.
921
if name in (None, 'DEFAULT'):
922
# This could happen for an empty file where the DEFAULT section
923
# doesn't exist yet. So we force DEFAULT when yielding
925
if 'DEFAULT' not in parser:
926
parser['DEFAULT']= {}
927
yield (name, parser[name], self.config_id())
930
def remove_user_option(self, option_name, section_name=None):
931
if section_name is None:
932
# We need to force the default section.
933
section_name = 'DEFAULT'
934
# We need to avoid the LockableConfig implementation or we'll lock
936
super(LockableConfig, self).remove_user_option(option_name,
940
class LocationConfig(LockableConfig):
414
# FIXME: RBC 20051029 This should refresh the parser and also take a
415
# file lock on bazaar.conf.
416
conf_dir = os.path.dirname(self._get_filename())
417
ensure_config_dir_exists(conf_dir)
418
if 'DEFAULT' not in self._get_parser():
419
self._get_parser()['DEFAULT'] = {}
420
self._get_parser()['DEFAULT'][option] = value
421
f = open(self._get_filename(), 'wb')
422
self._get_parser().write(f)
426
class LocationConfig(IniBasedConfig):
941
427
"""A configuration object that gives the policy for a location."""
943
429
def __init__(self, location):
944
super(LocationConfig, self).__init__(
945
file_name=locations_config_filename())
430
name_generator = locations_config_filename
431
if (not os.path.exists(name_generator()) and
432
os.path.exists(branches_config_filename())):
433
if sys.platform == 'win32':
434
warning('Please rename %s to %s'
435
% (branches_config_filename(),
436
locations_config_filename()))
438
warning('Please rename ~/.bazaar/branches.conf'
439
' to ~/.bazaar/locations.conf')
440
name_generator = branches_config_filename
441
super(LocationConfig, self).__init__(name_generator)
946
442
# local file locations are looked up by local path, rather than
947
443
# by file url. This is because the config file is a user
948
444
# file, and we would rather not expose the user to file urls.
1334
729
return osutils.pathjoin(config_dir(), 'bazaar.conf')
732
def branches_config_filename():
733
"""Return per-user configuration ini file filename."""
734
return osutils.pathjoin(config_dir(), 'branches.conf')
1337
737
def locations_config_filename():
1338
738
"""Return per-user configuration ini file filename."""
1339
739
return osutils.pathjoin(config_dir(), 'locations.conf')
1342
def authentication_config_filename():
1343
"""Return per-user authentication ini file filename."""
1344
return osutils.pathjoin(config_dir(), 'authentication.conf')
1347
742
def user_ignore_config_filename():
1348
743
"""Return the user default ignore filename"""
1349
744
return osutils.pathjoin(config_dir(), 'ignore')
1353
"""Return the directory name to store crash files.
1355
This doesn't implicitly create it.
1357
On Windows it's in the config directory; elsewhere it's /var/crash
1358
which may be monitored by apport. It can be overridden by
748
"""Calculate automatic user identification.
750
Returns (realname, email).
752
Only used when none is set in the environment or the id file.
754
This previously used the FQDN as the default domain, but that can
755
be very slow on machines where DNS is broken. So now we simply
1361
760
if sys.platform == 'win32':
1362
return osutils.pathjoin(config_dir(), 'Crash')
1364
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1366
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1369
def xdg_cache_dir():
1370
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1371
# Possibly this should be different on Windows?
1372
e = os.environ.get('XDG_CACHE_DIR', None)
1376
return os.path.expanduser('~/.cache')
1379
def parse_username(username):
1380
"""Parse e-mail username and return a (name, address) tuple."""
1381
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1383
return (username, '')
1385
return (match.group(1), match.group(2))
761
name = win32utils.get_user_name_unicode()
763
raise errors.BzrError("Cannot autodetect user name.\n"
764
"Please, set your name with command like:\n"
765
'bzr whoami "Your Name <name@domain.com>"')
766
host = win32utils.get_host_name_unicode()
768
host = socket.gethostname()
769
return name, (name + '@' + host)
774
w = pwd.getpwuid(uid)
776
# we try utf-8 first, because on many variants (like Linux),
777
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
778
# false positives. (many users will have their user encoding set to
779
# latin-1, which cannot raise UnicodeError.)
781
gecos = w.pw_gecos.decode('utf-8')
785
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
786
encoding = bzrlib.user_encoding
788
raise errors.BzrCommandError('Unable to determine your name. '
789
'Use "bzr whoami" to set it.')
791
username = w.pw_name.decode(encoding)
793
raise errors.BzrCommandError('Unable to determine your name. '
794
'Use "bzr whoami" to set it.')
796
comma = gecos.find(',')
800
realname = gecos[:comma]
807
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
808
except UnicodeDecodeError:
809
raise errors.BzrError("Can't decode username as %s." % \
810
bzrlib.user_encoding)
812
return realname, (username + '@' + socket.gethostname())
1388
815
def extract_email_address(e):
1389
816
"""Return just the address part of an email string.
1391
That is just the user@domain part, nothing else.
818
That is just the user@domain part, nothing else.
1392
819
This part is required to contain only ascii characters.
1393
820
If it can't be extracted, raises an error.
1395
822
>>> extract_email_address('Jane Tester <jane@test.com>')
1398
name, email = parse_username(e)
825
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
1400
827
raise errors.NoEmailInUsername(e)
1404
831
class TreeConfig(IniBasedConfig):
1405
832
"""Branch configuration data associated with its contents, not location"""
1407
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
1409
833
def __init__(self, branch):
1410
self._config = branch._get_config()
1411
834
self.branch = branch
1413
836
def _get_parser(self, file=None):
1414
837
if file is not None:
1415
838
return IniBasedConfig._get_parser(file)
1416
return self._config._get_configobj()
839
return self._get_config()
841
def _get_config(self):
843
obj = ConfigObj(self.branch.control_files.get('branch.conf'),
845
except errors.NoSuchFile:
846
obj = ConfigObj(encoding='utf=8')
1418
849
def get_option(self, name, section=None, default=None):
1419
850
self.branch.lock_read()
1421
return self._config.get_option(name, section, default)
852
obj = self._get_config()
854
if section is not None:
1423
860
self.branch.unlock()
1425
863
def set_option(self, value, name, section=None):
1426
864
"""Set a per-branch configuration option"""
1427
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1428
# higher levels providing the right lock -- vila 20101004
1429
self.branch.lock_write()
1431
self._config.set_option(value, name, section)
1433
self.branch.unlock()
1435
def remove_option(self, option_name, section_name=None):
1436
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1437
# higher levels providing the right lock -- vila 20101004
1438
self.branch.lock_write()
1440
self._config.remove_option(option_name, section_name)
1442
self.branch.unlock()
1445
class AuthenticationConfig(object):
1446
"""The authentication configuration file based on a ini file.
1448
Implements the authentication.conf file described in
1449
doc/developers/authentication-ring.txt.
1452
def __init__(self, _file=None):
1453
self._config = None # The ConfigObj
1455
self._filename = authentication_config_filename()
1456
self._input = self._filename = authentication_config_filename()
1458
# Tests can provide a string as _file
1459
self._filename = None
1462
def _get_config(self):
1463
if self._config is not None:
1466
# FIXME: Should we validate something here ? Includes: empty
1467
# sections are useless, at least one of
1468
# user/password/password_encoding should be defined, etc.
1470
# Note: the encoding below declares that the file itself is utf-8
1471
# encoded, but the values in the ConfigObj are always Unicode.
1472
self._config = ConfigObj(self._input, encoding='utf-8')
1473
except configobj.ConfigObjError, e:
1474
raise errors.ParseConfigError(e.errors, e.config.filename)
1478
"""Save the config file, only tests should use it for now."""
1479
conf_dir = os.path.dirname(self._filename)
1480
ensure_config_dir_exists(conf_dir)
1481
f = file(self._filename, 'wb')
1483
self._get_config().write(f)
1487
def _set_option(self, section_name, option_name, value):
1488
"""Set an authentication configuration option"""
1489
conf = self._get_config()
1490
section = conf.get(section_name)
1493
section = conf[section]
1494
section[option_name] = value
1497
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1499
"""Returns the matching credentials from authentication.conf file.
1501
:param scheme: protocol
1503
:param host: the server address
1505
:param port: the associated port (optional)
1507
:param user: login (optional)
1509
:param path: the absolute path on the server (optional)
1511
:param realm: the http authentication realm (optional)
1513
:return: A dict containing the matching credentials or None.
1515
- name: the section name of the credentials in the
1516
authentication.conf file,
1517
- user: can't be different from the provided user if any,
1518
- scheme: the server protocol,
1519
- host: the server address,
1520
- port: the server port (can be None),
1521
- path: the absolute server path (can be None),
1522
- realm: the http specific authentication realm (can be None),
1523
- password: the decoded password, could be None if the credential
1524
defines only the user
1525
- verify_certificates: https specific, True if the server
1526
certificate should be verified, False otherwise.
1529
for auth_def_name, auth_def in self._get_config().items():
1530
if type(auth_def) is not configobj.Section:
1531
raise ValueError("%s defined outside a section" % auth_def_name)
1533
a_scheme, a_host, a_user, a_path = map(
1534
auth_def.get, ['scheme', 'host', 'user', 'path'])
1537
a_port = auth_def.as_int('port')
1541
raise ValueError("'port' not numeric in %s" % auth_def_name)
1543
a_verify_certificates = auth_def.as_bool('verify_certificates')
1545
a_verify_certificates = True
1548
"'verify_certificates' not boolean in %s" % auth_def_name)
1551
if a_scheme is not None and scheme != a_scheme:
1553
if a_host is not None:
1554
if not (host == a_host
1555
or (a_host.startswith('.') and host.endswith(a_host))):
1557
if a_port is not None and port != a_port:
1559
if (a_path is not None and path is not None
1560
and not path.startswith(a_path)):
1562
if (a_user is not None and user is not None
1563
and a_user != user):
1564
# Never contradict the caller about the user to be used
1569
# Prepare a credentials dictionary with additional keys
1570
# for the credential providers
1571
credentials = dict(name=auth_def_name,
1578
password=auth_def.get('password', None),
1579
verify_certificates=a_verify_certificates)
1580
# Decode the password in the credentials (or get one)
1581
self.decode_password(credentials,
1582
auth_def.get('password_encoding', None))
1583
if 'auth' in debug.debug_flags:
1584
trace.mutter("Using authentication section: %r", auth_def_name)
1587
if credentials is None:
1588
# No credentials were found in authentication.conf, try the fallback
1589
# credentials stores.
1590
credentials = credential_store_registry.get_fallback_credentials(
1591
scheme, host, port, user, path, realm)
1595
def set_credentials(self, name, host, user, scheme=None, password=None,
1596
port=None, path=None, verify_certificates=None,
1598
"""Set authentication credentials for a host.
1600
Any existing credentials with matching scheme, host, port and path
1601
will be deleted, regardless of name.
1603
:param name: An arbitrary name to describe this set of credentials.
1604
:param host: Name of the host that accepts these credentials.
1605
:param user: The username portion of these credentials.
1606
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1608
:param password: Password portion of these credentials.
1609
:param port: The IP port on the host that these credentials apply to.
1610
:param path: A filesystem path on the host that these credentials
1612
:param verify_certificates: On https, verify server certificates if
1614
:param realm: The http authentication realm (optional).
1616
values = {'host': host, 'user': user}
1617
if password is not None:
1618
values['password'] = password
1619
if scheme is not None:
1620
values['scheme'] = scheme
1621
if port is not None:
1622
values['port'] = '%d' % port
1623
if path is not None:
1624
values['path'] = path
1625
if verify_certificates is not None:
1626
values['verify_certificates'] = str(verify_certificates)
1627
if realm is not None:
1628
values['realm'] = realm
1629
config = self._get_config()
1631
for section, existing_values in config.items():
1632
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1633
if existing_values.get(key) != values.get(key):
1637
config.update({name: values})
1640
def get_user(self, scheme, host, port=None, realm=None, path=None,
1641
prompt=None, ask=False, default=None):
1642
"""Get a user from authentication file.
1644
:param scheme: protocol
1646
:param host: the server address
1648
:param port: the associated port (optional)
1650
:param realm: the realm sent by the server (optional)
1652
:param path: the absolute path on the server (optional)
1654
:param ask: Ask the user if there is no explicitly configured username
1657
:param default: The username returned if none is defined (optional).
1659
:return: The found user.
1661
credentials = self.get_credentials(scheme, host, port, user=None,
1662
path=path, realm=realm)
1663
if credentials is not None:
1664
user = credentials['user']
1670
# Create a default prompt suitable for most cases
1671
prompt = scheme.upper() + ' %(host)s username'
1672
# Special handling for optional fields in the prompt
1673
if port is not None:
1674
prompt_host = '%s:%d' % (host, port)
1677
user = ui.ui_factory.get_username(prompt, host=prompt_host)
1682
def get_password(self, scheme, host, user, port=None,
1683
realm=None, path=None, prompt=None):
1684
"""Get a password from authentication file or prompt the user for one.
1686
:param scheme: protocol
1688
:param host: the server address
1690
:param port: the associated port (optional)
1694
:param realm: the realm sent by the server (optional)
1696
:param path: the absolute path on the server (optional)
1698
:return: The found password or the one entered by the user.
1700
credentials = self.get_credentials(scheme, host, port, user, path,
1702
if credentials is not None:
1703
password = credentials['password']
1704
if password is not None and scheme is 'ssh':
1705
trace.warning('password ignored in section [%s],'
1706
' use an ssh agent instead'
1707
% credentials['name'])
1711
# Prompt user only if we could't find a password
1712
if password is None:
1714
# Create a default prompt suitable for most cases
1715
prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1716
# Special handling for optional fields in the prompt
1717
if port is not None:
1718
prompt_host = '%s:%d' % (host, port)
1721
password = ui.ui_factory.get_password(prompt,
1722
host=prompt_host, user=user)
1725
def decode_password(self, credentials, encoding):
1727
cs = credential_store_registry.get_credential_store(encoding)
1729
raise ValueError('%r is not a known password_encoding' % encoding)
1730
credentials['password'] = cs.decode_password(credentials)
1734
class CredentialStoreRegistry(registry.Registry):
1735
"""A class that registers credential stores.
1737
A credential store provides access to credentials via the password_encoding
1738
field in authentication.conf sections.
1740
Except for stores provided by bzr itself, most stores are expected to be
1741
provided by plugins that will therefore use
1742
register_lazy(password_encoding, module_name, member_name, help=help,
1743
fallback=fallback) to install themselves.
1745
A fallback credential store is one that is queried if no credentials can be
1746
found via authentication.conf.
1749
def get_credential_store(self, encoding=None):
1750
cs = self.get(encoding)
1755
def is_fallback(self, name):
1756
"""Check if the named credentials store should be used as fallback."""
1757
return self.get_info(name)
1759
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1760
path=None, realm=None):
1761
"""Request credentials from all fallback credentials stores.
1763
The first credentials store that can provide credentials wins.
1766
for name in self.keys():
1767
if not self.is_fallback(name):
1769
cs = self.get_credential_store(name)
1770
credentials = cs.get_credentials(scheme, host, port, user,
1772
if credentials is not None:
1773
# We found some credentials
1777
def register(self, key, obj, help=None, override_existing=False,
1779
"""Register a new object to a name.
1781
:param key: This is the key to use to request the object later.
1782
:param obj: The object to register.
1783
:param help: Help text for this entry. This may be a string or
1784
a callable. If it is a callable, it should take two
1785
parameters (registry, key): this registry and the key that
1786
the help was registered under.
1787
:param override_existing: Raise KeyErorr if False and something has
1788
already been registered for that key. If True, ignore if there
1789
is an existing key (always register the new value).
1790
:param fallback: Whether this credential store should be
1793
return super(CredentialStoreRegistry,
1794
self).register(key, obj, help, info=fallback,
1795
override_existing=override_existing)
1797
def register_lazy(self, key, module_name, member_name,
1798
help=None, override_existing=False,
1800
"""Register a new credential store to be loaded on request.
1802
:param module_name: The python path to the module. Such as 'os.path'.
1803
:param member_name: The member of the module to return. If empty or
1804
None, get() will return the module itself.
1805
:param help: Help text for this entry. This may be a string or
1807
:param override_existing: If True, replace the existing object
1808
with the new one. If False, if there is already something
1809
registered with the same key, raise a KeyError
1810
:param fallback: Whether this credential store should be
1813
return super(CredentialStoreRegistry, self).register_lazy(
1814
key, module_name, member_name, help,
1815
info=fallback, override_existing=override_existing)
1818
credential_store_registry = CredentialStoreRegistry()
1821
class CredentialStore(object):
1822
"""An abstract class to implement storage for credentials"""
1824
def decode_password(self, credentials):
1825
"""Returns a clear text password for the provided credentials."""
1826
raise NotImplementedError(self.decode_password)
1828
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1830
"""Return the matching credentials from this credential store.
1832
This method is only called on fallback credential stores.
1834
raise NotImplementedError(self.get_credentials)
1838
class PlainTextCredentialStore(CredentialStore):
1839
__doc__ = """Plain text credential store for the authentication.conf file"""
1841
def decode_password(self, credentials):
1842
"""See CredentialStore.decode_password."""
1843
return credentials['password']
1846
credential_store_registry.register('plain', PlainTextCredentialStore,
1847
help=PlainTextCredentialStore.__doc__)
1848
credential_store_registry.default_key = 'plain'
1851
class BzrDirConfig(object):
1853
def __init__(self, bzrdir):
1854
self._bzrdir = bzrdir
1855
self._config = bzrdir._get_config()
1857
def set_default_stack_on(self, value):
1858
"""Set the default stacking location.
1860
It may be set to a location, or None.
1862
This policy affects all branches contained by this bzrdir, except for
1863
those under repositories.
1865
if self._config is None:
1866
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
1868
self._config.set_option('', 'default_stack_on')
1870
self._config.set_option(value, 'default_stack_on')
1872
def get_default_stack_on(self):
1873
"""Return the default stacking location.
1875
This will either be a location, or None.
1877
This policy affects all branches contained by this bzrdir, except for
1878
those under repositories.
1880
if self._config is None:
1882
value = self._config.get_option('default_stack_on')
1888
class TransportConfig(object):
1889
"""A Config that reads/writes a config file on a Transport.
1891
It is a low-level object that considers config data to be name/value pairs
1892
that may be associated with a section. Assigning meaning to these values
1893
is done at higher levels like TreeConfig.
1896
def __init__(self, transport, filename):
1897
self._transport = transport
1898
self._filename = filename
1900
def get_option(self, name, section=None, default=None):
1901
"""Return the value associated with a named option.
1903
:param name: The name of the value
1904
:param section: The section the option is in (if any)
1905
:param default: The value to return if the value is not set
1906
:return: The value or default value
1908
configobj = self._get_configobj()
1910
section_obj = configobj
1913
section_obj = configobj[section]
1916
return section_obj.get(name, default)
1918
def set_option(self, value, name, section=None):
1919
"""Set the value associated with a named option.
1921
:param value: The value to set
1922
:param name: The name of the value to set
1923
:param section: The section the option is in (if any)
1925
configobj = self._get_configobj()
1927
configobj[name] = value
1929
configobj.setdefault(section, {})[name] = value
1930
self._set_configobj(configobj)
1932
def remove_option(self, option_name, section_name=None):
1933
configobj = self._get_configobj()
1934
if section_name is None:
1935
del configobj[option_name]
1937
del configobj[section_name][option_name]
1938
self._set_configobj(configobj)
1940
def _get_config_file(self):
1942
return StringIO(self._transport.get_bytes(self._filename))
1943
except errors.NoSuchFile:
1946
def _get_configobj(self):
1947
f = self._get_config_file()
1949
return ConfigObj(f, encoding='utf-8')
1953
def _set_configobj(self, configobj):
1954
out_file = StringIO()
1955
configobj.write(out_file)
1957
self._transport.put_file(self._filename, out_file)
1960
class cmd_config(commands.Command):
1961
__doc__ = """Display, set or remove a configuration option.
1963
Display the active value for a given option.
1965
If --all is specified, NAME is interpreted as a regular expression and all
1966
matching options are displayed mentioning their scope. The active value
1967
that bzr will take into account is the first one displayed for each option.
1969
If no NAME is given, --all .* is implied.
1971
Setting a value is achieved by using name=value without spaces. The value
1972
is set in the most relevant scope and can be checked by displaying the
1976
takes_args = ['name?']
1980
# FIXME: This should be a registry option so that plugins can register
1981
# their own config files (or not) -- vila 20101002
1982
commands.Option('scope', help='Reduce the scope to the specified'
1983
' configuration file',
1985
commands.Option('all',
1986
help='Display all the defined values for the matching options.',
1988
commands.Option('remove', help='Remove the option from'
1989
' the configuration file'),
1992
@commands.display_command
1993
def run(self, name=None, all=False, directory=None, scope=None,
1995
if directory is None:
1997
directory = urlutils.normalize_url(directory)
1999
raise errors.BzrError(
2000
'--all and --remove are mutually exclusive.')
2002
# Delete the option in the given scope
2003
self._remove_config_option(name, directory, scope)
2005
# Defaults to all options
2006
self._show_matching_options('.*', directory, scope)
2009
name, value = name.split('=', 1)
2011
# Display the option(s) value(s)
2013
self._show_matching_options(name, directory, scope)
2015
self._show_value(name, directory, scope)
2018
raise errors.BzrError(
2019
'Only one option can be set.')
2020
# Set the option value
2021
self._set_config_option(name, value, directory, scope)
2023
def _get_configs(self, directory, scope=None):
2024
"""Iterate the configurations specified by ``directory`` and ``scope``.
2026
:param directory: Where the configurations are derived from.
2028
:param scope: A specific config to start from.
2030
if scope is not None:
2031
if scope == 'bazaar':
2032
yield GlobalConfig()
2033
elif scope == 'locations':
2034
yield LocationConfig(directory)
2035
elif scope == 'branch':
2036
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2038
yield br.get_config()
2041
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2043
yield br.get_config()
2044
except errors.NotBranchError:
2045
yield LocationConfig(directory)
2046
yield GlobalConfig()
2048
def _show_value(self, name, directory, scope):
2050
for c in self._get_configs(directory, scope):
2053
for (oname, value, section, conf_id, parser) in c._get_options():
2055
# Display only the first value and exit
2057
# FIXME: We need to use get_user_option to take policies
2058
# into account and we need to make sure the option exists
2059
# too (hence the two for loops), this needs a better API
2061
value = c.get_user_option(name)
2062
# Quote the value appropriately
2063
value = parser._quote(value)
2064
self.outf.write('%s\n' % (value,))
2068
raise errors.NoSuchConfigOption(name)
2070
def _show_matching_options(self, name, directory, scope):
2071
name = re.compile(name)
2072
# We want any error in the regexp to be raised *now* so we need to
2073
# avoid the delay introduced by the lazy regexp.
2074
name._compile_and_collapse()
2077
for c in self._get_configs(directory, scope):
2078
for (oname, value, section, conf_id, parser) in c._get_options():
2079
if name.search(oname):
2080
if cur_conf_id != conf_id:
2081
# Explain where the options are defined
2082
self.outf.write('%s:\n' % (conf_id,))
2083
cur_conf_id = conf_id
2085
if (section not in (None, 'DEFAULT')
2086
and cur_section != section):
2087
# Display the section if it's not the default (or only)
2089
self.outf.write(' [%s]\n' % (section,))
2090
cur_section = section
2091
self.outf.write(' %s = %s\n' % (oname, value))
2093
def _set_config_option(self, name, value, directory, scope):
2094
for conf in self._get_configs(directory, scope):
2095
conf.set_user_option(name, value)
2098
raise errors.NoSuchConfig(scope)
2100
def _remove_config_option(self, name, directory, scope):
2102
raise errors.BzrCommandError(
2103
'--remove expects an option to remove.')
2105
for conf in self._get_configs(directory, scope):
2106
for (section_name, section, conf_id) in conf._get_sections():
2107
if scope is not None and conf_id != scope:
2108
# Not the right configuration file
2111
if conf_id != conf.config_id():
2112
conf = self._get_configs(directory, conf_id).next()
2113
# We use the first section in the first config where the
2114
# option is defined to remove it
2115
conf.remove_user_option(name, section_name)
2120
raise errors.NoSuchConfig(scope)
2122
raise errors.NoSuchConfigOption(name)
865
self.branch.lock_write()
867
cfg_obj = self._get_config()
872
obj = cfg_obj[section]
874
cfg_obj[section] = {}
875
obj = cfg_obj[section]
877
out_file = StringIO()
878
cfg_obj.write(out_file)
880
self.branch.control_files.put('branch.conf', out_file)