55
55
turns on create_signatures.
56
56
create_signatures - this option controls whether bzr will always create
57
57
gpg signatures or not on commits. There is an unused
58
option which in future is expected to work if
58
option which in future is expected to work if
59
59
branch settings require signatures.
60
60
log_format - this option sets the default log format. Possible values are
61
61
long, short, line, or a plugin can register new formats.
197
197
return self[section][name]
200
# FIXME: Until we can guarantee that each config file is loaded once and
201
# only once for a given bzrlib session, we don't want to re-read the file every
202
# time we query for an option so we cache the value (bad ! watch out for tests
203
# needing to restore the proper value). -- vila 20110219
204
_expand_default_value = None
205
def _get_expand_default_value():
206
global _expand_default_value
207
if _expand_default_value is not None:
208
return _expand_default_value
209
conf = GlobalConfig()
210
# Note that we must not use None for the expand value below or we'll run
211
# into infinite recursion. Using False really would be quite silly ;)
212
expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
214
# This is an opt-in feature, you *really* need to clearly say you want
217
_expand_default_value = expand
200
221
class Config(object):
201
222
"""A configuration policy - what username, editor, gpg needs etc."""
207
228
"""Returns a unique ID for the config."""
208
229
raise NotImplementedError(self.config_id)
231
@deprecated_method(deprecated_in((2, 4, 0)))
232
def get_editor(self):
233
"""Get the users pop up editor."""
234
raise NotImplementedError
210
236
def get_change_editor(self, old_tree, new_tree):
211
237
from bzrlib import diff
212
238
cmd = self._get_change_editor()
215
241
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
244
def get_mail_client(self):
245
"""Get a mail client to use"""
246
selected_client = self.get_user_option('mail_client')
247
_registry = mail_client.mail_client_registry
249
mail_client_class = _registry.get(selected_client)
251
raise errors.UnknownMailClient(selected_client)
252
return mail_client_class(self)
218
254
def _get_signature_checking(self):
219
255
"""Template method to override signature checking policy."""
349
385
"""Template method to provide a user option."""
352
def get_user_option(self, option_name, expand=True):
388
def get_user_option(self, option_name, expand=None):
353
389
"""Get a generic option - no special process, no default.
355
391
:param option_name: The queried option.
611
649
for (oname, value, section, conf_id, parser) in self._get_options():
612
650
if oname.startswith('bzr.mergetool.'):
613
651
tool_name = oname[len('bzr.mergetool.'):]
614
tools[tool_name] = self.get_user_option(oname, False)
652
tools[tool_name] = self.get_user_option(oname)
615
653
trace.mutter('loaded merge tools: %r' % tools)
1487
1527
def config_dir():
1488
"""Return per-user configuration directory as unicode string
1528
"""Return per-user configuration directory.
1490
1530
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1491
and Linux. On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1531
and Linux. On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1492
1532
that will be used instead.
1494
1534
TODO: Global option --config-dir to override this.
1496
base = osutils.path_from_environ('BZR_HOME')
1536
base = os.environ.get('BZR_HOME', None)
1497
1537
if sys.platform == 'win32':
1499
base = win32utils.get_appdata_location()
1501
base = win32utils.get_home_location()
1502
# GZ 2012-02-01: Really the two level subdirs only make sense inside
1503
# APPDATA, but hard to move. See bug 348640 for more.
1538
# environ variables on Windows are in user encoding/mbcs. So decode
1540
if base is not None:
1541
base = base.decode('mbcs')
1543
base = win32utils.get_appdata_location_unicode()
1545
base = os.environ.get('HOME', None)
1546
if base is not None:
1547
base = base.decode('mbcs')
1549
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1504
1551
return osutils.pathjoin(base, 'bazaar', '2.0')
1506
xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1508
xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1509
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1510
if osutils.isdir(xdg_dir):
1512
"Using configuration in XDG directory %s." % xdg_dir)
1514
base = osutils._get_home_dir()
1515
return osutils.pathjoin(base, ".bazaar")
1553
if base is not None:
1554
base = base.decode(osutils._fs_enc)
1555
if sys.platform == 'darwin':
1557
# this takes into account $HOME
1558
base = os.path.expanduser("~")
1559
return osutils.pathjoin(base, '.bazaar')
1562
xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1564
xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1565
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1566
if osutils.isdir(xdg_dir):
1568
"Using configuration in XDG directory %s." % xdg_dir)
1570
base = os.path.expanduser("~")
1571
return osutils.pathjoin(base, ".bazaar")
1518
1574
def config_filename():
1555
1611
def xdg_cache_dir():
1556
1612
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1557
1613
# Possibly this should be different on Windows?
1558
e = os.environ.get('XDG_CACHE_HOME', None)
1614
e = os.environ.get('XDG_CACHE_DIR', None)
1562
1618
return os.path.expanduser('~/.cache')
1565
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1621
def _get_default_mail_domain():
1566
1622
"""If possible, return the assumed default email domain.
1568
1624
:returns: string mail domain, or None.
2131
2187
credential_store_registry.default_key = 'plain'
2134
class Base64CredentialStore(CredentialStore):
2135
__doc__ = """Base64 credential store for the authentication.conf file"""
2137
def decode_password(self, credentials):
2138
"""See CredentialStore.decode_password."""
2139
# GZ 2012-07-28: Will raise binascii.Error if password is not base64,
2140
# should probably propogate as something more useful.
2141
return base64.decodestring(credentials['password'])
2143
credential_store_registry.register('base64', Base64CredentialStore,
2144
help=Base64CredentialStore.__doc__)
2147
2190
class BzrDirConfig(object):
2149
2192
def __init__(self, bzrdir):
2156
2199
It may be set to a location, or None.
2158
This policy affects all branches contained by this control dir, except
2159
for those under repositories.
2201
This policy affects all branches contained by this bzrdir, except for
2202
those under repositories.
2161
2204
if self._config is None:
2162
raise errors.BzrError("Cannot set configuration in %s"
2205
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
2164
2206
if value is None:
2165
2207
self._config.set_option('', 'default_stack_on')
2354
2397
raise AssertionError('%r is not supported as a default value'
2356
2399
self.default_from_env = default_from_env
2358
2401
self.from_unicode = from_unicode
2359
2402
self.unquote = unquote
2360
2403
if invalid and invalid not in ('warning', 'error'):
2361
2404
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2362
2405
self.invalid = invalid
2368
2407
def convert_from_unicode(self, store, unicode_value):
2369
2408
if self.unquote and store is not None and unicode_value is not None:
2370
2409
unicode_value = store.unquote(unicode_value)
2411
2450
value = self.default()
2412
2451
if not isinstance(value, unicode):
2413
2452
raise AssertionError(
2414
"Callable default value for '%s' should be unicode"
2453
'Callable default values should be unicode')
2417
2455
value = self.default
2420
def get_help_topic(self):
2423
2458
def get_help_text(self, additional_see_also=None, plain=True):
2424
2459
result = self.help
2425
2460
from bzrlib import help_topics
2471
2506
return float(unicode_str)
2474
# Use an empty dict to initialize an empty configobj avoiding all parsing and
2509
# Use a an empty dict to initialize an empty configobj avoiding all
2510
# parsing and encoding checks
2476
2511
_list_converter_config = configobj.ConfigObj(
2477
2512
{}, encoding='utf-8', list_values=True, interpolation=False)
2517
class RegistryOption(Option):
2518
"""Option for a choice from a registry."""
2520
def __init__(self, name, registry, default_from_env=None,
2521
help=None, invalid=None):
2522
"""A registry based Option definition.
2524
This overrides the base class so the conversion from a unicode string
2525
can take quoting into account.
2527
super(RegistryOption, self).__init__(
2528
name, default=lambda: unicode(registry.default_key),
2529
default_from_env=default_from_env,
2530
from_unicode=self.from_unicode, help=help,
2531
invalid=invalid, unquote=False)
2532
self.registry = registry
2534
def from_unicode(self, unicode_str):
2535
if not isinstance(unicode_str, basestring):
2538
return self.registry.get(unicode_str)
2541
"Invalid value %s for %s."
2542
"See help for a list of possible values." % (unicode_str,
2547
ret = [self._help, "\n\nThe following values are supported:\n"]
2548
for key in self.registry.keys():
2549
ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
2553
_option_ref_re = lazy_regex.lazy_compile('({[^\d\W](?:\.\w|-\w|\w)*})')
2554
"""Describes an expandable option reference.
2556
We want to match the most embedded reference first.
2558
I.e. for '{{foo}}' we will get '{foo}',
2559
for '{bar{baz}}' we will get '{baz}'
2562
def iter_option_refs(string):
2563
# Split isolate refs so every other chunk is a ref
2565
for chunk in _option_ref_re.split(string):
2570
2552
class OptionRegistry(registry.Registry):
2571
2553
"""Register config options by their name.
2574
2556
some information from the option object itself.
2577
def _check_option_name(self, option_name):
2578
"""Ensures an option name is valid.
2580
:param option_name: The name to validate.
2582
if _option_ref_re.match('{%s}' % option_name) is None:
2583
raise errors.IllegalOptionName(option_name)
2585
2559
def register(self, option):
2586
2560
"""Register a new option to its name.
2588
2562
:param option: The option to register. Its name is used as the key.
2590
self._check_option_name(option.name)
2591
2564
super(OptionRegistry, self).register(option.name, option,
2592
2565
help=option.help)
2673
2645
Whether revisions associated with tags should be fetched.
2675
option_registry.register_lazy(
2676
'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2677
2647
option_registry.register(
2678
2648
Option('bzr.workingtree.worth_saving_limit', default=10,
2679
2649
from_unicode=int_from_store, invalid='warning',
2687
2657
a file has been touched.
2689
2659
option_registry.register(
2690
Option('bugtracker', default=None,
2692
Default bug tracker to use.
2694
This bug tracker will be used for example when marking bugs
2695
as fixed using ``bzr commit --fixes``, if no explicit
2696
bug tracker was specified.
2698
option_registry.register(
2699
2660
Option('check_signatures', default=CHECK_IF_POSSIBLE,
2700
2661
from_unicode=signature_policy_from_unicode,
2803
2764
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2804
2765
may be provided by plugins.
2806
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
2808
2767
option_registry.register(
2809
2768
Option('output_encoding',
2810
2769
help= 'Unicode encoding for output'
2909
2866
option_registry.register(
2910
2867
Option('submit_to',
2911
2868
help='''Where submissions from this branch are mailed to.'''))
2912
option_registry.register(
2913
ListOption('suppress_warnings',
2915
help="List of warning classes to suppress."))
2916
option_registry.register(
2917
Option('validate_signatures_in_log', default=False,
2918
from_unicode=bool_from_store, invalid='warning',
2919
help='''Whether to validate signatures in bzr log.'''))
2920
option_registry.register_lazy('ssl.ca_certs',
2921
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2923
option_registry.register_lazy('ssl.cert_reqs',
2924
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2927
2871
class Section(object):
3096
3039
# get_mutable_section() call below.
3098
3041
# Apply the changes from the preserved dirty sections
3099
for section_id, dirty in dirty_sections.iteritems():
3100
clean = self.get_mutable_section(section_id)
3042
for dirty in dirty_sections:
3043
clean = self.get_mutable_section(dirty.id)
3101
3044
clean.apply_changes(dirty, self)
3102
3045
# Everything is clean now
3103
self.dirty_sections = {}
3046
self.dirty_sections = []
3105
3048
def save_changes(self):
3106
3049
"""Saves the Store to persistent storage if changes occurred.
3281
3229
except errors.NoSuchFile:
3282
3230
# The file doesn't exist, let's pretend it was empty
3283
3231
self._load_from_string('')
3284
if section_id in self.dirty_sections:
3285
# We already created a mutable section for this id
3286
return self.dirty_sections[section_id]
3287
3232
if section_id is None:
3288
3233
section = self._config_obj
3290
3235
section = self._config_obj.setdefault(section_id, {})
3291
3236
mutable_section = self.mutable_section_class(section_id, section)
3292
3237
# All mutable sections can become dirty
3293
self.dirty_sections[section_id] = mutable_section
3238
self.dirty_sections.append(mutable_section)
3294
3239
return mutable_section
3296
3241
def quote(self, value):
3308
3253
value = self._config_obj._unquote(value)
3311
def external_url(self):
3312
# Since an IniFileStore can be used without a file (at least in tests),
3313
# it's better to provide something than raising a NotImplementedError.
3314
# All daughter classes are supposed to provide an implementation
3316
return 'In-Process Store, no URL'
3319
3257
class TransportIniFileStore(IniFileStore):
3320
3258
"""IniFileStore that loads files from a transport.
3322
:ivar transport: The transport object where the config file is located.
3324
:ivar file_name: The config file basename in the transport directory.
3327
3261
def __init__(self, transport, file_name):
3448
3370
self.branch = branch
3449
3371
self.id = 'branch'
3373
# FIXME: This is very handy to detect which callers forgot to lock the
3374
# branch but break many bt.test_config tests. Either these tests should
3375
# parametrized differently or better ways to achieve the branch locking
3376
# should be found that don't require this.
3377
def xget_mutable_section(self, section_id=None):
3378
if self.branch.peek_lock_mode() != 'w':
3379
from bzrlib import debug ; debug.set_trace()
3380
raise AssertionError('The branch for %s is not write-locked'
3381
% self.external_url())
3382
return super(BranchStore, self).get_mutable_section(section_id)
3452
3385
class ControlStore(LockableIniFileStore):
3500
3433
class LocationSection(Section):
3502
def __init__(self, section, extra_path, branch_name=None):
3435
def __init__(self, section, length, extra_path):
3503
3436
super(LocationSection, self).__init__(section.id, section.options)
3437
self.length = length
3504
3438
self.extra_path = extra_path
3505
if branch_name is None:
3507
3439
self.locals = {'relpath': extra_path,
3508
'basename': urlutils.basename(extra_path),
3509
'branchname': branch_name}
3440
'basename': urlutils.basename(extra_path)}
3511
3442
def get(self, name, default=None, expand=True):
3512
3443
value = super(LocationSection, self).get(name, default)
3534
class StartingPathMatcher(SectionMatcher):
3535
"""Select sections for a given location respecting the Store order."""
3537
# FIXME: Both local paths and urls can be used for section names as well as
3538
# ``location`` to stay consistent with ``LocationMatcher`` which itself
3539
# inherited the fuzziness from the previous ``LocationConfig``
3540
# implementation. We probably need to revisit which encoding is allowed for
3541
# both ``location`` and section names and how we normalize
3542
# them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
3543
# related too. -- vila 2012-01-04
3545
def __init__(self, store, location):
3546
super(StartingPathMatcher, self).__init__(store)
3547
if location.startswith('file://'):
3548
location = urlutils.local_path_from_url(location)
3549
self.location = location
3551
def get_sections(self):
3552
"""Get all sections matching ``location`` in the store.
3554
The most generic sections are described first in the store, then more
3555
specific ones can be provided for reduced scopes.
3557
The returned section are therefore returned in the reversed order so
3558
the most specific ones can be found first.
3560
location_parts = self.location.rstrip('/').split('/')
3562
# Later sections are more specific, they should be returned first
3563
for _, section in reversed(list(store.get_sections())):
3564
if section.id is None:
3565
# The no-name section is always included if present
3566
yield store, LocationSection(section, self.location)
3568
section_path = section.id
3569
if section_path.startswith('file://'):
3570
# the location is already a local path or URL, convert the
3571
# section id to the same format
3572
section_path = urlutils.local_path_from_url(section_path)
3573
if (self.location.startswith(section_path)
3574
or fnmatch.fnmatch(self.location, section_path)):
3575
section_parts = section_path.rstrip('/').split('/')
3576
extra_path = '/'.join(location_parts[len(section_parts):])
3577
yield store, LocationSection(section, extra_path)
3580
3465
class LocationMatcher(SectionMatcher):
3582
3467
def __init__(self, store, location):
3583
3468
super(LocationMatcher, self).__init__(store)
3584
url, params = urlutils.split_segment_parameters(location)
3585
3469
if location.startswith('file://'):
3586
3470
location = urlutils.local_path_from_url(location)
3587
3471
self.location = location
3588
branch_name = params.get('branch')
3589
if branch_name is None:
3590
self.branch_name = urlutils.basename(self.location)
3592
self.branch_name = urlutils.unescape(branch_name)
3594
3473
def _get_matching_sections(self):
3595
3474
"""Get all sections matching ``location``."""
3612
3491
matching_sections = []
3613
3492
if no_name_section is not None:
3614
3493
matching_sections.append(
3615
(0, LocationSection(no_name_section, self.location)))
3494
LocationSection(no_name_section, 0, self.location))
3616
3495
for section_id, extra_path, length in filtered_sections:
3617
3496
# a section id is unique for a given store so it's safe to take the
3618
3497
# first matching section while iterating. Also, all filtered
3622
3501
section = iter_all_sections.next()
3623
3502
if section_id == section.id:
3624
section = LocationSection(section, extra_path,
3626
matching_sections.append((length, section))
3503
matching_sections.append(
3504
LocationSection(section, length, extra_path))
3628
3506
return matching_sections
3632
3510
matching_sections = self._get_matching_sections()
3633
3511
# We want the longest (aka more specific) locations first
3634
3512
sections = sorted(matching_sections,
3635
key=lambda (length, section): (length, section.id),
3513
key=lambda section: (section.length, section.id),
3637
3515
# Sections mentioning 'ignore_parents' restrict the selection
3638
for _, section in sections:
3516
for section in sections:
3639
3517
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3640
3518
ignore = section.get('ignore_parents', None)
3641
3519
if ignore is not None:
3646
3524
yield self.store, section
3649
# FIXME: _shared_stores should be an attribute of a library state once a
3650
# library_state object is always available.
3652
_shared_stores_at_exit_installed = False
3527
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
3528
"""Describes an expandable option reference.
3530
We want to match the most embedded reference first.
3532
I.e. for '{{foo}}' we will get '{foo}',
3533
for '{bar{baz}}' we will get '{baz}'
3536
def iter_option_refs(string):
3537
# Split isolate refs so every other chunk is a ref
3539
for chunk in _option_ref_re.split(string):
3654
3544
class Stack(object):
3655
3545
"""A stack of configurations where an option can be defined"""
3672
3562
self.store = store
3673
3563
self.mutable_section_id = mutable_section_id
3675
def iter_sections(self):
3676
"""Iterate all the defined sections."""
3677
# Ensuring lazy loading is achieved by delaying section matching (which
3678
# implies querying the persistent storage) until it can't be avoided
3679
# anymore by using callables to describe (possibly empty) section
3681
for sections in self.sections_def:
3682
for store, section in sections():
3683
yield store, section
3685
def get(self, name, expand=True, convert=True):
3565
def get(self, name, expand=None):
3686
3566
"""Return the *first* option value found in the sections.
3688
3568
This is where we guarantee that sections coming from Store are loaded
3696
3576
:param expand: Whether options references should be expanded.
3698
:param convert: Whether the option value should be converted from
3699
unicode (do nothing for non-registered options).
3701
3578
:returns: The value of the option.
3703
3580
# FIXME: No caching of options nor sections yet -- vila 20110503
3582
expand = _get_expand_default_value()
3705
3584
found_store = None # Where the option value has been found
3706
3585
# If the option is registered, it may provide additional info about
3734
3613
value = opt.get_override()
3735
3614
value = expand_and_convert(value)
3736
3615
if value is None:
3737
for store, section in self.iter_sections():
3738
value = section.get(name)
3616
# Ensuring lazy loading is achieved by delaying section matching
3617
# (which implies querying the persistent storage) until it can't be
3618
# avoided anymore by using callables to describe (possibly empty)
3620
for sections in self.sections_def:
3621
for store, section in sections():
3622
value = section.get(name)
3623
if value is not None:
3739
3626
if value is not None:
3742
3628
value = expand_and_convert(value)
3743
3629
if opt is not None and value is None:
3844
3730
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3846
3732
def _get_overrides(self):
3847
# FIXME: Hack around library_state.initialize never called
3733
# Hack around library_state.initialize never called
3848
3734
if bzrlib.global_state is not None:
3849
3735
return bzrlib.global_state.cmdline_overrides.get_sections()
3852
def get_shared_store(self, store, state=None):
3853
"""Get a known shared store.
3855
Store urls uniquely identify them and are used to ensure a single copy
3856
is shared across all users.
3858
:param store: The store known to the caller.
3860
:param state: The library state where the known stores are kept.
3862
:returns: The store received if it's not a known one, an already known
3866
state = bzrlib.global_state
3868
global _shared_stores_at_exit_installed
3869
stores = _shared_stores
3870
def save_config_changes():
3871
for k, store in stores.iteritems():
3872
store.save_changes()
3873
if not _shared_stores_at_exit_installed:
3874
# FIXME: Ugly hack waiting for library_state to always be
3875
# available. -- vila 20120731
3877
atexit.register(save_config_changes)
3878
_shared_stores_at_exit_installed = True
3880
stores = state.config_stores
3881
url = store.external_url()
3889
3739
class MemoryStack(Stack):
3890
3740
"""A configuration stack defined from a string.
3956
3806
def __init__(self):
3957
gstore = self.get_shared_store(GlobalStore())
3807
gstore = GlobalStore()
3958
3808
super(GlobalStack, self).__init__(
3959
3809
[self._get_overrides,
3960
3810
NameMatcher(gstore, 'DEFAULT').get_sections],
3961
3811
gstore, mutable_section_id='DEFAULT')
3964
class LocationStack(Stack):
3814
class LocationStack(_CompatibleStack):
3965
3815
"""Per-location options falling back to global options stack.
3983
3833
"""Make a new stack for a location and global configuration.
3985
3835
:param location: A URL prefix to """
3986
lstore = self.get_shared_store(LocationStore())
3836
lstore = LocationStore()
3987
3837
if location.startswith('file://'):
3988
3838
location = urlutils.local_path_from_url(location)
3989
gstore = self.get_shared_store(GlobalStore())
3839
gstore = GlobalStore()
3990
3840
super(LocationStack, self).__init__(
3991
3841
[self._get_overrides,
3992
3842
LocationMatcher(lstore, location).get_sections,
4016
3866
def __init__(self, branch):
4017
lstore = self.get_shared_store(LocationStore())
3867
lstore = LocationStore()
4018
3868
bstore = branch._get_config_store()
4019
gstore = self.get_shared_store(GlobalStore())
3869
gstore = GlobalStore()
4020
3870
super(BranchStack, self).__init__(
4021
3871
[self._get_overrides,
4022
3872
LocationMatcher(lstore, branch.base).get_sections,
4034
3884
@needs_write_lock
4035
3885
def set(self, name, value):
4036
3886
super(BranchStack, self).set(name, value)
4037
# Unlocking the branch will trigger a store.save_changes() so the last
4038
# unlock saves all the changes.
3887
# Force a write to persistent storage
3888
self.store.save_changes()
4040
3890
@needs_write_lock
4041
3891
def remove(self, name):
4042
3892
super(BranchStack, self).remove(name)
4043
# Unlocking the branch will trigger a store.save_changes() so the last
4044
# unlock saves all the changes.
4047
class RemoteControlStack(Stack):
3893
# Force a write to persistent storage
3894
self.store.save_changes()
3897
class RemoteControlStack(_CompatibleStack):
4048
3898
"""Remote control-only options stack."""
4050
3900
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
4092
3942
self.store.save_changes()
3945
# Use a an empty dict to initialize an empty configobj avoiding all
3946
# parsing and encoding checks
3947
_quoting_config = configobj.ConfigObj(
3948
{}, encoding='utf-8', interpolation=False, list_values=True)
4095
3950
class cmd_config(commands.Command):
4096
3951
__doc__ = """Display, set or remove a configuration option.
4098
Display the active value for option NAME.
3953
Display the active value for a given option.
4100
3955
If --all is specified, NAME is interpreted as a regular expression and all
4101
matching options are displayed mentioning their scope and without resolving
4102
option references in the value). The active value that bzr will take into
4103
account is the first one displayed for each option.
4105
If NAME is not given, --all .* is implied (all options are displayed for the
4108
Setting a value is achieved by using NAME=value without spaces. The value
3956
matching options are displayed mentioning their scope. The active value
3957
that bzr will take into account is the first one displayed for each option.
3959
If no NAME is given, --all .* is implied.
3961
Setting a value is achieved by using name=value without spaces. The value
4109
3962
is set in the most relevant scope and can be checked by displaying the
4112
Removing a value is achieved by using --remove NAME.
4115
3966
takes_args = ['name?']
4200
4050
except errors.NotBranchError:
4201
4051
return LocationStack(directory)
4203
def _quote_multiline(self, value):
4205
value = '"""' + value + '"""'
4208
4053
def _show_value(self, name, directory, scope):
4209
4054
conf = self._get_stack(directory, scope)
4210
value = conf.get(name, expand=True, convert=False)
4055
value = conf.get(name, expand=True)
4211
4056
if value is not None:
4212
4057
# Quote the value appropriately
4213
value = self._quote_multiline(value)
4058
value = _quoting_config._quote(value)
4214
4059
self.outf.write('%s\n' % (value,))
4216
4061
raise errors.NoSuchConfigOption(name)
4224
4069
cur_store_id = None
4225
4070
cur_section = None
4226
4071
conf = self._get_stack(directory, scope)
4227
for store, section in conf.iter_sections():
4228
for oname in section.iter_option_names():
4229
if name.search(oname):
4230
if cur_store_id != store.id:
4231
# Explain where the options are defined
4232
self.outf.write('%s:\n' % (store.id,))
4233
cur_store_id = store.id
4235
if (section.id is not None and cur_section != section.id):
4236
# Display the section id as it appears in the store
4237
# (None doesn't appear by definition)
4238
self.outf.write(' [%s]\n' % (section.id,))
4239
cur_section = section.id
4240
value = section.get(oname, expand=False)
4241
# Quote the value appropriately
4242
value = self._quote_multiline(value)
4243
self.outf.write(' %s = %s\n' % (oname, value))
4072
for sections in conf.sections_def:
4073
for store, section in sections():
4074
for oname in section.iter_option_names():
4075
if name.search(oname):
4076
if cur_store_id != store.id:
4077
# Explain where the options are defined
4078
self.outf.write('%s:\n' % (store.id,))
4079
cur_store_id = store.id
4081
if (section.id is not None
4082
and cur_section != section.id):
4083
# Display the section id as it appears in the store
4084
# (None doesn't appear by definition)
4085
self.outf.write(' [%s]\n' % (section.id,))
4086
cur_section = section.id
4087
value = section.get(oname, expand=False)
4088
# Since we don't use the stack, we need to restore a
4091
opt = option_registry.get(oname)
4092
value = opt.convert_from_unicode(store, value)
4094
value = store.unquote(value)
4095
value = _quoting_config._quote(value)
4096
self.outf.write(' %s = %s\n' % (oname, value))
4245
4098
def _set_config_option(self, name, value, directory, scope):
4246
4099
conf = self._get_stack(directory, scope, write_access=True)
4247
4100
conf.set(name, value)
4248
# Explicitly save the changes
4249
conf.store.save_changes()
4251
4102
def _remove_config_option(self, name, directory, scope):
4252
4103
if name is None: