182
214
def _get_signing_policy(self):
183
215
"""Template method to override signature creation policy."""
219
def expand_options(self, string, env=None):
220
"""Expand option references in the string in the configuration context.
222
:param string: The string containing option to expand.
224
:param env: An option dict defining additional configuration options or
225
overriding existing ones.
227
:returns: The expanded string.
229
return self._expand_options_in_string(string, env)
231
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
232
"""Expand options in a list of strings in the configuration context.
234
:param slist: A list of strings.
236
:param env: An option dict defining additional configuration options or
237
overriding existing ones.
239
:param _ref_stack: Private list containing the options being
240
expanded to detect loops.
242
:returns: The flatten list of expanded strings.
244
# expand options in each value separately flattening lists
247
value = self._expand_options_in_string(s, env, _ref_stack)
248
if isinstance(value, list):
254
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
255
"""Expand options in the string in the configuration context.
257
:param string: The string to be expanded.
259
:param env: An option dict defining additional configuration options or
260
overriding existing ones.
262
:param _ref_stack: Private list containing the options being
263
expanded to detect loops.
265
:returns: The expanded string.
268
# Not much to expand there
270
if _ref_stack is None:
271
# What references are currently resolved (to detect loops)
273
if self.option_ref_re is None:
274
# We want to match the most embedded reference first (i.e. for
275
# '{{foo}}' we will get '{foo}',
276
# for '{bar{baz}}' we will get '{baz}'
277
self.option_ref_re = re.compile('({[^{}]+})')
279
# We need to iterate until no more refs appear ({{foo}} will need two
280
# iterations for example).
282
raw_chunks = self.option_ref_re.split(result)
283
if len(raw_chunks) == 1:
284
# Shorcut the trivial case: no refs
288
# Split will isolate refs so that every other chunk is a ref
290
for chunk in raw_chunks:
293
# Keep only non-empty strings (or we get bogus empty
294
# slots when a list value is involved).
299
if name in _ref_stack:
300
raise errors.OptionExpansionLoop(string, _ref_stack)
301
_ref_stack.append(name)
302
value = self._expand_option(name, env, _ref_stack)
304
raise errors.ExpandingUnknownOption(name, string)
305
if isinstance(value, list):
313
# Once a list appears as the result of an expansion, all
314
# callers will get a list result. This allows a consistent
315
# behavior even when some options in the expansion chain
316
# defined as strings (no comma in their value) but their
317
# expanded value is a list.
318
return self._expand_options_in_list(chunks, env, _ref_stack)
320
result = ''.join(chunks)
323
def _expand_option(self, name, env, _ref_stack):
324
if env is not None and name in env:
325
# Special case, values provided in env takes precedence over
329
# FIXME: This is a limited implementation, what we really need is a
330
# way to query the bzr config for the value of an option,
331
# respecting the scope rules (That is, once we implement fallback
332
# configs, getting the option value should restart from the top
333
# config, not the current one) -- vila 20101222
334
value = self.get_user_option(name, expand=False)
335
if isinstance(value, list):
336
value = self._expand_options_in_list(value, env, _ref_stack)
338
value = self._expand_options_in_string(value, env, _ref_stack)
185
341
def _get_user_option(self, option_name):
186
342
"""Template method to provide a user option."""
189
def get_user_option(self, option_name):
190
"""Get a generic option - no special process, no default."""
191
return self._get_user_option(option_name)
193
def get_user_option_as_bool(self, option_name):
345
def get_user_option(self, option_name, expand=None):
346
"""Get a generic option - no special process, no default.
348
:param option_name: The queried option.
350
:param expand: Whether options references should be expanded.
352
:returns: The value of the option.
355
expand = _get_expand_default_value()
356
value = self._get_user_option(option_name)
358
if isinstance(value, list):
359
value = self._expand_options_in_list(value)
360
elif isinstance(value, dict):
361
trace.warning('Cannot expand "%s":'
362
' Dicts do not support option expansion'
365
value = self._expand_options_in_string(value)
368
def get_user_option_as_bool(self, option_name, expand=None):
194
369
"""Get a generic option as a boolean - no special process, no default.
196
371
:return None if the option doesn't exist or its value can't be
197
372
interpreted as a boolean. Returns True or False otherwise.
199
s = self._get_user_option(option_name)
374
s = self.get_user_option(option_name, expand=expand)
201
376
# The option doesn't exist
1598
2092
configobj.write(out_file)
1599
2093
out_file.seek(0)
1600
2094
self._transport.put_file(self._filename, out_file)
2097
class Section(object):
2098
"""A section defines a dict of options.
2100
This is merely a read-only dict which can add some knowledge about the
2101
options. It is *not* a python dict object though and doesn't try to mimic
2105
def __init__(self, section_id, options):
2106
self.id = section_id
2107
# We re-use the dict-like object received
2108
self.options = options
2110
def get(self, name, default=None):
2111
return self.options.get(name, default)
2114
# Mostly for debugging use
2115
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2118
_NewlyCreatedOption = object()
2119
"""Was the option created during the MutableSection lifetime"""
2122
class MutableSection(Section):
2123
"""A section allowing changes and keeping track of the original values."""
2125
def __init__(self, section_id, options):
2126
super(MutableSection, self).__init__(section_id, options)
2129
def set(self, name, value):
2130
if name not in self.options:
2131
# This is a new option
2132
self.orig[name] = _NewlyCreatedOption
2133
elif name not in self.orig:
2134
self.orig[name] = self.get(name, None)
2135
self.options[name] = value
2137
def remove(self, name):
2138
if name not in self.orig:
2139
self.orig[name] = self.get(name, None)
2140
del self.options[name]
2143
class Store(object):
2144
"""Abstract interface to persistent storage for configuration options."""
2146
readonly_section_class = Section
2147
mutable_section_class = MutableSection
2149
def is_loaded(self):
2150
"""Returns True if the Store has been loaded.
2152
This is used to implement lazy loading and ensure the persistent
2153
storage is queried only when needed.
2155
raise NotImplementedError(self.is_loaded)
2158
"""Loads the Store from persistent storage."""
2159
raise NotImplementedError(self.load)
2161
def _load_from_string(self, str_or_unicode):
2162
"""Create a store from a string in configobj syntax.
2164
:param str_or_unicode: A string representing the file content. This will
2165
be encoded to suit store needs internally.
2167
This is for tests and should not be used in production unless a
2168
convincing use case can be demonstrated :)
2170
raise NotImplementedError(self._load_from_string)
2173
"""Saves the Store to persistent storage."""
2174
raise NotImplementedError(self.save)
2176
def external_url(self):
2177
raise NotImplementedError(self.external_url)
2179
def get_sections(self):
2180
"""Returns an ordered iterable of existing sections.
2182
:returns: An iterable of (name, dict).
2184
raise NotImplementedError(self.get_sections)
2186
def get_mutable_section(self, section_name=None):
2187
"""Returns the specified mutable section.
2189
:param section_name: The section identifier
2191
raise NotImplementedError(self.get_mutable_section)
2194
# Mostly for debugging use
2195
return "<config.%s(%s)>" % (self.__class__.__name__,
2196
self.external_url())
2199
class IniFileStore(Store):
2200
"""A config Store using ConfigObj for storage.
2202
:ivar transport: The transport object where the config file is located.
2204
:ivar file_name: The config file basename in the transport directory.
2206
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2207
serialize/deserialize the config file.
2210
def __init__(self, transport, file_name):
2211
"""A config Store using ConfigObj for storage.
2213
:param transport: The transport object where the config file is located.
2215
:param file_name: The config file basename in the transport directory.
2217
super(IniFileStore, self).__init__()
2218
self.transport = transport
2219
self.file_name = file_name
2220
self._config_obj = None
2222
def is_loaded(self):
2223
return self._config_obj != None
2226
"""Load the store from the associated file."""
2227
if self.is_loaded():
2229
content = self.transport.get_bytes(self.file_name)
2230
self._load_from_string(content)
2232
def _load_from_string(self, str_or_unicode):
2233
"""Create a config store from a string.
2235
:param str_or_unicode: A string representing the file content. This will
2236
be utf-8 encoded internally.
2238
This is for tests and should not be used in production unless a
2239
convincing use case can be demonstrated :)
2241
if self.is_loaded():
2242
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2243
co_input = StringIO(str_or_unicode.encode('utf-8'))
2245
# The config files are always stored utf8-encoded
2246
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2247
except configobj.ConfigObjError, e:
2248
self._config_obj = None
2249
raise errors.ParseConfigError(e.errors, self.external_url())
2252
if not self.is_loaded():
2256
self._config_obj.write(out)
2257
self.transport.put_bytes(self.file_name, out.getvalue())
2259
def external_url(self):
2260
# FIXME: external_url should really accepts an optional relpath
2261
# parameter (bug #750169) :-/ -- vila 2011-04-04
2262
# The following will do in the interim but maybe we don't want to
2263
# expose a path here but rather a config ID and its associated
2264
# object </hand wawe>.
2265
return urlutils.join(self.transport.external_url(), self.file_name)
2267
def get_sections(self):
2268
"""Get the configobj section in the file order.
2270
:returns: An iterable of (name, dict).
2272
# We need a loaded store
2274
cobj = self._config_obj
2276
yield self.readonly_section_class(None, cobj)
2277
for section_name in cobj.sections:
2278
yield self.readonly_section_class(section_name, cobj[section_name])
2280
def get_mutable_section(self, section_name=None):
2281
# We need a loaded store
2284
except errors.NoSuchFile:
2285
# The file doesn't exist, let's pretend it was empty
2286
self._load_from_string('')
2287
if section_name is None:
2288
section = self._config_obj
2290
section = self._config_obj.setdefault(section_name, {})
2291
return self.mutable_section_class(section_name, section)
2294
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2295
# unlockable stores for use with objects that can already ensure the locking
2296
# (think branches). If different stores (not based on ConfigObj) are created,
2297
# they may face the same issue.
2300
class LockableIniFileStore(IniFileStore):
2301
"""A ConfigObjStore using locks on save to ensure store integrity."""
2303
def __init__(self, transport, file_name, lock_dir_name=None):
2304
"""A config Store using ConfigObj for storage.
2306
:param transport: The transport object where the config file is located.
2308
:param file_name: The config file basename in the transport directory.
2310
if lock_dir_name is None:
2311
lock_dir_name = 'lock'
2312
self.lock_dir_name = lock_dir_name
2313
super(LockableIniFileStore, self).__init__(transport, file_name)
2314
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2316
def lock_write(self, token=None):
2317
"""Takes a write lock in the directory containing the config file.
2319
If the directory doesn't exist it is created.
2321
# FIXME: This doesn't check the ownership of the created directories as
2322
# ensure_config_dir_exists does. It should if the transport is local
2323
# -- vila 2011-04-06
2324
self.transport.create_prefix()
2325
return self._lock.lock_write(token)
2330
def break_lock(self):
2331
self._lock.break_lock()
2335
super(LockableIniFileStore, self).save()
2338
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2339
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2340
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2342
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2343
# functions or a registry will make it easier and clearer for tests, focusing
2344
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2345
# on a poolie's remark)
2346
class GlobalStore(LockableIniFileStore):
2348
def __init__(self, possible_transports=None):
2349
t = transport.get_transport(config_dir(),
2350
possible_transports=possible_transports)
2351
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2354
class LocationStore(LockableIniFileStore):
2356
def __init__(self, possible_transports=None):
2357
t = transport.get_transport(config_dir(),
2358
possible_transports=possible_transports)
2359
super(LocationStore, self).__init__(t, 'locations.conf')
2362
class BranchStore(IniFileStore):
2364
def __init__(self, branch):
2365
super(BranchStore, self).__init__(branch.control_transport,
2368
class SectionMatcher(object):
2369
"""Select sections into a given Store.
2371
This intended to be used to postpone getting an iterable of sections from a
2375
def __init__(self, store):
2378
def get_sections(self):
2379
# This is where we require loading the store so we can see all defined
2381
sections = self.store.get_sections()
2382
# Walk the revisions in the order provided
2387
def match(self, secion):
2388
raise NotImplementedError(self.match)
2391
class LocationSection(Section):
2393
def __init__(self, section, length, extra_path):
2394
super(LocationSection, self).__init__(section.id, section.options)
2395
self.length = length
2396
self.extra_path = extra_path
2398
def get(self, name, default=None):
2399
value = super(LocationSection, self).get(name, default)
2400
if value is not None:
2401
policy_name = self.get(name + ':policy', None)
2402
policy = _policy_value.get(policy_name, POLICY_NONE)
2403
if policy == POLICY_APPENDPATH:
2404
value = urlutils.join(value, self.extra_path)
2408
class LocationMatcher(SectionMatcher):
2410
def __init__(self, store, location):
2411
super(LocationMatcher, self).__init__(store)
2412
self.location = location
2414
def get_sections(self):
2415
# Override the default implementation as we want to change the order
2417
# The following is a bit hackish but ensures compatibility with
2418
# LocationConfig by reusing the same code
2419
sections = list(self.store.get_sections())
2420
filtered_sections = _iter_for_location_by_parts(
2421
[s.id for s in sections], self.location)
2422
iter_sections = iter(sections)
2423
matching_sections = []
2424
for section_id, extra_path, length in filtered_sections:
2425
# a section id is unique for a given store so it's safe to iterate
2427
section = iter_sections.next()
2428
if section_id == section.id:
2429
matching_sections.append(
2430
LocationSection(section, length, extra_path))
2431
# We want the longest (aka more specific) locations first
2432
sections = sorted(matching_sections,
2433
key=lambda section: (section.length, section.id),
2435
# Sections mentioning 'ignore_parents' restrict the selection
2436
for section in sections:
2437
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2438
ignore = section.get('ignore_parents', None)
2439
if ignore is not None:
2440
ignore = ui.bool_from_string(ignore)
2443
# Finally, we have a valid section
2447
class Stack(object):
2448
"""A stack of configurations where an option can be defined"""
2450
def __init__(self, sections_def, store=None, mutable_section_name=None):
2451
"""Creates a stack of sections with an optional store for changes.
2453
:param sections_def: A list of Section or callables that returns an
2454
iterable of Section. This defines the Sections for the Stack and
2455
can be called repeatedly if needed.
2457
:param store: The optional Store where modifications will be
2458
recorded. If none is specified, no modifications can be done.
2460
:param mutable_section_name: The name of the MutableSection where
2461
changes are recorded. This requires the ``store`` parameter to be
2464
self.sections_def = sections_def
2466
self.mutable_section_name = mutable_section_name
2468
def get(self, name):
2469
"""Return the *first* option value found in the sections.
2471
This is where we guarantee that sections coming from Store are loaded
2472
lazily: the loading is delayed until we need to either check that an
2473
option exists or get its value, which in turn may require to discover
2474
in which sections it can be defined. Both of these (section and option
2475
existence) require loading the store (even partially).
2477
# FIXME: No caching of options nor sections yet -- vila 20110503
2479
# Ensuring lazy loading is achieved by delaying section matching until
2480
# it can be avoided anymore by using callables to describe (possibly
2481
# empty) section lists.
2482
for section_or_callable in self.sections_def:
2483
# Each section can expand to multiple ones when a callable is used
2484
if callable(section_or_callable):
2485
sections = section_or_callable()
2487
sections = [section_or_callable]
2488
for section in sections:
2489
value = section.get(name)
2490
if value is not None:
2492
# No definition was found
2495
def _get_mutable_section(self):
2496
"""Get the MutableSection for the Stack.
2498
This is where we guarantee that the mutable section is lazily loaded:
2499
this means we won't load the corresponding store before setting a value
2500
or deleting an option. In practice the store will often be loaded but
2501
this allows catching some programming errors.
2503
section = self.store.get_mutable_section(self.mutable_section_name)
2506
def set(self, name, value):
2507
"""Set a new value for the option."""
2508
section = self._get_mutable_section()
2509
section.set(name, value)
2511
def remove(self, name):
2512
"""Remove an existing option."""
2513
section = self._get_mutable_section()
2514
section.remove(name)
2517
# Mostly for debugging use
2518
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2521
class cmd_config(commands.Command):
2522
__doc__ = """Display, set or remove a configuration option.
2524
Display the active value for a given option.
2526
If --all is specified, NAME is interpreted as a regular expression and all
2527
matching options are displayed mentioning their scope. The active value
2528
that bzr will take into account is the first one displayed for each option.
2530
If no NAME is given, --all .* is implied.
2532
Setting a value is achieved by using name=value without spaces. The value
2533
is set in the most relevant scope and can be checked by displaying the
2537
takes_args = ['name?']
2541
# FIXME: This should be a registry option so that plugins can register
2542
# their own config files (or not) -- vila 20101002
2543
commands.Option('scope', help='Reduce the scope to the specified'
2544
' configuration file',
2546
commands.Option('all',
2547
help='Display all the defined values for the matching options.',
2549
commands.Option('remove', help='Remove the option from'
2550
' the configuration file'),
2553
@commands.display_command
2554
def run(self, name=None, all=False, directory=None, scope=None,
2556
if directory is None:
2558
directory = urlutils.normalize_url(directory)
2560
raise errors.BzrError(
2561
'--all and --remove are mutually exclusive.')
2563
# Delete the option in the given scope
2564
self._remove_config_option(name, directory, scope)
2566
# Defaults to all options
2567
self._show_matching_options('.*', directory, scope)
2570
name, value = name.split('=', 1)
2572
# Display the option(s) value(s)
2574
self._show_matching_options(name, directory, scope)
2576
self._show_value(name, directory, scope)
2579
raise errors.BzrError(
2580
'Only one option can be set.')
2581
# Set the option value
2582
self._set_config_option(name, value, directory, scope)
2584
def _get_configs(self, directory, scope=None):
2585
"""Iterate the configurations specified by ``directory`` and ``scope``.
2587
:param directory: Where the configurations are derived from.
2589
:param scope: A specific config to start from.
2591
if scope is not None:
2592
if scope == 'bazaar':
2593
yield GlobalConfig()
2594
elif scope == 'locations':
2595
yield LocationConfig(directory)
2596
elif scope == 'branch':
2597
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2599
yield br.get_config()
2602
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2604
yield br.get_config()
2605
except errors.NotBranchError:
2606
yield LocationConfig(directory)
2607
yield GlobalConfig()
2609
def _show_value(self, name, directory, scope):
2611
for c in self._get_configs(directory, scope):
2614
for (oname, value, section, conf_id, parser) in c._get_options():
2616
# Display only the first value and exit
2618
# FIXME: We need to use get_user_option to take policies
2619
# into account and we need to make sure the option exists
2620
# too (hence the two for loops), this needs a better API
2622
value = c.get_user_option(name)
2623
# Quote the value appropriately
2624
value = parser._quote(value)
2625
self.outf.write('%s\n' % (value,))
2629
raise errors.NoSuchConfigOption(name)
2631
def _show_matching_options(self, name, directory, scope):
2632
name = re.compile(name)
2633
# We want any error in the regexp to be raised *now* so we need to
2634
# avoid the delay introduced by the lazy regexp.
2635
name._compile_and_collapse()
2638
for c in self._get_configs(directory, scope):
2639
for (oname, value, section, conf_id, parser) in c._get_options():
2640
if name.search(oname):
2641
if cur_conf_id != conf_id:
2642
# Explain where the options are defined
2643
self.outf.write('%s:\n' % (conf_id,))
2644
cur_conf_id = conf_id
2646
if (section not in (None, 'DEFAULT')
2647
and cur_section != section):
2648
# Display the section if it's not the default (or only)
2650
self.outf.write(' [%s]\n' % (section,))
2651
cur_section = section
2652
self.outf.write(' %s = %s\n' % (oname, value))
2654
def _set_config_option(self, name, value, directory, scope):
2655
for conf in self._get_configs(directory, scope):
2656
conf.set_user_option(name, value)
2659
raise errors.NoSuchConfig(scope)
2661
def _remove_config_option(self, name, directory, scope):
2663
raise errors.BzrCommandError(
2664
'--remove expects an option to remove.')
2666
for conf in self._get_configs(directory, scope):
2667
for (section_name, section, conf_id) in conf._get_sections():
2668
if scope is not None and conf_id != scope:
2669
# Not the right configuration file
2672
if conf_id != conf.config_id():
2673
conf = self._get_configs(directory, conf_id).next()
2674
# We use the first section in the first config where the
2675
# option is defined to remove it
2676
conf.remove_user_option(name, section_name)
2681
raise errors.NoSuchConfig(scope)
2683
raise errors.NoSuchConfigOption(name)