178
229
def _get_signing_policy(self):
179
230
"""Template method to override signature creation policy."""
234
def expand_options(self, string, env=None):
235
"""Expand option references in the string in the configuration context.
237
:param string: The string containing option to expand.
239
:param env: An option dict defining additional configuration options or
240
overriding existing ones.
242
:returns: The expanded string.
244
return self._expand_options_in_string(string, env)
246
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
247
"""Expand options in a list of strings in the configuration context.
249
:param slist: A list of strings.
251
:param env: An option dict defining additional configuration options or
252
overriding existing ones.
254
:param _ref_stack: Private list containing the options being
255
expanded to detect loops.
257
:returns: The flatten list of expanded strings.
259
# expand options in each value separately flattening lists
262
value = self._expand_options_in_string(s, env, _ref_stack)
263
if isinstance(value, list):
269
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
270
"""Expand options in the string in the configuration context.
272
:param string: The string to be expanded.
274
:param env: An option dict defining additional configuration options or
275
overriding existing ones.
277
:param _ref_stack: Private list containing the options being
278
expanded to detect loops.
280
:returns: The expanded string.
283
# Not much to expand there
285
if _ref_stack is None:
286
# What references are currently resolved (to detect loops)
288
if self.option_ref_re is None:
289
# We want to match the most embedded reference first (i.e. for
290
# '{{foo}}' we will get '{foo}',
291
# for '{bar{baz}}' we will get '{baz}'
292
self.option_ref_re = re.compile('({[^{}]+})')
294
# We need to iterate until no more refs appear ({{foo}} will need two
295
# iterations for example).
297
raw_chunks = self.option_ref_re.split(result)
298
if len(raw_chunks) == 1:
299
# Shorcut the trivial case: no refs
303
# Split will isolate refs so that every other chunk is a ref
305
for chunk in raw_chunks:
308
# Keep only non-empty strings (or we get bogus empty
309
# slots when a list value is involved).
314
if name in _ref_stack:
315
raise errors.OptionExpansionLoop(string, _ref_stack)
316
_ref_stack.append(name)
317
value = self._expand_option(name, env, _ref_stack)
319
raise errors.ExpandingUnknownOption(name, string)
320
if isinstance(value, list):
328
# Once a list appears as the result of an expansion, all
329
# callers will get a list result. This allows a consistent
330
# behavior even when some options in the expansion chain
331
# defined as strings (no comma in their value) but their
332
# expanded value is a list.
333
return self._expand_options_in_list(chunks, env, _ref_stack)
335
result = ''.join(chunks)
338
def _expand_option(self, name, env, _ref_stack):
339
if env is not None and name in env:
340
# Special case, values provided in env takes precedence over
344
# FIXME: This is a limited implementation, what we really need is a
345
# way to query the bzr config for the value of an option,
346
# respecting the scope rules (That is, once we implement fallback
347
# configs, getting the option value should restart from the top
348
# config, not the current one) -- vila 20101222
349
value = self.get_user_option(name, expand=False)
350
if isinstance(value, list):
351
value = self._expand_options_in_list(value, env, _ref_stack)
353
value = self._expand_options_in_string(value, env, _ref_stack)
181
356
def _get_user_option(self, option_name):
182
357
"""Template method to provide a user option."""
185
def get_user_option(self, option_name):
186
"""Get a generic option - no special process, no default."""
187
return self._get_user_option(option_name)
189
def get_user_option_as_bool(self, option_name):
190
"""Get a generic option as a boolean - no special process, no default.
360
def get_user_option(self, option_name, expand=None):
361
"""Get a generic option - no special process, no default.
363
:param option_name: The queried option.
365
:param expand: Whether options references should be expanded.
367
:returns: The value of the option.
370
expand = _get_expand_default_value()
371
value = self._get_user_option(option_name)
373
if isinstance(value, list):
374
value = self._expand_options_in_list(value)
375
elif isinstance(value, dict):
376
trace.warning('Cannot expand "%s":'
377
' Dicts do not support option expansion'
380
value = self._expand_options_in_string(value)
381
for hook in OldConfigHooks['get']:
382
hook(self, option_name, value)
385
def get_user_option_as_bool(self, option_name, expand=None, default=None):
386
"""Get a generic option as a boolean.
388
:param expand: Allow expanding references to other config values.
389
:param default: Default value if nothing is configured
192
390
:return None if the option doesn't exist or its value can't be
193
391
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
393
s = self.get_user_option(option_name, expand=expand)
197
395
# The option doesn't exist
199
397
val = ui.bool_from_string(s)
201
399
# The value can't be interpreted as a boolean
580
def get_merge_tools(self):
582
for (oname, value, section, conf_id, parser) in self._get_options():
583
if oname.startswith('bzr.mergetool.'):
584
tool_name = oname[len('bzr.mergetool.'):]
585
tools[tool_name] = value
586
trace.mutter('loaded merge tools: %r' % tools)
589
def find_merge_tool(self, name):
590
# We fake a defaults mechanism here by checking if the given name can
591
# be found in the known_merge_tools if it's not found in the config.
592
# This should be done through the proposed config defaults mechanism
593
# when it becomes available in the future.
594
command_line = (self.get_user_option('bzr.mergetool.%s' % name,
596
or mergetools.known_merge_tools.get(name, None))
600
class _ConfigHooks(hooks.Hooks):
601
"""A dict mapping hook names and a list of callables for configs.
605
"""Create the default hooks.
607
These are all empty initially, because by default nothing should get
610
super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
611
self.add_hook('load',
612
'Invoked when a config store is loaded.'
613
' The signature is (store).',
615
self.add_hook('save',
616
'Invoked when a config store is saved.'
617
' The signature is (store).',
619
# The hooks for config options
621
'Invoked when a config option is read.'
622
' The signature is (stack, name, value).',
625
'Invoked when a config option is set.'
626
' The signature is (stack, name, value).',
628
self.add_hook('remove',
629
'Invoked when a config option is removed.'
630
' The signature is (stack, name).',
632
ConfigHooks = _ConfigHooks()
635
class _OldConfigHooks(hooks.Hooks):
636
"""A dict mapping hook names and a list of callables for configs.
640
"""Create the default hooks.
642
These are all empty initially, because by default nothing should get
645
super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
646
self.add_hook('load',
647
'Invoked when a config store is loaded.'
648
' The signature is (config).',
650
self.add_hook('save',
651
'Invoked when a config store is saved.'
652
' The signature is (config).',
654
# The hooks for config options
656
'Invoked when a config option is read.'
657
' The signature is (config, name, value).',
660
'Invoked when a config option is set.'
661
' The signature is (config, name, value).',
663
self.add_hook('remove',
664
'Invoked when a config option is removed.'
665
' The signature is (config, name).',
667
OldConfigHooks = _OldConfigHooks()
350
670
class IniBasedConfig(Config):
351
671
"""A configuration policy that draws from ini files."""
353
def __init__(self, get_filename):
673
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
675
"""Base class for configuration files using an ini-like syntax.
677
:param file_name: The configuration file path.
354
679
super(IniBasedConfig, self).__init__()
355
self._get_filename = get_filename
680
self.file_name = file_name
681
if symbol_versioning.deprecated_passed(get_filename):
682
symbol_versioning.warn(
683
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
684
' Use file_name instead.',
687
if get_filename is not None:
688
self.file_name = get_filename()
690
self.file_name = file_name
356
692
self._parser = None
358
def _get_parser(self, file=None):
695
def from_string(cls, str_or_unicode, file_name=None, save=False):
696
"""Create a config object from a string.
698
:param str_or_unicode: A string representing the file content. This will
701
:param file_name: The configuration file path.
703
:param _save: Whether the file should be saved upon creation.
705
conf = cls(file_name=file_name)
706
conf._create_from_string(str_or_unicode, save)
709
def _create_from_string(self, str_or_unicode, save):
710
self._content = StringIO(str_or_unicode.encode('utf-8'))
711
# Some tests use in-memory configs, some other always need the config
712
# file to exist on disk.
714
self._write_config_file()
716
def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
359
717
if self._parser is not None:
360
718
return self._parser
362
input = self._get_filename()
719
if symbol_versioning.deprecated_passed(file):
720
symbol_versioning.warn(
721
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
722
' Use IniBasedConfig(_content=xxx) instead.',
725
if self._content is not None:
726
co_input = self._content
727
elif self.file_name is None:
728
raise AssertionError('We have no content to create the config')
730
co_input = self.file_name
366
self._parser = ConfigObj(input, encoding='utf-8')
732
self._parser = ConfigObj(co_input, encoding='utf-8')
367
733
except configobj.ConfigObjError, e:
368
734
raise errors.ParseConfigError(e.errors, e.config.filename)
735
except UnicodeDecodeError:
736
raise errors.ConfigContentError(self.file_name)
737
# Make sure self.reload() will use the right file name
738
self._parser.filename = self.file_name
739
for hook in OldConfigHooks['load']:
369
741
return self._parser
744
"""Reload the config file from disk."""
745
if self.file_name is None:
746
raise AssertionError('We need a file name to reload the config')
747
if self._parser is not None:
748
self._parser.reload()
749
for hook in ConfigHooks['load']:
371
752
def _get_matching_sections(self):
372
753
"""Return an ordered list of (section_name, extra_path) pairs.
1508
2216
configobj[name] = value
1510
2218
configobj.setdefault(section, {})[name] = value
2219
for hook in OldConfigHooks['set']:
2220
hook(self, name, value)
2221
self._set_configobj(configobj)
2223
def remove_option(self, option_name, section_name=None):
2224
configobj = self._get_configobj()
2225
if section_name is None:
2226
del configobj[option_name]
2228
del configobj[section_name][option_name]
2229
for hook in OldConfigHooks['remove']:
2230
hook(self, option_name)
1511
2231
self._set_configobj(configobj)
1513
2233
def _get_config_file(self):
1515
return StringIO(self._transport.get_bytes(self._filename))
2235
f = StringIO(self._transport.get_bytes(self._filename))
2236
for hook in OldConfigHooks['load']:
1516
2239
except errors.NoSuchFile:
1517
2240
return StringIO()
2242
def _external_url(self):
2243
return urlutils.join(self._transport.external_url(), self._filename)
1519
2245
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2246
f = self._get_config_file()
2249
conf = ConfigObj(f, encoding='utf-8')
2250
except configobj.ConfigObjError, e:
2251
raise errors.ParseConfigError(e.errors, self._external_url())
2252
except UnicodeDecodeError:
2253
raise errors.ConfigContentError(self._external_url())
1522
2258
def _set_configobj(self, configobj):
1523
2259
out_file = StringIO()
1524
2260
configobj.write(out_file)
1525
2261
out_file.seek(0)
1526
2262
self._transport.put_file(self._filename, out_file)
2263
for hook in OldConfigHooks['save']:
2267
class Option(object):
2268
"""An option definition.
2270
The option *values* are stored in config files and found in sections.
2272
Here we define various properties about the option itself, its default
2273
value, how to convert it from stores, what to do when invalid values are
2274
encoutered, in which config files it can be stored.
2277
def __init__(self, name, default=None, help=None, from_unicode=None,
2279
"""Build an option definition.
2281
:param name: the name used to refer to the option.
2283
:param default: the default value to use when none exist in the config
2286
:param help: a doc string to explain the option to the user.
2288
:param from_unicode: a callable to convert the unicode string
2289
representing the option value in a store. This is not called for
2292
:param invalid: the action to be taken when an invalid value is
2293
encountered in a store. This is called only when from_unicode is
2294
invoked to convert a string and returns None or raise ValueError or
2295
TypeError. Accepted values are: None (ignore invalid values),
2296
'warning' (emit a warning), 'error' (emit an error message and
2300
self.default = default
2302
self.from_unicode = from_unicode
2303
if invalid and invalid not in ('warning', 'error'):
2304
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2305
self.invalid = invalid
2307
def get_default(self):
2310
# Predefined converters to get proper values from store
2312
def bool_from_store(unicode_str):
2313
return ui.bool_from_string(unicode_str)
2316
def int_from_store(unicode_str):
2317
return int(unicode_str)
2320
def list_from_store(unicode_str):
2321
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2322
if isinstance(unicode_str, (str, unicode)):
2324
# A single value, most probably the user forgot (or didn't care to
2325
# add) the final ','
2328
# The empty string, convert to empty list
2331
# We rely on ConfigObj providing us with a list already
2336
class OptionRegistry(registry.Registry):
2337
"""Register config options by their name.
2339
This overrides ``registry.Registry`` to simplify registration by acquiring
2340
some information from the option object itself.
2343
def register(self, option):
2344
"""Register a new option to its name.
2346
:param option: The option to register. Its name is used as the key.
2348
super(OptionRegistry, self).register(option.name, option,
2351
def register_lazy(self, key, module_name, member_name):
2352
"""Register a new option to be loaded on request.
2354
:param key: This is the key to use to request the option later. Since
2355
the registration is lazy, it should be provided and match the
2358
:param module_name: The python path to the module. Such as 'os.path'.
2360
:param member_name: The member of the module to return. If empty or
2361
None, get() will return the module itself.
2363
super(OptionRegistry, self).register_lazy(key,
2364
module_name, member_name)
2366
def get_help(self, key=None):
2367
"""Get the help text associated with the given key"""
2368
option = self.get(key)
2369
the_help = option.help
2370
if callable(the_help):
2371
return the_help(self, key)
2375
option_registry = OptionRegistry()
2378
# Registered options in lexicographical order
2380
option_registry.register(
2381
Option('dirstate.fdatasync', default=True, from_unicode=bool_from_store,
2383
Flush dirstate changes onto physical disk?
2385
If true (default), working tree metadata changes are flushed through the
2386
OS buffers to physical disk. This is somewhat slower, but means data
2387
should not be lost if the machine crashes. See also repository.fdatasync.
2389
option_registry.register(
2390
Option('default_format', default='2a',
2391
help='Format used when creating branches.'))
2392
option_registry.register(
2394
help='The command called to launch an editor to enter a message.'))
2395
option_registry.register(
2397
help='Language to translate messages into.'))
2398
option_registry.register(
2399
Option('output_encoding',
2400
help= 'Unicode encoding for output'
2401
' (terminal encoding if not specified).'))
2402
option_registry.register(
2403
Option('repository.fdatasync', default=True, from_unicode=bool_from_store,
2405
Flush repository changes onto physical disk?
2407
If true (default), repository changes are flushed through the OS buffers
2408
to physical disk. This is somewhat slower, but means data should not be
2409
lost if the machine crashes. See also dirstate.fdatasync.
2413
class Section(object):
2414
"""A section defines a dict of option name => value.
2416
This is merely a read-only dict which can add some knowledge about the
2417
options. It is *not* a python dict object though and doesn't try to mimic
2421
def __init__(self, section_id, options):
2422
self.id = section_id
2423
# We re-use the dict-like object received
2424
self.options = options
2426
def get(self, name, default=None):
2427
return self.options.get(name, default)
2430
# Mostly for debugging use
2431
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2434
_NewlyCreatedOption = object()
2435
"""Was the option created during the MutableSection lifetime"""
2438
class MutableSection(Section):
2439
"""A section allowing changes and keeping track of the original values."""
2441
def __init__(self, section_id, options):
2442
super(MutableSection, self).__init__(section_id, options)
2445
def set(self, name, value):
2446
if name not in self.options:
2447
# This is a new option
2448
self.orig[name] = _NewlyCreatedOption
2449
elif name not in self.orig:
2450
self.orig[name] = self.get(name, None)
2451
self.options[name] = value
2453
def remove(self, name):
2454
if name not in self.orig:
2455
self.orig[name] = self.get(name, None)
2456
del self.options[name]
2459
class Store(object):
2460
"""Abstract interface to persistent storage for configuration options."""
2462
readonly_section_class = Section
2463
mutable_section_class = MutableSection
2465
def is_loaded(self):
2466
"""Returns True if the Store has been loaded.
2468
This is used to implement lazy loading and ensure the persistent
2469
storage is queried only when needed.
2471
raise NotImplementedError(self.is_loaded)
2474
"""Loads the Store from persistent storage."""
2475
raise NotImplementedError(self.load)
2477
def _load_from_string(self, bytes):
2478
"""Create a store from a string in configobj syntax.
2480
:param bytes: A string representing the file content.
2482
raise NotImplementedError(self._load_from_string)
2485
"""Unloads the Store.
2487
This should make is_loaded() return False. This is used when the caller
2488
knows that the persistent storage has changed or may have change since
2491
raise NotImplementedError(self.unload)
2494
"""Saves the Store to persistent storage."""
2495
raise NotImplementedError(self.save)
2497
def external_url(self):
2498
raise NotImplementedError(self.external_url)
2500
def get_sections(self):
2501
"""Returns an ordered iterable of existing sections.
2503
:returns: An iterable of (name, dict).
2505
raise NotImplementedError(self.get_sections)
2507
def get_mutable_section(self, section_name=None):
2508
"""Returns the specified mutable section.
2510
:param section_name: The section identifier
2512
raise NotImplementedError(self.get_mutable_section)
2515
# Mostly for debugging use
2516
return "<config.%s(%s)>" % (self.__class__.__name__,
2517
self.external_url())
2520
class IniFileStore(Store):
2521
"""A config Store using ConfigObj for storage.
2523
:ivar transport: The transport object where the config file is located.
2525
:ivar file_name: The config file basename in the transport directory.
2527
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2528
serialize/deserialize the config file.
2531
def __init__(self, transport, file_name):
2532
"""A config Store using ConfigObj for storage.
2534
:param transport: The transport object where the config file is located.
2536
:param file_name: The config file basename in the transport directory.
2538
super(IniFileStore, self).__init__()
2539
self.transport = transport
2540
self.file_name = file_name
2541
self._config_obj = None
2543
def is_loaded(self):
2544
return self._config_obj != None
2547
self._config_obj = None
2550
"""Load the store from the associated file."""
2551
if self.is_loaded():
2553
content = self.transport.get_bytes(self.file_name)
2554
self._load_from_string(content)
2555
for hook in ConfigHooks['load']:
2558
def _load_from_string(self, bytes):
2559
"""Create a config store from a string.
2561
:param bytes: A string representing the file content.
2563
if self.is_loaded():
2564
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2565
co_input = StringIO(bytes)
2567
# The config files are always stored utf8-encoded
2568
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2569
except configobj.ConfigObjError, e:
2570
self._config_obj = None
2571
raise errors.ParseConfigError(e.errors, self.external_url())
2572
except UnicodeDecodeError:
2573
raise errors.ConfigContentError(self.external_url())
2576
if not self.is_loaded():
2580
self._config_obj.write(out)
2581
self.transport.put_bytes(self.file_name, out.getvalue())
2582
for hook in ConfigHooks['save']:
2585
def external_url(self):
2586
# FIXME: external_url should really accepts an optional relpath
2587
# parameter (bug #750169) :-/ -- vila 2011-04-04
2588
# The following will do in the interim but maybe we don't want to
2589
# expose a path here but rather a config ID and its associated
2590
# object </hand wawe>.
2591
return urlutils.join(self.transport.external_url(), self.file_name)
2593
def get_sections(self):
2594
"""Get the configobj section in the file order.
2596
:returns: An iterable of (name, dict).
2598
# We need a loaded store
2601
except errors.NoSuchFile:
2602
# If the file doesn't exist, there is no sections
2604
cobj = self._config_obj
2606
yield self.readonly_section_class(None, cobj)
2607
for section_name in cobj.sections:
2608
yield self.readonly_section_class(section_name, cobj[section_name])
2610
def get_mutable_section(self, section_name=None):
2611
# We need a loaded store
2614
except errors.NoSuchFile:
2615
# The file doesn't exist, let's pretend it was empty
2616
self._load_from_string('')
2617
if section_name is None:
2618
section = self._config_obj
2620
section = self._config_obj.setdefault(section_name, {})
2621
return self.mutable_section_class(section_name, section)
2624
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2625
# unlockable stores for use with objects that can already ensure the locking
2626
# (think branches). If different stores (not based on ConfigObj) are created,
2627
# they may face the same issue.
2630
class LockableIniFileStore(IniFileStore):
2631
"""A ConfigObjStore using locks on save to ensure store integrity."""
2633
def __init__(self, transport, file_name, lock_dir_name=None):
2634
"""A config Store using ConfigObj for storage.
2636
:param transport: The transport object where the config file is located.
2638
:param file_name: The config file basename in the transport directory.
2640
if lock_dir_name is None:
2641
lock_dir_name = 'lock'
2642
self.lock_dir_name = lock_dir_name
2643
super(LockableIniFileStore, self).__init__(transport, file_name)
2644
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2646
def lock_write(self, token=None):
2647
"""Takes a write lock in the directory containing the config file.
2649
If the directory doesn't exist it is created.
2651
# FIXME: This doesn't check the ownership of the created directories as
2652
# ensure_config_dir_exists does. It should if the transport is local
2653
# -- vila 2011-04-06
2654
self.transport.create_prefix()
2655
return self._lock.lock_write(token)
2660
def break_lock(self):
2661
self._lock.break_lock()
2665
# We need to be able to override the undecorated implementation
2666
self.save_without_locking()
2668
def save_without_locking(self):
2669
super(LockableIniFileStore, self).save()
2672
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2673
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2674
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2676
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2677
# functions or a registry will make it easier and clearer for tests, focusing
2678
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2679
# on a poolie's remark)
2680
class GlobalStore(LockableIniFileStore):
2682
def __init__(self, possible_transports=None):
2683
t = transport.get_transport_from_path(
2684
config_dir(), possible_transports=possible_transports)
2685
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2688
class LocationStore(LockableIniFileStore):
2690
def __init__(self, possible_transports=None):
2691
t = transport.get_transport_from_path(
2692
config_dir(), possible_transports=possible_transports)
2693
super(LocationStore, self).__init__(t, 'locations.conf')
2696
class BranchStore(IniFileStore):
2698
def __init__(self, branch):
2699
super(BranchStore, self).__init__(branch.control_transport,
2701
self.branch = branch
2703
def lock_write(self, token=None):
2704
return self.branch.lock_write(token)
2707
return self.branch.unlock()
2711
# We need to be able to override the undecorated implementation
2712
self.save_without_locking()
2714
def save_without_locking(self):
2715
super(BranchStore, self).save()
2718
class SectionMatcher(object):
2719
"""Select sections into a given Store.
2721
This intended to be used to postpone getting an iterable of sections from a
2725
def __init__(self, store):
2728
def get_sections(self):
2729
# This is where we require loading the store so we can see all defined
2731
sections = self.store.get_sections()
2732
# Walk the revisions in the order provided
2737
def match(self, secion):
2738
raise NotImplementedError(self.match)
2741
class LocationSection(Section):
2743
def __init__(self, section, length, extra_path):
2744
super(LocationSection, self).__init__(section.id, section.options)
2745
self.length = length
2746
self.extra_path = extra_path
2748
def get(self, name, default=None):
2749
value = super(LocationSection, self).get(name, default)
2750
if value is not None:
2751
policy_name = self.get(name + ':policy', None)
2752
policy = _policy_value.get(policy_name, POLICY_NONE)
2753
if policy == POLICY_APPENDPATH:
2754
value = urlutils.join(value, self.extra_path)
2758
class LocationMatcher(SectionMatcher):
2760
def __init__(self, store, location):
2761
super(LocationMatcher, self).__init__(store)
2762
if location.startswith('file://'):
2763
location = urlutils.local_path_from_url(location)
2764
self.location = location
2766
def _get_matching_sections(self):
2767
"""Get all sections matching ``location``."""
2768
# We slightly diverge from LocalConfig here by allowing the no-name
2769
# section as the most generic one and the lower priority.
2770
no_name_section = None
2772
# Filter out the no_name_section so _iter_for_location_by_parts can be
2773
# used (it assumes all sections have a name).
2774
for section in self.store.get_sections():
2775
if section.id is None:
2776
no_name_section = section
2778
sections.append(section)
2779
# Unfortunately _iter_for_location_by_parts deals with section names so
2780
# we have to resync.
2781
filtered_sections = _iter_for_location_by_parts(
2782
[s.id for s in sections], self.location)
2783
iter_sections = iter(sections)
2784
matching_sections = []
2785
if no_name_section is not None:
2786
matching_sections.append(
2787
LocationSection(no_name_section, 0, self.location))
2788
for section_id, extra_path, length in filtered_sections:
2789
# a section id is unique for a given store so it's safe to iterate
2791
section = iter_sections.next()
2792
if section_id == section.id:
2793
matching_sections.append(
2794
LocationSection(section, length, extra_path))
2795
return matching_sections
2797
def get_sections(self):
2798
# Override the default implementation as we want to change the order
2799
matching_sections = self._get_matching_sections()
2800
# We want the longest (aka more specific) locations first
2801
sections = sorted(matching_sections,
2802
key=lambda section: (section.length, section.id),
2804
# Sections mentioning 'ignore_parents' restrict the selection
2805
for section in sections:
2806
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2807
ignore = section.get('ignore_parents', None)
2808
if ignore is not None:
2809
ignore = ui.bool_from_string(ignore)
2812
# Finally, we have a valid section
2816
class Stack(object):
2817
"""A stack of configurations where an option can be defined"""
2819
def __init__(self, sections_def, store=None, mutable_section_name=None):
2820
"""Creates a stack of sections with an optional store for changes.
2822
:param sections_def: A list of Section or callables that returns an
2823
iterable of Section. This defines the Sections for the Stack and
2824
can be called repeatedly if needed.
2826
:param store: The optional Store where modifications will be
2827
recorded. If none is specified, no modifications can be done.
2829
:param mutable_section_name: The name of the MutableSection where
2830
changes are recorded. This requires the ``store`` parameter to be
2833
self.sections_def = sections_def
2835
self.mutable_section_name = mutable_section_name
2837
def get(self, name):
2838
"""Return the *first* option value found in the sections.
2840
This is where we guarantee that sections coming from Store are loaded
2841
lazily: the loading is delayed until we need to either check that an
2842
option exists or get its value, which in turn may require to discover
2843
in which sections it can be defined. Both of these (section and option
2844
existence) require loading the store (even partially).
2846
# FIXME: No caching of options nor sections yet -- vila 20110503
2848
# Ensuring lazy loading is achieved by delaying section matching (which
2849
# implies querying the persistent storage) until it can't be avoided
2850
# anymore by using callables to describe (possibly empty) section
2852
for section_or_callable in self.sections_def:
2853
# Each section can expand to multiple ones when a callable is used
2854
if callable(section_or_callable):
2855
sections = section_or_callable()
2857
sections = [section_or_callable]
2858
for section in sections:
2859
value = section.get(name)
2860
if value is not None:
2862
if value is not None:
2864
# If the option is registered, it may provide additional info about
2867
opt = option_registry.get(name)
2871
if (opt is not None and opt.from_unicode is not None
2872
and value is not None):
2873
# If a value exists and the option provides a converter, use it
2875
converted = opt.from_unicode(value)
2876
except (ValueError, TypeError):
2877
# Invalid values are ignored
2879
if converted is None and opt.invalid is not None:
2880
# The conversion failed
2881
if opt.invalid == 'warning':
2882
trace.warning('Value "%s" is not valid for "%s"',
2884
elif opt.invalid == 'error':
2885
raise errors.ConfigOptionValueError(name, value)
2888
# If the option is registered, it may provide a default value
2890
value = opt.get_default()
2891
for hook in ConfigHooks['get']:
2892
hook(self, name, value)
2895
def _get_mutable_section(self):
2896
"""Get the MutableSection for the Stack.
2898
This is where we guarantee that the mutable section is lazily loaded:
2899
this means we won't load the corresponding store before setting a value
2900
or deleting an option. In practice the store will often be loaded but
2901
this allows helps catching some programming errors.
2903
section = self.store.get_mutable_section(self.mutable_section_name)
2906
def set(self, name, value):
2907
"""Set a new value for the option."""
2908
section = self._get_mutable_section()
2909
section.set(name, value)
2910
for hook in ConfigHooks['set']:
2911
hook(self, name, value)
2913
def remove(self, name):
2914
"""Remove an existing option."""
2915
section = self._get_mutable_section()
2916
section.remove(name)
2917
for hook in ConfigHooks['remove']:
2921
# Mostly for debugging use
2922
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2925
class _CompatibleStack(Stack):
2926
"""Place holder for compatibility with previous design.
2928
This is intended to ease the transition from the Config-based design to the
2929
Stack-based design and should not be used nor relied upon by plugins.
2931
One assumption made here is that the daughter classes will all use Stores
2932
derived from LockableIniFileStore).
2934
It implements set() by re-loading the store before applying the
2935
modification and saving it.
2937
The long term plan being to implement a single write by store to save
2938
all modifications, this class should not be used in the interim.
2941
def set(self, name, value):
2944
super(_CompatibleStack, self).set(name, value)
2945
# Force a write to persistent storage
2949
class GlobalStack(_CompatibleStack):
2953
gstore = GlobalStore()
2954
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2957
class LocationStack(_CompatibleStack):
2959
def __init__(self, location):
2960
"""Make a new stack for a location and global configuration.
2962
:param location: A URL prefix to """
2963
lstore = LocationStore()
2964
matcher = LocationMatcher(lstore, location)
2965
gstore = GlobalStore()
2966
super(LocationStack, self).__init__(
2967
[matcher.get_sections, gstore.get_sections], lstore)
2969
class BranchStack(_CompatibleStack):
2971
def __init__(self, branch):
2972
bstore = BranchStore(branch)
2973
lstore = LocationStore()
2974
matcher = LocationMatcher(lstore, branch.base)
2975
gstore = GlobalStore()
2976
super(BranchStack, self).__init__(
2977
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2979
self.branch = branch
2982
class cmd_config(commands.Command):
2983
__doc__ = """Display, set or remove a configuration option.
2985
Display the active value for a given option.
2987
If --all is specified, NAME is interpreted as a regular expression and all
2988
matching options are displayed mentioning their scope. The active value
2989
that bzr will take into account is the first one displayed for each option.
2991
If no NAME is given, --all .* is implied.
2993
Setting a value is achieved by using name=value without spaces. The value
2994
is set in the most relevant scope and can be checked by displaying the
2998
takes_args = ['name?']
3002
# FIXME: This should be a registry option so that plugins can register
3003
# their own config files (or not) -- vila 20101002
3004
commands.Option('scope', help='Reduce the scope to the specified'
3005
' configuration file',
3007
commands.Option('all',
3008
help='Display all the defined values for the matching options.',
3010
commands.Option('remove', help='Remove the option from'
3011
' the configuration file'),
3014
_see_also = ['configuration']
3016
@commands.display_command
3017
def run(self, name=None, all=False, directory=None, scope=None,
3019
if directory is None:
3021
directory = urlutils.normalize_url(directory)
3023
raise errors.BzrError(
3024
'--all and --remove are mutually exclusive.')
3026
# Delete the option in the given scope
3027
self._remove_config_option(name, directory, scope)
3029
# Defaults to all options
3030
self._show_matching_options('.*', directory, scope)
3033
name, value = name.split('=', 1)
3035
# Display the option(s) value(s)
3037
self._show_matching_options(name, directory, scope)
3039
self._show_value(name, directory, scope)
3042
raise errors.BzrError(
3043
'Only one option can be set.')
3044
# Set the option value
3045
self._set_config_option(name, value, directory, scope)
3047
def _get_configs(self, directory, scope=None):
3048
"""Iterate the configurations specified by ``directory`` and ``scope``.
3050
:param directory: Where the configurations are derived from.
3052
:param scope: A specific config to start from.
3054
if scope is not None:
3055
if scope == 'bazaar':
3056
yield GlobalConfig()
3057
elif scope == 'locations':
3058
yield LocationConfig(directory)
3059
elif scope == 'branch':
3060
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3062
yield br.get_config()
3065
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3067
yield br.get_config()
3068
except errors.NotBranchError:
3069
yield LocationConfig(directory)
3070
yield GlobalConfig()
3072
def _show_value(self, name, directory, scope):
3074
for c in self._get_configs(directory, scope):
3077
for (oname, value, section, conf_id, parser) in c._get_options():
3079
# Display only the first value and exit
3081
# FIXME: We need to use get_user_option to take policies
3082
# into account and we need to make sure the option exists
3083
# too (hence the two for loops), this needs a better API
3085
value = c.get_user_option(name)
3086
# Quote the value appropriately
3087
value = parser._quote(value)
3088
self.outf.write('%s\n' % (value,))
3092
raise errors.NoSuchConfigOption(name)
3094
def _show_matching_options(self, name, directory, scope):
3095
name = lazy_regex.lazy_compile(name)
3096
# We want any error in the regexp to be raised *now* so we need to
3097
# avoid the delay introduced by the lazy regexp. But, we still do
3098
# want the nicer errors raised by lazy_regex.
3099
name._compile_and_collapse()
3102
for c in self._get_configs(directory, scope):
3103
for (oname, value, section, conf_id, parser) in c._get_options():
3104
if name.search(oname):
3105
if cur_conf_id != conf_id:
3106
# Explain where the options are defined
3107
self.outf.write('%s:\n' % (conf_id,))
3108
cur_conf_id = conf_id
3110
if (section not in (None, 'DEFAULT')
3111
and cur_section != section):
3112
# Display the section if it's not the default (or only)
3114
self.outf.write(' [%s]\n' % (section,))
3115
cur_section = section
3116
self.outf.write(' %s = %s\n' % (oname, value))
3118
def _set_config_option(self, name, value, directory, scope):
3119
for conf in self._get_configs(directory, scope):
3120
conf.set_user_option(name, value)
3123
raise errors.NoSuchConfig(scope)
3125
def _remove_config_option(self, name, directory, scope):
3127
raise errors.BzrCommandError(
3128
'--remove expects an option to remove.')
3130
for conf in self._get_configs(directory, scope):
3131
for (section_name, section, conf_id) in conf._get_sections():
3132
if scope is not None and conf_id != scope:
3133
# Not the right configuration file
3136
if conf_id != conf.config_id():
3137
conf = self._get_configs(directory, conf_id).next()
3138
# We use the first section in the first config where the
3139
# option is defined to remove it
3140
conf.remove_user_option(name, section_name)
3145
raise errors.NoSuchConfig(scope)
3147
raise errors.NoSuchConfigOption(name)
3151
# We need adapters that can build a Store or a Stack in a test context. Test
3152
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3153
# themselves. The builder will receive a test instance and should return a
3154
# ready-to-use store or stack. Plugins that define new store/stacks can also
3155
# register themselves here to be tested against the tests defined in
3156
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3157
# for the same tests.
3159
# The registered object should be a callable receiving a test instance
3160
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3162
test_store_builder_registry = registry.Registry()
3164
# The registered object should be a callable receiving a test instance
3165
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3167
test_stack_builder_registry = registry.Registry()