1
# Copyright (C) 2005-2011 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
"""Configuration that affects the behaviour of Bazaar.
21
Currently this configuration resides in ~/.bazaar/bazaar.conf
22
and ~/.bazaar/locations.conf, which is written to by bzr.
24
In bazaar.conf the following options may be set:
26
editor=name-of-program
27
email=Your Name <your@email.address>
28
check_signatures=require|ignore|check-available(default)
29
create_signatures=always|never|when-required(default)
30
gpg_signing_command=name-of-program
31
log_format=name-of-format
33
in locations.conf, you specify the url of a branch and options for it.
34
Wildcards may be used - * and ? as normal in shell completion. Options
35
set in both bazaar.conf and locations.conf are overridden by the locations.conf
37
[/home/robertc/source]
38
recurse=False|True(default)
40
check_signatures= as above
41
create_signatures= as above.
43
explanation of options
44
----------------------
45
editor - this option sets the pop up editor to use during commits.
46
email - this option sets the user id bzr will use when committing.
47
check_signatures - this option controls whether bzr will require good gpg
48
signatures, ignore them, or check them if they are
50
create_signatures - this option controls whether bzr will always create
51
gpg signatures, never create them, or create them if the
52
branch is configured to require them.
53
log_format - this option sets the default log format. Possible values are
54
long, short, line, or a plugin can register new formats.
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
59
lastlog=log --line -r-10..-1
60
ll=log --line -r-10..-1
69
from bzrlib import commands
70
from bzrlib.decorators import needs_write_lock
71
from bzrlib.lazy_import import lazy_import
72
lazy_import(globals(), """
75
from cStringIO import StringIO
95
from bzrlib.util.configobj import configobj
111
POLICY_APPENDPATH = 2
115
POLICY_NORECURSE: 'norecurse',
116
POLICY_APPENDPATH: 'appendpath',
121
'norecurse': POLICY_NORECURSE,
122
'appendpath': POLICY_APPENDPATH,
126
STORE_LOCATION = POLICY_NONE
127
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
128
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
133
class ConfigObj(configobj.ConfigObj):
135
def __init__(self, infile=None, **kwargs):
136
# We define our own interpolation mechanism calling it option expansion
137
super(ConfigObj, self).__init__(infile=infile,
142
def get_bool(self, section, key):
143
return self[section].as_bool(key)
145
def get_value(self, section, name):
146
# Try [] for the old DEFAULT section.
147
if section == "DEFAULT":
152
return self[section][name]
155
# FIXME: Until we can guarantee that each config file is loaded once and and
156
# only once for a given bzrlib session, we don't want to re-read the file every
157
# time we query for an option so we cache the value (bad ! watch out for tests
158
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
159
# yell at mgz^W vila and the RM if this is still present at that time
161
_expand_default_value = None
162
def _get_expand_default_value():
163
global _expand_default_value
164
if _expand_default_value is not None:
165
return _expand_default_value
166
conf = GlobalConfig()
167
# Note that we must not use None for the expand value below or we'll run
168
# into infinite recursion. Using False really would be quite silly ;)
169
expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
171
# This is an opt-in feature, you *really* need to clearly say you want
174
_expand_default_value = expand
178
class Config(object):
179
"""A configuration policy - what username, editor, gpg needs etc."""
182
super(Config, self).__init__()
185
"""Returns a unique ID for the config."""
186
raise NotImplementedError(self.config_id)
188
def get_editor(self):
189
"""Get the users pop up editor."""
190
raise NotImplementedError
192
def get_change_editor(self, old_tree, new_tree):
193
from bzrlib import diff
194
cmd = self._get_change_editor()
197
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
201
def get_mail_client(self):
202
"""Get a mail client to use"""
203
selected_client = self.get_user_option('mail_client')
204
_registry = mail_client.mail_client_registry
206
mail_client_class = _registry.get(selected_client)
208
raise errors.UnknownMailClient(selected_client)
209
return mail_client_class(self)
211
def _get_signature_checking(self):
212
"""Template method to override signature checking policy."""
214
def _get_signing_policy(self):
215
"""Template method to override signature creation policy."""
219
def expand_options(self, string, env=None):
220
"""Expand option references in the string in the configuration context.
222
:param string: The string containing option to expand.
224
:param env: An option dict defining additional configuration options or
225
overriding existing ones.
227
:returns: The expanded string.
229
return self._expand_options_in_string(string, env)
231
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
232
"""Expand options in a list of strings in the configuration context.
234
:param slist: A list of strings.
236
:param env: An option dict defining additional configuration options or
237
overriding existing ones.
239
:param _ref_stack: Private list containing the options being
240
expanded to detect loops.
242
:returns: The flatten list of expanded strings.
244
# expand options in each value separately flattening lists
247
value = self._expand_options_in_string(s, env, _ref_stack)
248
if isinstance(value, list):
254
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
255
"""Expand options in the string in the configuration context.
257
:param string: The string to be expanded.
259
:param env: An option dict defining additional configuration options or
260
overriding existing ones.
262
:param _ref_stack: Private list containing the options being
263
expanded to detect loops.
265
:returns: The expanded string.
268
# Not much to expand there
270
if _ref_stack is None:
271
# What references are currently resolved (to detect loops)
273
if self.option_ref_re is None:
274
# We want to match the most embedded reference first (i.e. for
275
# '{{foo}}' we will get '{foo}',
276
# for '{bar{baz}}' we will get '{baz}'
277
self.option_ref_re = re.compile('({[^{}]+})')
279
# We need to iterate until no more refs appear ({{foo}} will need two
280
# iterations for example).
282
raw_chunks = self.option_ref_re.split(result)
283
if len(raw_chunks) == 1:
284
# Shorcut the trivial case: no refs
288
# Split will isolate refs so that every other chunk is a ref
290
for chunk in raw_chunks:
293
# Keep only non-empty strings (or we get bogus empty
294
# slots when a list value is involved).
299
if name in _ref_stack:
300
raise errors.OptionExpansionLoop(string, _ref_stack)
301
_ref_stack.append(name)
302
value = self._expand_option(name, env, _ref_stack)
304
raise errors.ExpandingUnknownOption(name, string)
305
if isinstance(value, list):
313
# Once a list appears as the result of an expansion, all
314
# callers will get a list result. This allows a consistent
315
# behavior even when some options in the expansion chain
316
# defined as strings (no comma in their value) but their
317
# expanded value is a list.
318
return self._expand_options_in_list(chunks, env, _ref_stack)
320
result = ''.join(chunks)
323
def _expand_option(self, name, env, _ref_stack):
324
if env is not None and name in env:
325
# Special case, values provided in env takes precedence over
329
# FIXME: This is a limited implementation, what we really need is a
330
# way to query the bzr config for the value of an option,
331
# respecting the scope rules (That is, once we implement fallback
332
# configs, getting the option value should restart from the top
333
# config, not the current one) -- vila 20101222
334
value = self.get_user_option(name, expand=False)
335
if isinstance(value, list):
336
value = self._expand_options_in_list(value, env, _ref_stack)
338
value = self._expand_options_in_string(value, env, _ref_stack)
341
def _get_user_option(self, option_name):
342
"""Template method to provide a user option."""
345
def get_user_option(self, option_name, expand=None):
346
"""Get a generic option - no special process, no default.
348
:param option_name: The queried option.
350
:param expand: Whether options references should be expanded.
352
:returns: The value of the option.
355
expand = _get_expand_default_value()
356
value = self._get_user_option(option_name)
358
if isinstance(value, list):
359
value = self._expand_options_in_list(value)
360
elif isinstance(value, dict):
361
trace.warning('Cannot expand "%s":'
362
' Dicts do not support option expansion'
365
value = self._expand_options_in_string(value)
368
def get_user_option_as_bool(self, option_name, expand=None):
369
"""Get a generic option as a boolean - no special process, no default.
371
:return None if the option doesn't exist or its value can't be
372
interpreted as a boolean. Returns True or False otherwise.
374
s = self.get_user_option(option_name, expand=expand)
376
# The option doesn't exist
378
val = ui.bool_from_string(s)
380
# The value can't be interpreted as a boolean
381
trace.warning('Value "%s" is not a boolean for "%s"',
385
def get_user_option_as_list(self, option_name, expand=None):
386
"""Get a generic option as a list - no special process, no default.
388
:return None if the option doesn't exist. Returns the value as a list
391
l = self.get_user_option(option_name, expand=expand)
392
if isinstance(l, (str, unicode)):
393
# A single value, most probably the user forgot (or didn't care to
398
def gpg_signing_command(self):
399
"""What program should be used to sign signatures?"""
400
result = self._gpg_signing_command()
405
def _gpg_signing_command(self):
406
"""See gpg_signing_command()."""
409
def log_format(self):
410
"""What log format should be used"""
411
result = self._log_format()
416
def _log_format(self):
417
"""See log_format()."""
420
def post_commit(self):
421
"""An ordered list of python functions to call.
423
Each function takes branch, rev_id as parameters.
425
return self._post_commit()
427
def _post_commit(self):
428
"""See Config.post_commit."""
431
def user_email(self):
432
"""Return just the email component of a username."""
433
return extract_email_address(self.username())
436
"""Return email-style username.
438
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
440
$BZR_EMAIL can be set to override this, then
441
the concrete policy type is checked, and finally
443
If no username can be found, errors.NoWhoami exception is raised.
445
v = os.environ.get('BZR_EMAIL')
447
return v.decode(osutils.get_user_encoding())
448
v = self._get_user_id()
451
v = os.environ.get('EMAIL')
453
return v.decode(osutils.get_user_encoding())
454
name, email = _auto_user_id()
456
return '%s <%s>' % (name, email)
459
raise errors.NoWhoami()
461
def ensure_username(self):
462
"""Raise errors.NoWhoami if username is not set.
464
This method relies on the username() function raising the error.
468
def signature_checking(self):
469
"""What is the current policy for signature checking?."""
470
policy = self._get_signature_checking()
471
if policy is not None:
473
return CHECK_IF_POSSIBLE
475
def signing_policy(self):
476
"""What is the current policy for signature checking?."""
477
policy = self._get_signing_policy()
478
if policy is not None:
480
return SIGN_WHEN_REQUIRED
482
def signature_needed(self):
483
"""Is a signature needed when committing ?."""
484
policy = self._get_signing_policy()
486
policy = self._get_signature_checking()
487
if policy is not None:
488
trace.warning("Please use create_signatures,"
489
" not check_signatures to set signing policy.")
490
if policy == CHECK_ALWAYS:
492
elif policy == SIGN_ALWAYS:
496
def get_alias(self, value):
497
return self._get_alias(value)
499
def _get_alias(self, value):
502
def get_nickname(self):
503
return self._get_nickname()
505
def _get_nickname(self):
508
def get_bzr_remote_path(self):
510
return os.environ['BZR_REMOTE_PATH']
512
path = self.get_user_option("bzr_remote_path")
517
def suppress_warning(self, warning):
518
"""Should the warning be suppressed or emitted.
520
:param warning: The name of the warning being tested.
522
:returns: True if the warning should be suppressed, False otherwise.
524
warnings = self.get_user_option_as_list('suppress_warnings')
525
if warnings is None or warning not in warnings:
530
def get_merge_tools(self):
532
for (oname, value, section, conf_id, parser) in self._get_options():
533
if oname.startswith('bzr.mergetool.'):
534
tool_name = oname[len('bzr.mergetool.'):]
535
tools[tool_name] = value
536
trace.mutter('loaded merge tools: %r' % tools)
539
def find_merge_tool(self, name):
540
# We fake a defaults mechanism here by checking if the given name can
541
# be found in the known_merge_tools if it's not found in the config.
542
# This should be done through the proposed config defaults mechanism
543
# when it becomes available in the future.
544
command_line = (self.get_user_option('bzr.mergetool.%s' % name,
546
or mergetools.known_merge_tools.get(name, None))
550
class IniBasedConfig(Config):
551
"""A configuration policy that draws from ini files."""
553
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
555
"""Base class for configuration files using an ini-like syntax.
557
:param file_name: The configuration file path.
559
super(IniBasedConfig, self).__init__()
560
self.file_name = file_name
561
if symbol_versioning.deprecated_passed(get_filename):
562
symbol_versioning.warn(
563
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
564
' Use file_name instead.',
567
if get_filename is not None:
568
self.file_name = get_filename()
570
self.file_name = file_name
575
def from_string(cls, str_or_unicode, file_name=None, save=False):
576
"""Create a config object from a string.
578
:param str_or_unicode: A string representing the file content. This will
581
:param file_name: The configuration file path.
583
:param _save: Whether the file should be saved upon creation.
585
conf = cls(file_name=file_name)
586
conf._create_from_string(str_or_unicode, save)
589
def _create_from_string(self, str_or_unicode, save):
590
self._content = StringIO(str_or_unicode.encode('utf-8'))
591
# Some tests use in-memory configs, some other always need the config
592
# file to exist on disk.
594
self._write_config_file()
596
def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
597
if self._parser is not None:
599
if symbol_versioning.deprecated_passed(file):
600
symbol_versioning.warn(
601
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
602
' Use IniBasedConfig(_content=xxx) instead.',
605
if self._content is not None:
606
co_input = self._content
607
elif self.file_name is None:
608
raise AssertionError('We have no content to create the config')
610
co_input = self.file_name
612
self._parser = ConfigObj(co_input, encoding='utf-8')
613
except configobj.ConfigObjError, e:
614
raise errors.ParseConfigError(e.errors, e.config.filename)
615
# Make sure self.reload() will use the right file name
616
self._parser.filename = self.file_name
620
"""Reload the config file from disk."""
621
if self.file_name is None:
622
raise AssertionError('We need a file name to reload the config')
623
if self._parser is not None:
624
self._parser.reload()
626
def _get_matching_sections(self):
627
"""Return an ordered list of (section_name, extra_path) pairs.
629
If the section contains inherited configuration, extra_path is
630
a string containing the additional path components.
632
section = self._get_section()
633
if section is not None:
634
return [(section, '')]
638
def _get_section(self):
639
"""Override this to define the section used by the config."""
642
def _get_sections(self, name=None):
643
"""Returns an iterator of the sections specified by ``name``.
645
:param name: The section name. If None is supplied, the default
646
configurations are yielded.
648
:return: A tuple (name, section, config_id) for all sections that will
649
be walked by user_get_option() in the 'right' order. The first one
650
is where set_user_option() will update the value.
652
parser = self._get_parser()
654
yield (name, parser[name], self.config_id())
656
# No section name has been given so we fallback to the configobj
657
# itself which holds the variables defined outside of any section.
658
yield (None, parser, self.config_id())
660
def _get_options(self, sections=None):
661
"""Return an ordered list of (name, value, section, config_id) tuples.
663
All options are returned with their associated value and the section
664
they appeared in. ``config_id`` is a unique identifier for the
665
configuration file the option is defined in.
667
:param sections: Default to ``_get_matching_sections`` if not
668
specified. This gives a better control to daughter classes about
669
which sections should be searched. This is a list of (name,
674
parser = self._get_parser()
676
for (section_name, _) in self._get_matching_sections():
678
section = parser[section_name]
680
# This could happen for an empty file for which we define a
681
# DEFAULT section. FIXME: Force callers to provide sections
682
# instead ? -- vila 20100930
684
sections.append((section_name, section))
685
config_id = self.config_id()
686
for (section_name, section) in sections:
687
for (name, value) in section.iteritems():
688
yield (name, parser._quote(value), section_name,
691
def _get_option_policy(self, section, option_name):
692
"""Return the policy for the given (section, option_name) pair."""
695
def _get_change_editor(self):
696
return self.get_user_option('change_editor')
698
def _get_signature_checking(self):
699
"""See Config._get_signature_checking."""
700
policy = self._get_user_option('check_signatures')
702
return self._string_to_signature_policy(policy)
704
def _get_signing_policy(self):
705
"""See Config._get_signing_policy"""
706
policy = self._get_user_option('create_signatures')
708
return self._string_to_signing_policy(policy)
710
def _get_user_id(self):
711
"""Get the user id from the 'email' key in the current section."""
712
return self._get_user_option('email')
714
def _get_user_option(self, option_name):
715
"""See Config._get_user_option."""
716
for (section, extra_path) in self._get_matching_sections():
718
value = self._get_parser().get_value(section, option_name)
721
policy = self._get_option_policy(section, option_name)
722
if policy == POLICY_NONE:
724
elif policy == POLICY_NORECURSE:
725
# norecurse items only apply to the exact path
730
elif policy == POLICY_APPENDPATH:
732
value = urlutils.join(value, extra_path)
735
raise AssertionError('Unexpected config policy %r' % policy)
739
def _gpg_signing_command(self):
740
"""See Config.gpg_signing_command."""
741
return self._get_user_option('gpg_signing_command')
743
def _log_format(self):
744
"""See Config.log_format."""
745
return self._get_user_option('log_format')
747
def _post_commit(self):
748
"""See Config.post_commit."""
749
return self._get_user_option('post_commit')
751
def _string_to_signature_policy(self, signature_string):
752
"""Convert a string to a signing policy."""
753
if signature_string.lower() == 'check-available':
754
return CHECK_IF_POSSIBLE
755
if signature_string.lower() == 'ignore':
757
if signature_string.lower() == 'require':
759
raise errors.BzrError("Invalid signatures policy '%s'"
762
def _string_to_signing_policy(self, signature_string):
763
"""Convert a string to a signing policy."""
764
if signature_string.lower() == 'when-required':
765
return SIGN_WHEN_REQUIRED
766
if signature_string.lower() == 'never':
768
if signature_string.lower() == 'always':
770
raise errors.BzrError("Invalid signing policy '%s'"
773
def _get_alias(self, value):
775
return self._get_parser().get_value("ALIASES",
780
def _get_nickname(self):
781
return self.get_user_option('nickname')
783
def remove_user_option(self, option_name, section_name=None):
784
"""Remove a user option and save the configuration file.
786
:param option_name: The option to be removed.
788
:param section_name: The section the option is defined in, default to
792
parser = self._get_parser()
793
if section_name is None:
796
section = parser[section_name]
798
del section[option_name]
800
raise errors.NoSuchConfigOption(option_name)
801
self._write_config_file()
803
def _write_config_file(self):
804
if self.file_name is None:
805
raise AssertionError('We cannot save, self.file_name is None')
806
conf_dir = os.path.dirname(self.file_name)
807
ensure_config_dir_exists(conf_dir)
808
atomic_file = atomicfile.AtomicFile(self.file_name)
809
self._get_parser().write(atomic_file)
812
osutils.copy_ownership_from_path(self.file_name)
815
class LockableConfig(IniBasedConfig):
816
"""A configuration needing explicit locking for access.
818
If several processes try to write the config file, the accesses need to be
821
Daughter classes should decorate all methods that update a config with the
822
``@needs_write_lock`` decorator (they call, directly or indirectly, the
823
``_write_config_file()`` method. These methods (typically ``set_option()``
824
and variants must reload the config file from disk before calling
825
``_write_config_file()``), this can be achieved by calling the
826
``self.reload()`` method. Note that the lock scope should cover both the
827
reading and the writing of the config file which is why the decorator can't
828
be applied to ``_write_config_file()`` only.
830
This should be enough to implement the following logic:
831
- lock for exclusive write access,
832
- reload the config file from disk,
836
This logic guarantees that a writer can update a value without erasing an
837
update made by another writer.
842
def __init__(self, file_name):
843
super(LockableConfig, self).__init__(file_name=file_name)
844
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
845
# FIXME: It doesn't matter that we don't provide possible_transports
846
# below since this is currently used only for local config files ;
847
# local transports are not shared. But if/when we start using
848
# LockableConfig for other kind of transports, we will need to reuse
849
# whatever connection is already established -- vila 20100929
850
self.transport = transport.get_transport(self.dir)
851
self._lock = lockdir.LockDir(self.transport, self.lock_name)
853
def _create_from_string(self, unicode_bytes, save):
854
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
856
# We need to handle the saving here (as opposed to IniBasedConfig)
859
self._write_config_file()
862
def lock_write(self, token=None):
863
"""Takes a write lock in the directory containing the config file.
865
If the directory doesn't exist it is created.
867
ensure_config_dir_exists(self.dir)
868
return self._lock.lock_write(token)
873
def break_lock(self):
874
self._lock.break_lock()
877
def remove_user_option(self, option_name, section_name=None):
878
super(LockableConfig, self).remove_user_option(option_name,
881
def _write_config_file(self):
882
if self._lock is None or not self._lock.is_held:
883
# NB: if the following exception is raised it probably means a
884
# missing @needs_write_lock decorator on one of the callers.
885
raise errors.ObjectNotLocked(self)
886
super(LockableConfig, self)._write_config_file()
889
class GlobalConfig(LockableConfig):
890
"""The configuration that should be used for a specific location."""
893
super(GlobalConfig, self).__init__(file_name=config_filename())
899
def from_string(cls, str_or_unicode, save=False):
900
"""Create a config object from a string.
902
:param str_or_unicode: A string representing the file content. This
903
will be utf-8 encoded.
905
:param save: Whether the file should be saved upon creation.
908
conf._create_from_string(str_or_unicode, save)
911
def get_editor(self):
912
return self._get_user_option('editor')
915
def set_user_option(self, option, value):
916
"""Save option and its value in the configuration."""
917
self._set_option(option, value, 'DEFAULT')
919
def get_aliases(self):
920
"""Return the aliases section."""
921
if 'ALIASES' in self._get_parser():
922
return self._get_parser()['ALIASES']
927
def set_alias(self, alias_name, alias_command):
928
"""Save the alias in the configuration."""
929
self._set_option(alias_name, alias_command, 'ALIASES')
932
def unset_alias(self, alias_name):
933
"""Unset an existing alias."""
935
aliases = self._get_parser().get('ALIASES')
936
if not aliases or alias_name not in aliases:
937
raise errors.NoSuchAlias(alias_name)
938
del aliases[alias_name]
939
self._write_config_file()
941
def _set_option(self, option, value, section):
943
self._get_parser().setdefault(section, {})[option] = value
944
self._write_config_file()
947
def _get_sections(self, name=None):
948
"""See IniBasedConfig._get_sections()."""
949
parser = self._get_parser()
950
# We don't give access to options defined outside of any section, we
951
# used the DEFAULT section by... default.
952
if name in (None, 'DEFAULT'):
953
# This could happen for an empty file where the DEFAULT section
954
# doesn't exist yet. So we force DEFAULT when yielding
956
if 'DEFAULT' not in parser:
957
parser['DEFAULT']= {}
958
yield (name, parser[name], self.config_id())
961
def remove_user_option(self, option_name, section_name=None):
962
if section_name is None:
963
# We need to force the default section.
964
section_name = 'DEFAULT'
965
# We need to avoid the LockableConfig implementation or we'll lock
967
super(LockableConfig, self).remove_user_option(option_name,
970
def _iter_for_location_by_parts(sections, location):
971
"""Keep only the sessions matching the specified location.
973
:param sections: An iterable of section names.
975
:param location: An url or a local path to match against.
977
:returns: An iterator of (section, extra_path, nb_parts) where nb is the
978
number of path components in the section name, section is the section
979
name and extra_path is the difference between location and the section
982
``location`` will always be a local path and never a 'file://' url but the
983
section names themselves can be in either form.
985
location_parts = location.rstrip('/').split('/')
987
for section in sections:
988
# location is a local path if possible, so we need to convert 'file://'
989
# urls in section names to local paths if necessary.
991
# This also avoids having file:///path be a more exact
992
# match than '/path'.
994
# FIXME: This still raises an issue if a user defines both file:///path
995
# *and* /path. Should we raise an error in this case -- vila 20110505
997
if section.startswith('file://'):
998
section_path = urlutils.local_path_from_url(section)
1000
section_path = section
1001
section_parts = section_path.rstrip('/').split('/')
1004
if len(section_parts) > len(location_parts):
1005
# More path components in the section, they can't match
1008
# Rely on zip truncating in length to the length of the shortest
1009
# argument sequence.
1010
names = zip(location_parts, section_parts)
1012
if not fnmatch.fnmatch(name[0], name[1]):
1017
# build the path difference between the section and the location
1018
extra_path = '/'.join(location_parts[len(section_parts):])
1019
yield section, extra_path, len(section_parts)
1022
class LocationConfig(LockableConfig):
1023
"""A configuration object that gives the policy for a location."""
1025
def __init__(self, location):
1026
super(LocationConfig, self).__init__(
1027
file_name=locations_config_filename())
1028
# local file locations are looked up by local path, rather than
1029
# by file url. This is because the config file is a user
1030
# file, and we would rather not expose the user to file urls.
1031
if location.startswith('file://'):
1032
location = urlutils.local_path_from_url(location)
1033
self.location = location
1035
def config_id(self):
1039
def from_string(cls, str_or_unicode, location, save=False):
1040
"""Create a config object from a string.
1042
:param str_or_unicode: A string representing the file content. This will
1045
:param location: The location url to filter the configuration.
1047
:param save: Whether the file should be saved upon creation.
1049
conf = cls(location)
1050
conf._create_from_string(str_or_unicode, save)
1053
def _get_matching_sections(self):
1054
"""Return an ordered list of section names matching this location."""
1055
matches = list(_iter_for_location_by_parts(self._get_parser(),
1057
# put the longest (aka more specific) locations first
1059
key=lambda (section, extra_path, length): (length, section),
1061
for (section, extra_path, length) in matches:
1062
yield section, extra_path
1063
# should we stop looking for parent configs here?
1065
if self._get_parser()[section].as_bool('ignore_parents'):
1070
def _get_sections(self, name=None):
1071
"""See IniBasedConfig._get_sections()."""
1072
# We ignore the name here as the only sections handled are named with
1073
# the location path and we don't expose embedded sections either.
1074
parser = self._get_parser()
1075
for name, extra_path in self._get_matching_sections():
1076
yield (name, parser[name], self.config_id())
1078
def _get_option_policy(self, section, option_name):
1079
"""Return the policy for the given (section, option_name) pair."""
1080
# check for the old 'recurse=False' flag
1082
recurse = self._get_parser()[section].as_bool('recurse')
1086
return POLICY_NORECURSE
1088
policy_key = option_name + ':policy'
1090
policy_name = self._get_parser()[section][policy_key]
1094
return _policy_value[policy_name]
1096
def _set_option_policy(self, section, option_name, option_policy):
1097
"""Set the policy for the given option name in the given section."""
1098
# The old recurse=False option affects all options in the
1099
# section. To handle multiple policies in the section, we
1100
# need to convert it to a policy_norecurse key.
1102
recurse = self._get_parser()[section].as_bool('recurse')
1106
symbol_versioning.warn(
1107
'The recurse option is deprecated as of 0.14. '
1108
'The section "%s" has been converted to use policies.'
1111
del self._get_parser()[section]['recurse']
1113
for key in self._get_parser()[section].keys():
1114
if not key.endswith(':policy'):
1115
self._get_parser()[section][key +
1116
':policy'] = 'norecurse'
1118
policy_key = option_name + ':policy'
1119
policy_name = _policy_name[option_policy]
1120
if policy_name is not None:
1121
self._get_parser()[section][policy_key] = policy_name
1123
if policy_key in self._get_parser()[section]:
1124
del self._get_parser()[section][policy_key]
1127
def set_user_option(self, option, value, store=STORE_LOCATION):
1128
"""Save option and its value in the configuration."""
1129
if store not in [STORE_LOCATION,
1130
STORE_LOCATION_NORECURSE,
1131
STORE_LOCATION_APPENDPATH]:
1132
raise ValueError('bad storage policy %r for %r' %
1135
location = self.location
1136
if location.endswith('/'):
1137
location = location[:-1]
1138
parser = self._get_parser()
1139
if not location in parser and not location + '/' in parser:
1140
parser[location] = {}
1141
elif location + '/' in parser:
1142
location = location + '/'
1143
parser[location][option]=value
1144
# the allowed values of store match the config policies
1145
self._set_option_policy(location, option, store)
1146
self._write_config_file()
1149
class BranchConfig(Config):
1150
"""A configuration object giving the policy for a branch."""
1152
def __init__(self, branch):
1153
super(BranchConfig, self).__init__()
1154
self._location_config = None
1155
self._branch_data_config = None
1156
self._global_config = None
1157
self.branch = branch
1158
self.option_sources = (self._get_location_config,
1159
self._get_branch_data_config,
1160
self._get_global_config)
1162
def config_id(self):
1165
def _get_branch_data_config(self):
1166
if self._branch_data_config is None:
1167
self._branch_data_config = TreeConfig(self.branch)
1168
self._branch_data_config.config_id = self.config_id
1169
return self._branch_data_config
1171
def _get_location_config(self):
1172
if self._location_config is None:
1173
self._location_config = LocationConfig(self.branch.base)
1174
return self._location_config
1176
def _get_global_config(self):
1177
if self._global_config is None:
1178
self._global_config = GlobalConfig()
1179
return self._global_config
1181
def _get_best_value(self, option_name):
1182
"""This returns a user option from local, tree or global config.
1184
They are tried in that order. Use get_safe_value if trusted values
1187
for source in self.option_sources:
1188
value = getattr(source(), option_name)()
1189
if value is not None:
1193
def _get_safe_value(self, option_name):
1194
"""This variant of get_best_value never returns untrusted values.
1196
It does not return values from the branch data, because the branch may
1197
not be controlled by the user.
1199
We may wish to allow locations.conf to control whether branches are
1200
trusted in the future.
1202
for source in (self._get_location_config, self._get_global_config):
1203
value = getattr(source(), option_name)()
1204
if value is not None:
1208
def _get_user_id(self):
1209
"""Return the full user id for the branch.
1211
e.g. "John Hacker <jhacker@example.com>"
1212
This is looked up in the email controlfile for the branch.
1215
return (self.branch._transport.get_bytes("email")
1216
.decode(osutils.get_user_encoding())
1218
except errors.NoSuchFile, e:
1221
return self._get_best_value('_get_user_id')
1223
def _get_change_editor(self):
1224
return self._get_best_value('_get_change_editor')
1226
def _get_signature_checking(self):
1227
"""See Config._get_signature_checking."""
1228
return self._get_best_value('_get_signature_checking')
1230
def _get_signing_policy(self):
1231
"""See Config._get_signing_policy."""
1232
return self._get_best_value('_get_signing_policy')
1234
def _get_user_option(self, option_name):
1235
"""See Config._get_user_option."""
1236
for source in self.option_sources:
1237
value = source()._get_user_option(option_name)
1238
if value is not None:
1242
def _get_sections(self, name=None):
1243
"""See IniBasedConfig.get_sections()."""
1244
for source in self.option_sources:
1245
for section in source()._get_sections(name):
1248
def _get_options(self, sections=None):
1250
# First the locations options
1251
for option in self._get_location_config()._get_options():
1253
# Then the branch options
1254
branch_config = self._get_branch_data_config()
1255
if sections is None:
1256
sections = [('DEFAULT', branch_config._get_parser())]
1257
# FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
1258
# Config itself has no notion of sections :( -- vila 20101001
1259
config_id = self.config_id()
1260
for (section_name, section) in sections:
1261
for (name, value) in section.iteritems():
1262
yield (name, value, section_name,
1263
config_id, branch_config._get_parser())
1264
# Then the global options
1265
for option in self._get_global_config()._get_options():
1268
def set_user_option(self, name, value, store=STORE_BRANCH,
1270
if store == STORE_BRANCH:
1271
self._get_branch_data_config().set_option(value, name)
1272
elif store == STORE_GLOBAL:
1273
self._get_global_config().set_user_option(name, value)
1275
self._get_location_config().set_user_option(name, value, store)
1278
if store in (STORE_GLOBAL, STORE_BRANCH):
1279
mask_value = self._get_location_config().get_user_option(name)
1280
if mask_value is not None:
1281
trace.warning('Value "%s" is masked by "%s" from'
1282
' locations.conf', value, mask_value)
1284
if store == STORE_GLOBAL:
1285
branch_config = self._get_branch_data_config()
1286
mask_value = branch_config.get_user_option(name)
1287
if mask_value is not None:
1288
trace.warning('Value "%s" is masked by "%s" from'
1289
' branch.conf', value, mask_value)
1291
def remove_user_option(self, option_name, section_name=None):
1292
self._get_branch_data_config().remove_option(option_name, section_name)
1294
def _gpg_signing_command(self):
1295
"""See Config.gpg_signing_command."""
1296
return self._get_safe_value('_gpg_signing_command')
1298
def _post_commit(self):
1299
"""See Config.post_commit."""
1300
return self._get_safe_value('_post_commit')
1302
def _get_nickname(self):
1303
value = self._get_explicit_nickname()
1304
if value is not None:
1306
return urlutils.unescape(self.branch.base.split('/')[-2])
1308
def has_explicit_nickname(self):
1309
"""Return true if a nickname has been explicitly assigned."""
1310
return self._get_explicit_nickname() is not None
1312
def _get_explicit_nickname(self):
1313
return self._get_best_value('_get_nickname')
1315
def _log_format(self):
1316
"""See Config.log_format."""
1317
return self._get_best_value('_log_format')
1320
def ensure_config_dir_exists(path=None):
1321
"""Make sure a configuration directory exists.
1322
This makes sure that the directory exists.
1323
On windows, since configuration directories are 2 levels deep,
1324
it makes sure both the directory and the parent directory exists.
1328
if not os.path.isdir(path):
1329
if sys.platform == 'win32':
1330
parent_dir = os.path.dirname(path)
1331
if not os.path.isdir(parent_dir):
1332
trace.mutter('creating config parent directory: %r', parent_dir)
1333
os.mkdir(parent_dir)
1334
trace.mutter('creating config directory: %r', path)
1336
osutils.copy_ownership_from_path(path)
1340
"""Return per-user configuration directory.
1342
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1343
and Linux. On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1344
that will be used instead.
1346
TODO: Global option --config-dir to override this.
1348
base = os.environ.get('BZR_HOME', None)
1349
if sys.platform == 'win32':
1350
# environ variables on Windows are in user encoding/mbcs. So decode
1352
if base is not None:
1353
base = base.decode('mbcs')
1355
base = win32utils.get_appdata_location_unicode()
1357
base = os.environ.get('HOME', None)
1358
if base is not None:
1359
base = base.decode('mbcs')
1361
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1363
return osutils.pathjoin(base, 'bazaar', '2.0')
1364
elif sys.platform == 'darwin':
1366
# this takes into account $HOME
1367
base = os.path.expanduser("~")
1368
return osutils.pathjoin(base, '.bazaar')
1372
xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1374
xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1375
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1376
if osutils.isdir(xdg_dir):
1378
"Using configuration in XDG directory %s." % xdg_dir)
1381
base = os.path.expanduser("~")
1382
return osutils.pathjoin(base, ".bazaar")
1385
def config_filename():
1386
"""Return per-user configuration ini file filename."""
1387
return osutils.pathjoin(config_dir(), 'bazaar.conf')
1390
def locations_config_filename():
1391
"""Return per-user configuration ini file filename."""
1392
return osutils.pathjoin(config_dir(), 'locations.conf')
1395
def authentication_config_filename():
1396
"""Return per-user authentication ini file filename."""
1397
return osutils.pathjoin(config_dir(), 'authentication.conf')
1400
def user_ignore_config_filename():
1401
"""Return the user default ignore filename"""
1402
return osutils.pathjoin(config_dir(), 'ignore')
1406
"""Return the directory name to store crash files.
1408
This doesn't implicitly create it.
1410
On Windows it's in the config directory; elsewhere it's /var/crash
1411
which may be monitored by apport. It can be overridden by
1414
if sys.platform == 'win32':
1415
return osutils.pathjoin(config_dir(), 'Crash')
1417
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1419
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1422
def xdg_cache_dir():
1423
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1424
# Possibly this should be different on Windows?
1425
e = os.environ.get('XDG_CACHE_DIR', None)
1429
return os.path.expanduser('~/.cache')
1432
def _get_default_mail_domain():
1433
"""If possible, return the assumed default email domain.
1435
:returns: string mail domain, or None.
1437
if sys.platform == 'win32':
1438
# No implementation yet; patches welcome
1441
f = open('/etc/mailname')
1442
except (IOError, OSError), e:
1445
domain = f.read().strip()
1451
def _auto_user_id():
1452
"""Calculate automatic user identification.
1454
:returns: (realname, email), either of which may be None if they can't be
1457
Only used when none is set in the environment or the id file.
1459
This only returns an email address if we can be fairly sure the
1460
address is reasonable, ie if /etc/mailname is set on unix.
1462
This doesn't use the FQDN as the default domain because that may be
1463
slow, and it doesn't use the hostname alone because that's not normally
1464
a reasonable address.
1466
if sys.platform == 'win32':
1467
# No implementation to reliably determine Windows default mail
1468
# address; please add one.
1471
default_mail_domain = _get_default_mail_domain()
1472
if not default_mail_domain:
1478
w = pwd.getpwuid(uid)
1480
mutter('no passwd entry for uid %d?' % uid)
1483
# we try utf-8 first, because on many variants (like Linux),
1484
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
1485
# false positives. (many users will have their user encoding set to
1486
# latin-1, which cannot raise UnicodeError.)
1488
gecos = w.pw_gecos.decode('utf-8')
1490
except UnicodeError:
1492
encoding = osutils.get_user_encoding()
1493
gecos = w.pw_gecos.decode(encoding)
1494
except UnicodeError, e:
1495
mutter("cannot decode passwd entry %s" % w)
1498
username = w.pw_name.decode(encoding)
1499
except UnicodeError, e:
1500
mutter("cannot decode passwd entry %s" % w)
1503
comma = gecos.find(',')
1507
realname = gecos[:comma]
1509
return realname, (username + '@' + default_mail_domain)
1512
def parse_username(username):
1513
"""Parse e-mail username and return a (name, address) tuple."""
1514
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1516
return (username, '')
1518
return (match.group(1), match.group(2))
1521
def extract_email_address(e):
1522
"""Return just the address part of an email string.
1524
That is just the user@domain part, nothing else.
1525
This part is required to contain only ascii characters.
1526
If it can't be extracted, raises an error.
1528
>>> extract_email_address('Jane Tester <jane@test.com>')
1531
name, email = parse_username(e)
1533
raise errors.NoEmailInUsername(e)
1537
class TreeConfig(IniBasedConfig):
1538
"""Branch configuration data associated with its contents, not location"""
1540
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
1542
def __init__(self, branch):
1543
self._config = branch._get_config()
1544
self.branch = branch
1546
def _get_parser(self, file=None):
1547
if file is not None:
1548
return IniBasedConfig._get_parser(file)
1549
return self._config._get_configobj()
1551
def get_option(self, name, section=None, default=None):
1552
self.branch.lock_read()
1554
return self._config.get_option(name, section, default)
1556
self.branch.unlock()
1558
def set_option(self, value, name, section=None):
1559
"""Set a per-branch configuration option"""
1560
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1561
# higher levels providing the right lock -- vila 20101004
1562
self.branch.lock_write()
1564
self._config.set_option(value, name, section)
1566
self.branch.unlock()
1568
def remove_option(self, option_name, section_name=None):
1569
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1570
# higher levels providing the right lock -- vila 20101004
1571
self.branch.lock_write()
1573
self._config.remove_option(option_name, section_name)
1575
self.branch.unlock()
1578
class AuthenticationConfig(object):
1579
"""The authentication configuration file based on a ini file.
1581
Implements the authentication.conf file described in
1582
doc/developers/authentication-ring.txt.
1585
def __init__(self, _file=None):
1586
self._config = None # The ConfigObj
1588
self._filename = authentication_config_filename()
1589
self._input = self._filename = authentication_config_filename()
1591
# Tests can provide a string as _file
1592
self._filename = None
1595
def _get_config(self):
1596
if self._config is not None:
1599
# FIXME: Should we validate something here ? Includes: empty
1600
# sections are useless, at least one of
1601
# user/password/password_encoding should be defined, etc.
1603
# Note: the encoding below declares that the file itself is utf-8
1604
# encoded, but the values in the ConfigObj are always Unicode.
1605
self._config = ConfigObj(self._input, encoding='utf-8')
1606
except configobj.ConfigObjError, e:
1607
raise errors.ParseConfigError(e.errors, e.config.filename)
1611
"""Save the config file, only tests should use it for now."""
1612
conf_dir = os.path.dirname(self._filename)
1613
ensure_config_dir_exists(conf_dir)
1614
f = file(self._filename, 'wb')
1616
self._get_config().write(f)
1620
def _set_option(self, section_name, option_name, value):
1621
"""Set an authentication configuration option"""
1622
conf = self._get_config()
1623
section = conf.get(section_name)
1626
section = conf[section]
1627
section[option_name] = value
1630
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1632
"""Returns the matching credentials from authentication.conf file.
1634
:param scheme: protocol
1636
:param host: the server address
1638
:param port: the associated port (optional)
1640
:param user: login (optional)
1642
:param path: the absolute path on the server (optional)
1644
:param realm: the http authentication realm (optional)
1646
:return: A dict containing the matching credentials or None.
1648
- name: the section name of the credentials in the
1649
authentication.conf file,
1650
- user: can't be different from the provided user if any,
1651
- scheme: the server protocol,
1652
- host: the server address,
1653
- port: the server port (can be None),
1654
- path: the absolute server path (can be None),
1655
- realm: the http specific authentication realm (can be None),
1656
- password: the decoded password, could be None if the credential
1657
defines only the user
1658
- verify_certificates: https specific, True if the server
1659
certificate should be verified, False otherwise.
1662
for auth_def_name, auth_def in self._get_config().items():
1663
if type(auth_def) is not configobj.Section:
1664
raise ValueError("%s defined outside a section" % auth_def_name)
1666
a_scheme, a_host, a_user, a_path = map(
1667
auth_def.get, ['scheme', 'host', 'user', 'path'])
1670
a_port = auth_def.as_int('port')
1674
raise ValueError("'port' not numeric in %s" % auth_def_name)
1676
a_verify_certificates = auth_def.as_bool('verify_certificates')
1678
a_verify_certificates = True
1681
"'verify_certificates' not boolean in %s" % auth_def_name)
1684
if a_scheme is not None and scheme != a_scheme:
1686
if a_host is not None:
1687
if not (host == a_host
1688
or (a_host.startswith('.') and host.endswith(a_host))):
1690
if a_port is not None and port != a_port:
1692
if (a_path is not None and path is not None
1693
and not path.startswith(a_path)):
1695
if (a_user is not None and user is not None
1696
and a_user != user):
1697
# Never contradict the caller about the user to be used
1702
# Prepare a credentials dictionary with additional keys
1703
# for the credential providers
1704
credentials = dict(name=auth_def_name,
1711
password=auth_def.get('password', None),
1712
verify_certificates=a_verify_certificates)
1713
# Decode the password in the credentials (or get one)
1714
self.decode_password(credentials,
1715
auth_def.get('password_encoding', None))
1716
if 'auth' in debug.debug_flags:
1717
trace.mutter("Using authentication section: %r", auth_def_name)
1720
if credentials is None:
1721
# No credentials were found in authentication.conf, try the fallback
1722
# credentials stores.
1723
credentials = credential_store_registry.get_fallback_credentials(
1724
scheme, host, port, user, path, realm)
1728
def set_credentials(self, name, host, user, scheme=None, password=None,
1729
port=None, path=None, verify_certificates=None,
1731
"""Set authentication credentials for a host.
1733
Any existing credentials with matching scheme, host, port and path
1734
will be deleted, regardless of name.
1736
:param name: An arbitrary name to describe this set of credentials.
1737
:param host: Name of the host that accepts these credentials.
1738
:param user: The username portion of these credentials.
1739
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1741
:param password: Password portion of these credentials.
1742
:param port: The IP port on the host that these credentials apply to.
1743
:param path: A filesystem path on the host that these credentials
1745
:param verify_certificates: On https, verify server certificates if
1747
:param realm: The http authentication realm (optional).
1749
values = {'host': host, 'user': user}
1750
if password is not None:
1751
values['password'] = password
1752
if scheme is not None:
1753
values['scheme'] = scheme
1754
if port is not None:
1755
values['port'] = '%d' % port
1756
if path is not None:
1757
values['path'] = path
1758
if verify_certificates is not None:
1759
values['verify_certificates'] = str(verify_certificates)
1760
if realm is not None:
1761
values['realm'] = realm
1762
config = self._get_config()
1764
for section, existing_values in config.items():
1765
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1766
if existing_values.get(key) != values.get(key):
1770
config.update({name: values})
1773
def get_user(self, scheme, host, port=None, realm=None, path=None,
1774
prompt=None, ask=False, default=None):
1775
"""Get a user from authentication file.
1777
:param scheme: protocol
1779
:param host: the server address
1781
:param port: the associated port (optional)
1783
:param realm: the realm sent by the server (optional)
1785
:param path: the absolute path on the server (optional)
1787
:param ask: Ask the user if there is no explicitly configured username
1790
:param default: The username returned if none is defined (optional).
1792
:return: The found user.
1794
credentials = self.get_credentials(scheme, host, port, user=None,
1795
path=path, realm=realm)
1796
if credentials is not None:
1797
user = credentials['user']
1803
# Create a default prompt suitable for most cases
1804
prompt = scheme.upper() + ' %(host)s username'
1805
# Special handling for optional fields in the prompt
1806
if port is not None:
1807
prompt_host = '%s:%d' % (host, port)
1810
user = ui.ui_factory.get_username(prompt, host=prompt_host)
1815
def get_password(self, scheme, host, user, port=None,
1816
realm=None, path=None, prompt=None):
1817
"""Get a password from authentication file or prompt the user for one.
1819
:param scheme: protocol
1821
:param host: the server address
1823
:param port: the associated port (optional)
1827
:param realm: the realm sent by the server (optional)
1829
:param path: the absolute path on the server (optional)
1831
:return: The found password or the one entered by the user.
1833
credentials = self.get_credentials(scheme, host, port, user, path,
1835
if credentials is not None:
1836
password = credentials['password']
1837
if password is not None and scheme is 'ssh':
1838
trace.warning('password ignored in section [%s],'
1839
' use an ssh agent instead'
1840
% credentials['name'])
1844
# Prompt user only if we could't find a password
1845
if password is None:
1847
# Create a default prompt suitable for most cases
1848
prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1849
# Special handling for optional fields in the prompt
1850
if port is not None:
1851
prompt_host = '%s:%d' % (host, port)
1854
password = ui.ui_factory.get_password(prompt,
1855
host=prompt_host, user=user)
1858
def decode_password(self, credentials, encoding):
1860
cs = credential_store_registry.get_credential_store(encoding)
1862
raise ValueError('%r is not a known password_encoding' % encoding)
1863
credentials['password'] = cs.decode_password(credentials)
1867
class CredentialStoreRegistry(registry.Registry):
1868
"""A class that registers credential stores.
1870
A credential store provides access to credentials via the password_encoding
1871
field in authentication.conf sections.
1873
Except for stores provided by bzr itself, most stores are expected to be
1874
provided by plugins that will therefore use
1875
register_lazy(password_encoding, module_name, member_name, help=help,
1876
fallback=fallback) to install themselves.
1878
A fallback credential store is one that is queried if no credentials can be
1879
found via authentication.conf.
1882
def get_credential_store(self, encoding=None):
1883
cs = self.get(encoding)
1888
def is_fallback(self, name):
1889
"""Check if the named credentials store should be used as fallback."""
1890
return self.get_info(name)
1892
def get_fallback_credentials(self, scheme, host, port=None, user=None,
1893
path=None, realm=None):
1894
"""Request credentials from all fallback credentials stores.
1896
The first credentials store that can provide credentials wins.
1899
for name in self.keys():
1900
if not self.is_fallback(name):
1902
cs = self.get_credential_store(name)
1903
credentials = cs.get_credentials(scheme, host, port, user,
1905
if credentials is not None:
1906
# We found some credentials
1910
def register(self, key, obj, help=None, override_existing=False,
1912
"""Register a new object to a name.
1914
:param key: This is the key to use to request the object later.
1915
:param obj: The object to register.
1916
:param help: Help text for this entry. This may be a string or
1917
a callable. If it is a callable, it should take two
1918
parameters (registry, key): this registry and the key that
1919
the help was registered under.
1920
:param override_existing: Raise KeyErorr if False and something has
1921
already been registered for that key. If True, ignore if there
1922
is an existing key (always register the new value).
1923
:param fallback: Whether this credential store should be
1926
return super(CredentialStoreRegistry,
1927
self).register(key, obj, help, info=fallback,
1928
override_existing=override_existing)
1930
def register_lazy(self, key, module_name, member_name,
1931
help=None, override_existing=False,
1933
"""Register a new credential store to be loaded on request.
1935
:param module_name: The python path to the module. Such as 'os.path'.
1936
:param member_name: The member of the module to return. If empty or
1937
None, get() will return the module itself.
1938
:param help: Help text for this entry. This may be a string or
1940
:param override_existing: If True, replace the existing object
1941
with the new one. If False, if there is already something
1942
registered with the same key, raise a KeyError
1943
:param fallback: Whether this credential store should be
1946
return super(CredentialStoreRegistry, self).register_lazy(
1947
key, module_name, member_name, help,
1948
info=fallback, override_existing=override_existing)
1951
credential_store_registry = CredentialStoreRegistry()
1954
class CredentialStore(object):
1955
"""An abstract class to implement storage for credentials"""
1957
def decode_password(self, credentials):
1958
"""Returns a clear text password for the provided credentials."""
1959
raise NotImplementedError(self.decode_password)
1961
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1963
"""Return the matching credentials from this credential store.
1965
This method is only called on fallback credential stores.
1967
raise NotImplementedError(self.get_credentials)
1971
class PlainTextCredentialStore(CredentialStore):
1972
__doc__ = """Plain text credential store for the authentication.conf file"""
1974
def decode_password(self, credentials):
1975
"""See CredentialStore.decode_password."""
1976
return credentials['password']
1979
credential_store_registry.register('plain', PlainTextCredentialStore,
1980
help=PlainTextCredentialStore.__doc__)
1981
credential_store_registry.default_key = 'plain'
1984
class BzrDirConfig(object):
1986
def __init__(self, bzrdir):
1987
self._bzrdir = bzrdir
1988
self._config = bzrdir._get_config()
1990
def set_default_stack_on(self, value):
1991
"""Set the default stacking location.
1993
It may be set to a location, or None.
1995
This policy affects all branches contained by this bzrdir, except for
1996
those under repositories.
1998
if self._config is None:
1999
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
2001
self._config.set_option('', 'default_stack_on')
2003
self._config.set_option(value, 'default_stack_on')
2005
def get_default_stack_on(self):
2006
"""Return the default stacking location.
2008
This will either be a location, or None.
2010
This policy affects all branches contained by this bzrdir, except for
2011
those under repositories.
2013
if self._config is None:
2015
value = self._config.get_option('default_stack_on')
2021
class TransportConfig(object):
2022
"""A Config that reads/writes a config file on a Transport.
2024
It is a low-level object that considers config data to be name/value pairs
2025
that may be associated with a section. Assigning meaning to these values
2026
is done at higher levels like TreeConfig.
2029
def __init__(self, transport, filename):
2030
self._transport = transport
2031
self._filename = filename
2033
def get_option(self, name, section=None, default=None):
2034
"""Return the value associated with a named option.
2036
:param name: The name of the value
2037
:param section: The section the option is in (if any)
2038
:param default: The value to return if the value is not set
2039
:return: The value or default value
2041
configobj = self._get_configobj()
2043
section_obj = configobj
2046
section_obj = configobj[section]
2049
return section_obj.get(name, default)
2051
def set_option(self, value, name, section=None):
2052
"""Set the value associated with a named option.
2054
:param value: The value to set
2055
:param name: The name of the value to set
2056
:param section: The section the option is in (if any)
2058
configobj = self._get_configobj()
2060
configobj[name] = value
2062
configobj.setdefault(section, {})[name] = value
2063
self._set_configobj(configobj)
2065
def remove_option(self, option_name, section_name=None):
2066
configobj = self._get_configobj()
2067
if section_name is None:
2068
del configobj[option_name]
2070
del configobj[section_name][option_name]
2071
self._set_configobj(configobj)
2073
def _get_config_file(self):
2075
return StringIO(self._transport.get_bytes(self._filename))
2076
except errors.NoSuchFile:
2079
def _get_configobj(self):
2080
f = self._get_config_file()
2082
return ConfigObj(f, encoding='utf-8')
2086
def _set_configobj(self, configobj):
2087
out_file = StringIO()
2088
configobj.write(out_file)
2090
self._transport.put_file(self._filename, out_file)
2093
class Section(object):
2094
"""A section defines a dict of options.
2096
This is merely a read-only dict which can add some knowledge about the
2097
options. It is *not* a python dict object though and doesn't try to mimic
2101
def __init__(self, section_id, options):
2102
self.id = section_id
2103
# We re-use the dict-like object received
2104
self.options = options
2106
def get(self, name, default=None):
2107
return self.options.get(name, default)
2110
# Mostly for debugging use
2111
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2114
_NewlyCreatedOption = object()
2115
"""Was the option created during the MutableSection lifetime"""
2118
class MutableSection(Section):
2119
"""A section allowing changes and keeping track of the original values."""
2121
def __init__(self, section_id, options):
2122
super(MutableSection, self).__init__(section_id, options)
2125
def set(self, name, value):
2126
if name not in self.options:
2127
# This is a new option
2128
self.orig[name] = _NewlyCreatedOption
2129
elif name not in self.orig:
2130
self.orig[name] = self.get(name, None)
2131
self.options[name] = value
2133
def remove(self, name):
2134
if name not in self.orig:
2135
self.orig[name] = self.get(name, None)
2136
del self.options[name]
2139
class Store(object):
2140
"""Abstract interface to persistent storage for configuration options."""
2142
readonly_section_class = Section
2143
mutable_section_class = MutableSection
2145
def is_loaded(self):
2146
"""Returns True if the Store has been loaded.
2148
This is used to implement lazy loading and ensure the persistent
2149
storage is queried only when needed.
2151
raise NotImplementedError(self.is_loaded)
2154
"""Loads the Store from persistent storage."""
2155
raise NotImplementedError(self.load)
2157
def _load_from_string(self, str_or_unicode):
2158
"""Create a store from a string in configobj syntax.
2160
:param str_or_unicode: A string representing the file content. This will
2161
be encoded to suit store needs internally.
2163
This is for tests and should not be used in production unless a
2164
convincing use case can be demonstrated :)
2166
raise NotImplementedError(self._load_from_string)
2169
"""Saves the Store to persistent storage."""
2170
raise NotImplementedError(self.save)
2172
def external_url(self):
2173
raise NotImplementedError(self.external_url)
2175
def get_sections(self):
2176
"""Returns an ordered iterable of existing sections.
2178
:returns: An iterable of (name, dict).
2180
raise NotImplementedError(self.get_sections)
2182
def get_mutable_section(self, section_name=None):
2183
"""Returns the specified mutable section.
2185
:param section_name: The section identifier
2187
raise NotImplementedError(self.get_mutable_section)
2190
# Mostly for debugging use
2191
return "<config.%s(%s)>" % (self.__class__.__name__,
2192
self.external_url())
2195
class IniFileStore(Store):
2196
"""A config Store using ConfigObj for storage.
2198
:ivar transport: The transport object where the config file is located.
2200
:ivar file_name: The config file basename in the transport directory.
2202
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2203
serialize/deserialize the config file.
2206
def __init__(self, transport, file_name):
2207
"""A config Store using ConfigObj for storage.
2209
:param transport: The transport object where the config file is located.
2211
:param file_name: The config file basename in the transport directory.
2213
super(IniFileStore, self).__init__()
2214
self.transport = transport
2215
self.file_name = file_name
2216
self._config_obj = None
2218
def is_loaded(self):
2219
return self._config_obj != None
2222
"""Load the store from the associated file."""
2223
if self.is_loaded():
2225
content = self.transport.get_bytes(self.file_name)
2226
self._load_from_string(content)
2228
def _load_from_string(self, str_or_unicode):
2229
"""Create a config store from a string.
2231
:param str_or_unicode: A string representing the file content. This will
2232
be utf-8 encoded internally.
2234
This is for tests and should not be used in production unless a
2235
convincing use case can be demonstrated :)
2237
if self.is_loaded():
2238
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2239
co_input = StringIO(str_or_unicode.encode('utf-8'))
2241
# The config files are always stored utf8-encoded
2242
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2243
except configobj.ConfigObjError, e:
2244
self._config_obj = None
2245
raise errors.ParseConfigError(e.errors, self.external_url())
2248
if not self.is_loaded():
2252
self._config_obj.write(out)
2253
self.transport.put_bytes(self.file_name, out.getvalue())
2255
def external_url(self):
2256
# FIXME: external_url should really accepts an optional relpath
2257
# parameter (bug #750169) :-/ -- vila 2011-04-04
2258
# The following will do in the interim but maybe we don't want to
2259
# expose a path here but rather a config ID and its associated
2260
# object </hand wawe>.
2261
return urlutils.join(self.transport.external_url(), self.file_name)
2263
def get_sections(self):
2264
"""Get the configobj section in the file order.
2266
:returns: An iterable of (name, dict).
2268
# We need a loaded store
2271
except errors.NoSuchFile:
2272
# If the file doesn't exist, there is no sections
2274
cobj = self._config_obj
2276
yield self.readonly_section_class(None, cobj)
2277
for section_name in cobj.sections:
2278
yield self.readonly_section_class(section_name, cobj[section_name])
2280
def get_mutable_section(self, section_name=None):
2281
# We need a loaded store
2284
except errors.NoSuchFile:
2285
# The file doesn't exist, let's pretend it was empty
2286
self._load_from_string('')
2287
if section_name is None:
2288
section = self._config_obj
2290
section = self._config_obj.setdefault(section_name, {})
2291
return self.mutable_section_class(section_name, section)
2294
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2295
# unlockable stores for use with objects that can already ensure the locking
2296
# (think branches). If different stores (not based on ConfigObj) are created,
2297
# they may face the same issue.
2300
class LockableIniFileStore(IniFileStore):
2301
"""A ConfigObjStore using locks on save to ensure store integrity."""
2303
def __init__(self, transport, file_name, lock_dir_name=None):
2304
"""A config Store using ConfigObj for storage.
2306
:param transport: The transport object where the config file is located.
2308
:param file_name: The config file basename in the transport directory.
2310
if lock_dir_name is None:
2311
lock_dir_name = 'lock'
2312
self.lock_dir_name = lock_dir_name
2313
super(LockableIniFileStore, self).__init__(transport, file_name)
2314
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2316
def lock_write(self, token=None):
2317
"""Takes a write lock in the directory containing the config file.
2319
If the directory doesn't exist it is created.
2321
# FIXME: This doesn't check the ownership of the created directories as
2322
# ensure_config_dir_exists does. It should if the transport is local
2323
# -- vila 2011-04-06
2324
self.transport.create_prefix()
2325
return self._lock.lock_write(token)
2330
def break_lock(self):
2331
self._lock.break_lock()
2335
super(LockableIniFileStore, self).save()
2338
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2339
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2340
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2342
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2343
# functions or a registry will make it easier and clearer for tests, focusing
2344
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2345
# on a poolie's remark)
2346
class GlobalStore(LockableIniFileStore):
2348
def __init__(self, possible_transports=None):
2349
t = transport.get_transport(config_dir(),
2350
possible_transports=possible_transports)
2351
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2354
class LocationStore(LockableIniFileStore):
2356
def __init__(self, possible_transports=None):
2357
t = transport.get_transport(config_dir(),
2358
possible_transports=possible_transports)
2359
super(LocationStore, self).__init__(t, 'locations.conf')
2362
class BranchStore(IniFileStore):
2364
def __init__(self, branch):
2365
super(BranchStore, self).__init__(branch.control_transport,
2368
class SectionMatcher(object):
2369
"""Select sections into a given Store.
2371
This intended to be used to postpone getting an iterable of sections from a
2375
def __init__(self, store):
2378
def get_sections(self):
2379
# This is where we require loading the store so we can see all defined
2381
sections = self.store.get_sections()
2382
# Walk the revisions in the order provided
2387
def match(self, secion):
2388
raise NotImplementedError(self.match)
2391
class LocationSection(Section):
2393
def __init__(self, section, length, extra_path):
2394
super(LocationSection, self).__init__(section.id, section.options)
2395
self.length = length
2396
self.extra_path = extra_path
2398
def get(self, name, default=None):
2399
value = super(LocationSection, self).get(name, default)
2400
if value is not None:
2401
policy_name = self.get(name + ':policy', None)
2402
policy = _policy_value.get(policy_name, POLICY_NONE)
2403
if policy == POLICY_APPENDPATH:
2404
value = urlutils.join(value, self.extra_path)
2408
class LocationMatcher(SectionMatcher):
2410
def __init__(self, store, location):
2411
super(LocationMatcher, self).__init__(store)
2412
if location.startswith('file://'):
2413
location = urlutils.local_path_from_url(location)
2414
self.location = location
2416
def _get_matching_sections(self):
2417
"""Get all sections matching ``location``."""
2418
# We slightly diverge from LocalConfig here by allowing the no-name
2419
# section as the most generic one and the lower priority.
2420
no_name_section = None
2422
# Filter out the no_name_section so _iter_for_location_by_parts can be
2423
# used (it assumes all sections have a name).
2424
for section in self.store.get_sections():
2425
if section.id is None:
2426
no_name_section = section
2428
sections.append(section)
2429
# Unfortunately _iter_for_location_by_parts deals with section names so
2430
# we have to resync.
2431
filtered_sections = _iter_for_location_by_parts(
2432
[s.id for s in sections], self.location)
2433
iter_sections = iter(sections)
2434
matching_sections = []
2435
if no_name_section is not None:
2436
matching_sections.append(
2437
LocationSection(no_name_section, 0, self.location))
2438
for section_id, extra_path, length in filtered_sections:
2439
# a section id is unique for a given store so it's safe to iterate
2441
section = iter_sections.next()
2442
if section_id == section.id:
2443
matching_sections.append(
2444
LocationSection(section, length, extra_path))
2445
return matching_sections
2447
def get_sections(self):
2448
# Override the default implementation as we want to change the order
2449
matching_sections = self._get_matching_sections()
2450
# We want the longest (aka more specific) locations first
2451
sections = sorted(matching_sections,
2452
key=lambda section: (section.length, section.id),
2454
# Sections mentioning 'ignore_parents' restrict the selection
2455
for section in sections:
2456
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2457
ignore = section.get('ignore_parents', None)
2458
if ignore is not None:
2459
ignore = ui.bool_from_string(ignore)
2462
# Finally, we have a valid section
2466
class Stack(object):
2467
"""A stack of configurations where an option can be defined"""
2469
def __init__(self, sections_def, store=None, mutable_section_name=None):
2470
"""Creates a stack of sections with an optional store for changes.
2472
:param sections_def: A list of Section or callables that returns an
2473
iterable of Section. This defines the Sections for the Stack and
2474
can be called repeatedly if needed.
2476
:param store: The optional Store where modifications will be
2477
recorded. If none is specified, no modifications can be done.
2479
:param mutable_section_name: The name of the MutableSection where
2480
changes are recorded. This requires the ``store`` parameter to be
2483
self.sections_def = sections_def
2485
self.mutable_section_name = mutable_section_name
2487
def get(self, name):
2488
"""Return the *first* option value found in the sections.
2490
This is where we guarantee that sections coming from Store are loaded
2491
lazily: the loading is delayed until we need to either check that an
2492
option exists or get its value, which in turn may require to discover
2493
in which sections it can be defined. Both of these (section and option
2494
existence) require loading the store (even partially).
2496
# FIXME: No caching of options nor sections yet -- vila 20110503
2498
# Ensuring lazy loading is achieved by delaying section matching (which
2499
# implies querying the persistent storage) until it can't be avoided
2500
# anymore by using callables to describe (possibly empty) section
2502
for section_or_callable in self.sections_def:
2503
# Each section can expand to multiple ones when a callable is used
2504
if callable(section_or_callable):
2505
sections = section_or_callable()
2507
sections = [section_or_callable]
2508
for section in sections:
2509
value = section.get(name)
2510
if value is not None:
2512
# No definition was found
2515
def _get_mutable_section(self):
2516
"""Get the MutableSection for the Stack.
2518
This is where we guarantee that the mutable section is lazily loaded:
2519
this means we won't load the corresponding store before setting a value
2520
or deleting an option. In practice the store will often be loaded but
2521
this allows helps catching some programming errors.
2523
section = self.store.get_mutable_section(self.mutable_section_name)
2526
def set(self, name, value):
2527
"""Set a new value for the option."""
2528
section = self._get_mutable_section()
2529
section.set(name, value)
2531
def remove(self, name):
2532
"""Remove an existing option."""
2533
section = self._get_mutable_section()
2534
section.remove(name)
2537
# Mostly for debugging use
2538
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2541
class GlobalStack(Stack):
2545
gstore = GlobalStore()
2546
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2549
class LocationStack(Stack):
2551
def __init__(self, location):
2552
lstore = LocationStore()
2553
matcher = LocationMatcher(lstore, location)
2554
gstore = GlobalStore()
2555
super(LocationStack, self).__init__(
2556
[matcher.get_sections, gstore.get_sections], lstore)
2559
class BranchStack(Stack):
2561
def __init__(self, branch):
2562
bstore = BranchStore(branch)
2563
lstore = LocationStore()
2564
matcher = LocationMatcher(lstore, branch.base)
2565
gstore = GlobalStore()
2566
super(BranchStack, self).__init__(
2567
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2571
class cmd_config(commands.Command):
2572
__doc__ = """Display, set or remove a configuration option.
2574
Display the active value for a given option.
2576
If --all is specified, NAME is interpreted as a regular expression and all
2577
matching options are displayed mentioning their scope. The active value
2578
that bzr will take into account is the first one displayed for each option.
2580
If no NAME is given, --all .* is implied.
2582
Setting a value is achieved by using name=value without spaces. The value
2583
is set in the most relevant scope and can be checked by displaying the
2587
takes_args = ['name?']
2591
# FIXME: This should be a registry option so that plugins can register
2592
# their own config files (or not) -- vila 20101002
2593
commands.Option('scope', help='Reduce the scope to the specified'
2594
' configuration file',
2596
commands.Option('all',
2597
help='Display all the defined values for the matching options.',
2599
commands.Option('remove', help='Remove the option from'
2600
' the configuration file'),
2603
@commands.display_command
2604
def run(self, name=None, all=False, directory=None, scope=None,
2606
if directory is None:
2608
directory = urlutils.normalize_url(directory)
2610
raise errors.BzrError(
2611
'--all and --remove are mutually exclusive.')
2613
# Delete the option in the given scope
2614
self._remove_config_option(name, directory, scope)
2616
# Defaults to all options
2617
self._show_matching_options('.*', directory, scope)
2620
name, value = name.split('=', 1)
2622
# Display the option(s) value(s)
2624
self._show_matching_options(name, directory, scope)
2626
self._show_value(name, directory, scope)
2629
raise errors.BzrError(
2630
'Only one option can be set.')
2631
# Set the option value
2632
self._set_config_option(name, value, directory, scope)
2634
def _get_configs(self, directory, scope=None):
2635
"""Iterate the configurations specified by ``directory`` and ``scope``.
2637
:param directory: Where the configurations are derived from.
2639
:param scope: A specific config to start from.
2641
if scope is not None:
2642
if scope == 'bazaar':
2643
yield GlobalConfig()
2644
elif scope == 'locations':
2645
yield LocationConfig(directory)
2646
elif scope == 'branch':
2647
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2649
yield br.get_config()
2652
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2654
yield br.get_config()
2655
except errors.NotBranchError:
2656
yield LocationConfig(directory)
2657
yield GlobalConfig()
2659
def _show_value(self, name, directory, scope):
2661
for c in self._get_configs(directory, scope):
2664
for (oname, value, section, conf_id, parser) in c._get_options():
2666
# Display only the first value and exit
2668
# FIXME: We need to use get_user_option to take policies
2669
# into account and we need to make sure the option exists
2670
# too (hence the two for loops), this needs a better API
2672
value = c.get_user_option(name)
2673
# Quote the value appropriately
2674
value = parser._quote(value)
2675
self.outf.write('%s\n' % (value,))
2679
raise errors.NoSuchConfigOption(name)
2681
def _show_matching_options(self, name, directory, scope):
2682
name = re.compile(name)
2683
# We want any error in the regexp to be raised *now* so we need to
2684
# avoid the delay introduced by the lazy regexp.
2685
name._compile_and_collapse()
2688
for c in self._get_configs(directory, scope):
2689
for (oname, value, section, conf_id, parser) in c._get_options():
2690
if name.search(oname):
2691
if cur_conf_id != conf_id:
2692
# Explain where the options are defined
2693
self.outf.write('%s:\n' % (conf_id,))
2694
cur_conf_id = conf_id
2696
if (section not in (None, 'DEFAULT')
2697
and cur_section != section):
2698
# Display the section if it's not the default (or only)
2700
self.outf.write(' [%s]\n' % (section,))
2701
cur_section = section
2702
self.outf.write(' %s = %s\n' % (oname, value))
2704
def _set_config_option(self, name, value, directory, scope):
2705
for conf in self._get_configs(directory, scope):
2706
conf.set_user_option(name, value)
2709
raise errors.NoSuchConfig(scope)
2711
def _remove_config_option(self, name, directory, scope):
2713
raise errors.BzrCommandError(
2714
'--remove expects an option to remove.')
2716
for conf in self._get_configs(directory, scope):
2717
for (section_name, section, conf_id) in conf._get_sections():
2718
if scope is not None and conf_id != scope:
2719
# Not the right configuration file
2722
if conf_id != conf.config_id():
2723
conf = self._get_configs(directory, conf_id).next()
2724
# We use the first section in the first config where the
2725
# option is defined to remove it
2726
conf.remove_user_option(name, section_name)
2731
raise errors.NoSuchConfig(scope)
2733
raise errors.NoSuchConfigOption(name)