2261
2318
The option *values* are stored in config files and found in sections.
2263
2320
Here we define various properties about the option itself, its default
2264
value, in which config files it can be stored, etc (TBC).
2321
value, how to convert it from stores, what to do when invalid values are
2322
encoutered, in which config files it can be stored.
2267
def __init__(self, name, default=None, from_unicode=None):
2325
def __init__(self, name, default=None, default_from_env=None,
2327
from_unicode=None, invalid=None):
2328
"""Build an option definition.
2330
:param name: the name used to refer to the option.
2332
:param default: the default value to use when none exist in the config
2333
stores. This is either a string that ``from_unicode`` will convert
2334
into the proper type or a python object that can be stringified (so
2335
only the empty list is supported for example).
2337
:param default_from_env: A list of environment variables which can
2338
provide a default value. 'default' will be used only if none of the
2339
variables specified here are set in the environment.
2341
:param help: a doc string to explain the option to the user.
2343
:param from_unicode: a callable to convert the unicode string
2344
representing the option value in a store. This is not called for
2347
:param invalid: the action to be taken when an invalid value is
2348
encountered in a store. This is called only when from_unicode is
2349
invoked to convert a string and returns None or raise ValueError or
2350
TypeError. Accepted values are: None (ignore invalid values),
2351
'warning' (emit a warning), 'error' (emit an error message and
2354
if default_from_env is None:
2355
default_from_env = []
2268
2356
self.name = name
2269
self.default = default
2357
# Convert the default value to a unicode string so all values are
2358
# strings internally before conversion (via from_unicode) is attempted.
2361
elif isinstance(default, list):
2362
# Only the empty list is supported
2364
raise AssertionError(
2365
'Only empty lists are supported as default values')
2367
elif isinstance(default, (str, unicode, bool, int, float)):
2368
# Rely on python to convert strings, booleans and integers
2369
self.default = u'%s' % (default,)
2371
# other python objects are not expected
2372
raise AssertionError('%r is not supported as a default value'
2374
self.default_from_env = default_from_env
2270
2376
self.from_unicode = from_unicode
2377
if invalid and invalid not in ('warning', 'error'):
2378
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2379
self.invalid = invalid
2381
def convert_from_unicode(self, unicode_value):
2382
if self.from_unicode is None or unicode_value is None:
2383
# Don't convert or nothing to convert
2384
return unicode_value
2386
converted = self.from_unicode(unicode_value)
2387
except (ValueError, TypeError):
2388
# Invalid values are ignored
2390
if converted is None and self.invalid is not None:
2391
# The conversion failed
2392
if self.invalid == 'warning':
2393
trace.warning('Value "%s" is not valid for "%s"',
2394
unicode_value, self.name)
2395
elif self.invalid == 'error':
2396
raise errors.ConfigOptionValueError(self.name, unicode_value)
2272
2399
def get_default(self):
2401
for var in self.default_from_env:
2403
# If the env variable is defined, its value is the default one
2404
value = os.environ[var]
2409
# Otherwise, fallback to the value defined at registration
2410
value = self.default
2413
def get_help_text(self, additional_see_also=None, plain=True):
2415
from bzrlib import help_topics
2416
result += help_topics._format_see_also(additional_see_also)
2418
result = help_topics.help_as_plain_text(result)
2276
2422
# Predefined converters to get proper values from store
2279
2425
return ui.bool_from_string(unicode_str)
2284
option_registry = registry.Registry()
2287
option_registry.register(
2288
'editor', Option('editor'),
2289
help='The command called to launch an editor to enter a message.')
2291
option_registry.register(
2292
'dirstate.fdatasync', Option('dirstate.fdatasync', default=True,
2293
from_unicode=bool_from_store),
2294
help='Flush dirstate changes onto physical disk?')
2296
option_registry.register(
2297
'repository.fdatasync',
2298
Option('repository.fdatasync', default=True, from_unicode=bool_from_store),
2299
help='Flush repository changes onto physical disk?')
2428
def int_from_store(unicode_str):
2429
return int(unicode_str)
2432
def float_from_store(unicode_str):
2433
return float(unicode_str)
2437
# Use a an empty dict to initialize an empty configobj avoiding all
2438
# parsing and encoding checks
2439
_list_converter_config = configobj.ConfigObj(
2440
{}, encoding='utf-8', list_values=True, interpolation=False)
2443
def list_from_store(unicode_str):
2444
if not isinstance(unicode_str, basestring):
2446
# Now inject our string directly as unicode. All callers got their value
2447
# from configobj, so values that need to be quoted are already properly
2449
_list_converter_config.reset()
2450
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2451
maybe_list = _list_converter_config['list']
2452
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2453
if isinstance(maybe_list, basestring):
2455
# A single value, most probably the user forgot (or didn't care to
2456
# add) the final ','
2459
# The empty string, convert to empty list
2462
# We rely on ConfigObj providing us with a list already
2467
class OptionRegistry(registry.Registry):
2468
"""Register config options by their name.
2470
This overrides ``registry.Registry`` to simplify registration by acquiring
2471
some information from the option object itself.
2474
def register(self, option):
2475
"""Register a new option to its name.
2477
:param option: The option to register. Its name is used as the key.
2479
super(OptionRegistry, self).register(option.name, option,
2482
def register_lazy(self, key, module_name, member_name):
2483
"""Register a new option to be loaded on request.
2485
:param key: the key to request the option later. Since the registration
2486
is lazy, it should be provided and match the option name.
2488
:param module_name: the python path to the module. Such as 'os.path'.
2490
:param member_name: the member of the module to return. If empty or
2491
None, get() will return the module itself.
2493
super(OptionRegistry, self).register_lazy(key,
2494
module_name, member_name)
2496
def get_help(self, key=None):
2497
"""Get the help text associated with the given key"""
2498
option = self.get(key)
2499
the_help = option.help
2500
if callable(the_help):
2501
return the_help(self, key)
2505
option_registry = OptionRegistry()
2508
# Registered options in lexicographical order
2510
option_registry.register(
2511
Option('bzr.workingtree.worth_saving_limit', default=10,
2512
from_unicode=int_from_store, invalid='warning',
2514
How many changes before saving the dirstate.
2516
-1 means that we will never rewrite the dirstate file for only
2517
stat-cache changes. Regardless of this setting, we will always rewrite
2518
the dirstate file if a file is added/removed/renamed/etc. This flag only
2519
affects the behavior of updating the dirstate file after we notice that
2520
a file has been touched.
2522
option_registry.register(
2523
Option('dirstate.fdatasync', default=True,
2524
from_unicode=bool_from_store,
2526
Flush dirstate changes onto physical disk?
2528
If true (default), working tree metadata changes are flushed through the
2529
OS buffers to physical disk. This is somewhat slower, but means data
2530
should not be lost if the machine crashes. See also repository.fdatasync.
2532
option_registry.register(
2533
Option('debug_flags', default=[], from_unicode=list_from_store,
2534
help='Debug flags to activate.'))
2535
option_registry.register(
2536
Option('default_format', default='2a',
2537
help='Format used when creating branches.'))
2538
option_registry.register(
2539
Option('dpush_strict', default=None,
2540
from_unicode=bool_from_store,
2542
The default value for ``dpush --strict``.
2544
If present, defines the ``--strict`` option default value for checking
2545
uncommitted changes before pushing into a different VCS without any
2546
custom bzr metadata.
2548
option_registry.register(
2550
help='The command called to launch an editor to enter a message.'))
2551
option_registry.register(
2552
Option('ignore_missing_extensions', default=False,
2553
from_unicode=bool_from_store,
2555
Control the missing extensions warning display.
2557
The warning will not be emitted if set to True.
2559
option_registry.register(
2561
help='Language to translate messages into.'))
2562
option_registry.register(
2563
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2565
Steal locks that appears to be dead.
2567
If set to True, bzr will check if a lock is supposed to be held by an
2568
active process from the same user on the same machine. If the user and
2569
machine match, but no process with the given PID is active, then bzr
2570
will automatically break the stale lock, and create a new lock for
2572
Otherwise, bzr will prompt as normal to break the lock.
2574
option_registry.register(
2575
Option('log_format', default='long',
2577
Log format to use when displaying revisions.
2579
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2580
may be provided by plugins.
2582
option_registry.register(
2583
Option('output_encoding',
2584
help= 'Unicode encoding for output'
2585
' (terminal encoding if not specified).'))
2586
option_registry.register(
2587
Option('push_strict', default=None,
2588
from_unicode=bool_from_store,
2590
The default value for ``push --strict``.
2592
If present, defines the ``--strict`` option default value for checking
2593
uncommitted changes before sending a merge directive.
2595
option_registry.register(
2596
Option('repository.fdatasync', default=True,
2597
from_unicode=bool_from_store,
2599
Flush repository changes onto physical disk?
2601
If true (default), repository changes are flushed through the OS buffers
2602
to physical disk. This is somewhat slower, but means data should not be
2603
lost if the machine crashes. See also dirstate.fdatasync.
2605
option_registry.register(
2606
Option('send_strict', default=None,
2607
from_unicode=bool_from_store,
2609
The default value for ``send --strict``.
2611
If present, defines the ``--strict`` option default value for checking
2612
uncommitted changes before pushing.
2615
option_registry.register(
2616
Option('serve.client_timeout',
2617
default=300.0, from_unicode=float_from_store,
2618
help="If we wait for a new request from a client for more than"
2619
" X seconds, consider the client idle, and hangup."))
2302
2622
class Section(object):
2468
2840
out = StringIO()
2469
2841
self._config_obj.write(out)
2470
self.transport.put_bytes(self.file_name, out.getvalue())
2842
self._save_content(out.getvalue())
2471
2843
for hook in ConfigHooks['save']:
2474
def external_url(self):
2475
# FIXME: external_url should really accepts an optional relpath
2476
# parameter (bug #750169) :-/ -- vila 2011-04-04
2477
# The following will do in the interim but maybe we don't want to
2478
# expose a path here but rather a config ID and its associated
2479
# object </hand wawe>.
2480
return urlutils.join(self.transport.external_url(), self.file_name)
2482
2846
def get_sections(self):
2483
2847
"""Get the configobj section in the file order.
2485
:returns: An iterable of (name, dict).
2849
:returns: An iterable of (store, section).
2487
2851
# We need a loaded store
2490
except errors.NoSuchFile:
2491
# If the file doesn't exist, there is no sections
2854
except (errors.NoSuchFile, errors.PermissionDenied):
2855
# If the file can't be read, there is no sections
2493
2857
cobj = self._config_obj
2494
2858
if cobj.scalars:
2495
yield self.readonly_section_class(None, cobj)
2859
yield self, self.readonly_section_class(None, cobj)
2496
2860
for section_name in cobj.sections:
2497
yield self.readonly_section_class(section_name, cobj[section_name])
2862
self.readonly_section_class(section_name,
2863
cobj[section_name]))
2499
def get_mutable_section(self, section_name=None):
2865
def get_mutable_section(self, section_id=None):
2500
2866
# We need a loaded store
2503
2869
except errors.NoSuchFile:
2504
2870
# The file doesn't exist, let's pretend it was empty
2505
2871
self._load_from_string('')
2506
if section_name is None:
2872
if section_id is None:
2507
2873
section = self._config_obj
2509
section = self._config_obj.setdefault(section_name, {})
2510
return self.mutable_section_class(section_name, section)
2875
section = self._config_obj.setdefault(section_id, {})
2876
return self.mutable_section_class(section_id, section)
2879
class TransportIniFileStore(IniFileStore):
2880
"""IniFileStore that loads files from a transport.
2883
def __init__(self, transport, file_name):
2884
"""A Store using a ini file on a Transport
2886
:param transport: The transport object where the config file is located.
2887
:param file_name: The config file basename in the transport directory.
2889
super(TransportIniFileStore, self).__init__()
2890
self.transport = transport
2891
self.file_name = file_name
2893
def _load_content(self):
2895
return self.transport.get_bytes(self.file_name)
2896
except errors.PermissionDenied:
2897
trace.warning("Permission denied while trying to load "
2898
"configuration store %s.", self.external_url())
2901
def _save_content(self, content):
2902
self.transport.put_bytes(self.file_name, content)
2904
def external_url(self):
2905
# FIXME: external_url should really accepts an optional relpath
2906
# parameter (bug #750169) :-/ -- vila 2011-04-04
2907
# The following will do in the interim but maybe we don't want to
2908
# expose a path here but rather a config ID and its associated
2909
# object </hand wawe>.
2910
return urlutils.join(self.transport.external_url(), self.file_name)
2513
2913
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2620
3031
sections = self.store.get_sections()
2621
3032
# Walk the revisions in the order provided
3033
for store, s in sections:
2623
3034
if self.match(s):
2626
def match(self, secion):
3037
def match(self, section):
3038
"""Does the proposed section match.
3040
:param section: A Section object.
3042
:returns: True if the section matches, False otherwise.
2627
3044
raise NotImplementedError(self.match)
3047
class NameMatcher(SectionMatcher):
3049
def __init__(self, store, section_id):
3050
super(NameMatcher, self).__init__(store)
3051
self.section_id = section_id
3053
def match(self, section):
3054
return section.id == self.section_id
2630
3057
class LocationSection(Section):
2632
3059
def __init__(self, section, length, extra_path):
2633
3060
super(LocationSection, self).__init__(section.id, section.options)
2634
3061
self.length = length
2635
3062
self.extra_path = extra_path
3063
self.locals = {'relpath': extra_path,
3064
'basename': urlutils.basename(extra_path)}
2637
def get(self, name, default=None):
3066
def get(self, name, default=None, expand=True):
2638
3067
value = super(LocationSection, self).get(name, default)
2639
if value is not None:
3068
if value is not None and expand:
2640
3069
policy_name = self.get(name + ':policy', None)
2641
3070
policy = _policy_value.get(policy_name, POLICY_NONE)
2642
3071
if policy == POLICY_APPENDPATH:
2643
3072
value = urlutils.join(value, self.extra_path)
3073
# expand section local options right now (since POLICY_APPENDPATH
3074
# will never add options references, it's ok to expand after it).
3076
for is_ref, chunk in iter_option_refs(value):
3078
chunks.append(chunk)
3081
if ref in self.locals:
3082
chunks.append(self.locals[ref])
3084
chunks.append(chunk)
3085
value = ''.join(chunks)
2761
3223
except KeyError:
2762
3224
# Not registered
2764
if (opt is not None and opt.from_unicode is not None
2765
and value is not None):
2766
# If a value exists and the option provides a converter, use it
2768
converted = opt.from_unicode(value)
2769
except (ValueError, TypeError):
2770
# Invalid values are ignored
3226
def expand_and_convert(val):
3227
# This may need to be called twice if the value is None or ends up
3228
# being None during expansion or conversion.
3231
if isinstance(val, basestring):
3232
val = self._expand_options_in_string(val)
3234
trace.warning('Cannot expand "%s":'
3235
' %s does not support option expansion'
3236
% (name, type(val)))
3238
val = opt.convert_from_unicode(val)
3240
value = expand_and_convert(value)
3241
if opt is not None and value is None:
2774
3242
# If the option is registered, it may provide a default value
2776
value = opt.get_default()
2777
if opt is not None and value is None:
2778
3243
value = opt.get_default()
3244
value = expand_and_convert(value)
2779
3245
for hook in ConfigHooks['get']:
2780
3246
hook(self, name, value)
3249
def expand_options(self, string, env=None):
3250
"""Expand option references in the string in the configuration context.
3252
:param string: The string containing option(s) to expand.
3254
:param env: An option dict defining additional configuration options or
3255
overriding existing ones.
3257
:returns: The expanded string.
3259
return self._expand_options_in_string(string, env)
3261
def _expand_options_in_string(self, string, env=None, _refs=None):
3262
"""Expand options in the string in the configuration context.
3264
:param string: The string to be expanded.
3266
:param env: An option dict defining additional configuration options or
3267
overriding existing ones.
3269
:param _refs: Private list (FIFO) containing the options being expanded
3272
:returns: The expanded string.
3275
# Not much to expand there
3278
# What references are currently resolved (to detect loops)
3281
# We need to iterate until no more refs appear ({{foo}} will need two
3282
# iterations for example).
3287
for is_ref, chunk in iter_option_refs(result):
3289
chunks.append(chunk)
3294
raise errors.OptionExpansionLoop(string, _refs)
3296
value = self._expand_option(name, env, _refs)
3298
raise errors.ExpandingUnknownOption(name, string)
3299
chunks.append(value)
3301
result = ''.join(chunks)
3304
def _expand_option(self, name, env, _refs):
3305
if env is not None and name in env:
3306
# Special case, values provided in env takes precedence over
3310
value = self.get(name, expand=False)
3311
value = self._expand_options_in_string(value, env, _refs)
2783
3314
def _get_mutable_section(self):
2784
3315
"""Get the MutableSection for the Stack.
2786
3317
This is where we guarantee that the mutable section is lazily loaded:
2787
3318
this means we won't load the corresponding store before setting a value
2788
3319
or deleting an option. In practice the store will often be loaded but
2789
this allows helps catching some programming errors.
3320
this helps catching some programming errors.
2791
section = self.store.get_mutable_section(self.mutable_section_name)
3322
section = self.store.get_mutable_section(self.mutable_section_id)
2794
3325
def set(self, name, value):
2833
3370
# Force a write to persistent storage
2834
3371
self.store.save()
3373
def remove(self, name):
3376
super(_CompatibleStack, self).remove(name)
3377
# Force a write to persistent storage
2837
3381
class GlobalStack(_CompatibleStack):
3382
"""Global options only stack."""
2839
3384
def __init__(self):
2840
3385
# Get a GlobalStore
2841
3386
gstore = GlobalStore()
2842
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3387
super(GlobalStack, self).__init__(
3388
[self._get_overrides, NameMatcher(gstore, 'DEFAULT').get_sections],
3389
gstore, mutable_section_id='DEFAULT')
2845
3392
class LocationStack(_CompatibleStack):
3393
"""Per-location options falling back to global options stack."""
2847
3395
def __init__(self, location):
2848
3396
"""Make a new stack for a location and global configuration.
2850
3398
:param location: A URL prefix to """
2851
3399
lstore = LocationStore()
3400
if location.startswith('file://'):
3401
location = urlutils.local_path_from_url(location)
2852
3402
matcher = LocationMatcher(lstore, location)
2853
3403
gstore = GlobalStore()
2854
3404
super(LocationStack, self).__init__(
2855
[matcher.get_sections, gstore.get_sections], lstore)
3405
[self._get_overrides,
3406
matcher.get_sections, NameMatcher(gstore, 'DEFAULT').get_sections],
3407
lstore, mutable_section_id=location)
2857
3410
class BranchStack(_CompatibleStack):
3411
"""Per-location options falling back to branch then global options stack."""
2859
3413
def __init__(self, branch):
2860
bstore = BranchStore(branch)
3414
bstore = branch._get_config_store()
2861
3415
lstore = LocationStore()
2862
3416
matcher = LocationMatcher(lstore, branch.base)
2863
3417
gstore = GlobalStore()
2864
3418
super(BranchStack, self).__init__(
2865
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2867
self.branch = branch
3419
[self._get_overrides,
3420
matcher.get_sections, bstore.get_sections,
3421
NameMatcher(gstore, 'DEFAULT').get_sections],
3423
self.branch = branch
3426
class RemoteControlStack(_CompatibleStack):
3427
"""Remote control-only options stack."""
3429
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3430
# with the stack used for remote bzr dirs. RemoteControlStack only uses
3431
# control.conf and is used only for stack options.
3433
def __init__(self, bzrdir):
3434
cstore = bzrdir._get_config_store()
3435
super(RemoteControlStack, self).__init__(
3436
[cstore.get_sections],
3438
self.bzrdir = bzrdir
3441
class RemoteBranchStack(_CompatibleStack):
3442
"""Remote branch-only options stack."""
3444
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3445
# with the stack used for remote branches. RemoteBranchStack only uses
3446
# branch.conf and is used only for the stack options.
3448
def __init__(self, branch):
3449
bstore = branch._get_config_store()
3450
super(RemoteBranchStack, self).__init__(
3451
[bstore.get_sections],
3453
self.branch = branch
3455
# Use a an empty dict to initialize an empty configobj avoiding all
3456
# parsing and encoding checks
3457
_quoting_config = configobj.ConfigObj(
3458
{}, encoding='utf-8', interpolation=False)
2870
3460
class cmd_config(commands.Command):
2871
3461
__doc__ = """Display, set or remove a configuration option.
2932
3523
# Set the option value
2933
3524
self._set_config_option(name, value, directory, scope)
2935
def _get_configs(self, directory, scope=None):
2936
"""Iterate the configurations specified by ``directory`` and ``scope``.
3526
def _get_stack(self, directory, scope=None):
3527
"""Get the configuration stack specified by ``directory`` and ``scope``.
2938
3529
:param directory: Where the configurations are derived from.
2940
3531
:param scope: A specific config to start from.
3533
# FIXME: scope should allow access to plugin-specific stacks (even
3534
# reduced to the plugin-specific store), related to
3535
# http://pad.lv/788991 -- vila 2011-11-15
2942
3536
if scope is not None:
2943
3537
if scope == 'bazaar':
2944
yield GlobalConfig()
3538
return GlobalStack()
2945
3539
elif scope == 'locations':
2946
yield LocationConfig(directory)
3540
return LocationStack(directory)
2947
3541
elif scope == 'branch':
2948
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2950
yield br.get_config()
3543
controldir.ControlDir.open_containing_tree_or_branch(
3545
return br.get_config_stack()
3546
raise errors.NoSuchConfig(scope)
2953
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2955
yield br.get_config()
3550
controldir.ControlDir.open_containing_tree_or_branch(
3552
return br.get_config_stack()
2956
3553
except errors.NotBranchError:
2957
yield LocationConfig(directory)
2958
yield GlobalConfig()
3554
return LocationStack(directory)
2960
3556
def _show_value(self, name, directory, scope):
2962
for c in self._get_configs(directory, scope):
2965
for (oname, value, section, conf_id, parser) in c._get_options():
2967
# Display only the first value and exit
2969
# FIXME: We need to use get_user_option to take policies
2970
# into account and we need to make sure the option exists
2971
# too (hence the two for loops), this needs a better API
2973
value = c.get_user_option(name)
2974
# Quote the value appropriately
2975
value = parser._quote(value)
2976
self.outf.write('%s\n' % (value,))
3557
conf = self._get_stack(directory, scope)
3558
value = conf.get(name, expand=True)
3559
if value is not None:
3560
# Quote the value appropriately
3561
value = _quoting_config._quote(value)
3562
self.outf.write('%s\n' % (value,))
2980
3564
raise errors.NoSuchConfigOption(name)
2982
3566
def _show_matching_options(self, name, directory, scope):
2985
3569
# avoid the delay introduced by the lazy regexp. But, we still do
2986
3570
# want the nicer errors raised by lazy_regex.
2987
3571
name._compile_and_collapse()
2989
3573
cur_section = None
2990
for c in self._get_configs(directory, scope):
2991
for (oname, value, section, conf_id, parser) in c._get_options():
2992
if name.search(oname):
2993
if cur_conf_id != conf_id:
2994
# Explain where the options are defined
2995
self.outf.write('%s:\n' % (conf_id,))
2996
cur_conf_id = conf_id
2998
if (section not in (None, 'DEFAULT')
2999
and cur_section != section):
3000
# Display the section if it's not the default (or only)
3002
self.outf.write(' [%s]\n' % (section,))
3003
cur_section = section
3004
self.outf.write(' %s = %s\n' % (oname, value))
3574
conf = self._get_stack(directory, scope)
3575
for sections in conf.sections_def:
3576
for store, section in sections():
3577
for oname in section.iter_option_names():
3578
if name.search(oname):
3579
if cur_store_id != store.id:
3580
# Explain where the options are defined
3581
self.outf.write('%s:\n' % (store.id,))
3582
cur_store_id = store.id
3584
if (section.id not in (None, 'DEFAULT')
3585
and cur_section != section.id):
3586
# Display the section if it's not the default (or
3588
self.outf.write(' [%s]\n' % (section.id,))
3589
cur_section = section.id
3590
value = section.get(oname, expand=False)
3591
value = _quoting_config._quote(value)
3592
self.outf.write(' %s = %s\n' % (oname, value))
3006
3594
def _set_config_option(self, name, value, directory, scope):
3007
for conf in self._get_configs(directory, scope):
3008
conf.set_user_option(name, value)
3011
raise errors.NoSuchConfig(scope)
3595
conf = self._get_stack(directory, scope)
3596
conf.set(name, value)
3013
3598
def _remove_config_option(self, name, directory, scope):
3014
3599
if name is None:
3015
3600
raise errors.BzrCommandError(
3016
3601
'--remove expects an option to remove.')
3018
for conf in self._get_configs(directory, scope):
3019
for (section_name, section, conf_id) in conf._get_sections():
3020
if scope is not None and conf_id != scope:
3021
# Not the right configuration file
3024
if conf_id != conf.config_id():
3025
conf = self._get_configs(directory, conf_id).next()
3026
# We use the first section in the first config where the
3027
# option is defined to remove it
3028
conf.remove_user_option(name, section_name)
3033
raise errors.NoSuchConfig(scope)
3602
conf = self._get_stack(directory, scope)
3035
3606
raise errors.NoSuchConfigOption(name)
3037
3609
# Test registries
3039
3611
# We need adapters that can build a Store or a Stack in a test context. Test