413
414
# add) the final ','
418
def get_user_option_as_int_from_SI(self, option_name, default=None):
419
"""Get a generic option from a human readable size in SI units, e.g 10MB
421
Accepted suffixes are K,M,G. It is case-insensitive and may be followed
422
by a trailing b (i.e. Kb, MB). This is intended to be practical and not
425
:return Integer, expanded to its base-10 value if a proper SI unit is
426
found. If the option doesn't exist, or isn't a value in
427
SI units, return default (which defaults to None)
429
val = self.get_user_option(option_name)
430
if isinstance(val, list):
435
p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
439
val = int(m.group(1))
440
if m.group(2) is not None:
441
if m.group(2).lower() == 'k':
443
elif m.group(2).lower() == 'm':
445
elif m.group(2).lower() == 'g':
448
ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
449
' value {1!r} is not an SI unit.').format(
417
457
def gpg_signing_command(self):
418
458
"""What program should be used to sign signatures?"""
2274
2319
encoutered, in which config files it can be stored.
2277
def __init__(self, name, default=None, help=None, from_unicode=None,
2322
def __init__(self, name, default=None, default_from_env=None,
2324
from_unicode=None, invalid=None):
2279
2325
"""Build an option definition.
2281
2327
:param name: the name used to refer to the option.
2283
2329
:param default: the default value to use when none exist in the config
2330
stores. This is either a string that ``from_unicode`` will convert
2331
into the proper type or a python object that can be stringified (so
2332
only the empty list is supported for example).
2334
:param default_from_env: A list of environment variables which can
2335
provide a default value. 'default' will be used only if none of the
2336
variables specified here are set in the environment.
2286
2338
:param help: a doc string to explain the option to the user.
2296
2348
'warning' (emit a warning), 'error' (emit an error message and
2351
if default_from_env is None:
2352
default_from_env = []
2299
2353
self.name = name
2300
self.default = default
2354
# Convert the default value to a unicode string so all values are
2355
# strings internally before conversion (via from_unicode) is attempted.
2358
elif isinstance(default, list):
2359
# Only the empty list is supported
2361
raise AssertionError(
2362
'Only empty lists are supported as default values')
2364
elif isinstance(default, (str, unicode, bool, int)):
2365
# Rely on python to convert strings, booleans and integers
2366
self.default = u'%s' % (default,)
2368
# other python objects are not expected
2369
raise AssertionError('%r is not supported as a default value'
2371
self.default_from_env = default_from_env
2301
2372
self.help = help
2302
2373
self.from_unicode = from_unicode
2303
2374
if invalid and invalid not in ('warning', 'error'):
2304
2375
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2305
2376
self.invalid = invalid
2378
def convert_from_unicode(self, unicode_value):
2379
if self.from_unicode is None or unicode_value is None:
2380
# Don't convert or nothing to convert
2381
return unicode_value
2383
converted = self.from_unicode(unicode_value)
2384
except (ValueError, TypeError):
2385
# Invalid values are ignored
2387
if converted is None and self.invalid is not None:
2388
# The conversion failed
2389
if self.invalid == 'warning':
2390
trace.warning('Value "%s" is not valid for "%s"',
2391
unicode_value, self.name)
2392
elif self.invalid == 'error':
2393
raise errors.ConfigOptionValueError(self.name, unicode_value)
2307
2396
def get_default(self):
2398
for var in self.default_from_env:
2400
# If the env variable is defined, its value is the default one
2401
value = os.environ[var]
2406
# Otherwise, fallback to the value defined at registration
2407
value = self.default
2310
2410
def get_help_text(self, additional_see_also=None, plain=True):
2311
2411
result = self.help
2326
2426
return int(unicode_str)
2429
# Use a an empty dict to initialize an empty configobj avoiding all
2430
# parsing and encoding checks
2431
_list_converter_config = configobj.ConfigObj(
2432
{}, encoding='utf-8', list_values=True, interpolation=False)
2329
2435
def list_from_store(unicode_str):
2436
if not isinstance(unicode_str, basestring):
2438
# Now inject our string directly as unicode. All callers got their value
2439
# from configobj, so values that need to be quoted are already properly
2441
_list_converter_config.reset()
2442
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2443
maybe_list = _list_converter_config['list']
2330
2444
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2331
if isinstance(unicode_str, (str, unicode)):
2445
if isinstance(maybe_list, basestring):
2333
2447
# A single value, most probably the user forgot (or didn't care to
2334
2448
# add) the final ','
2337
2451
# The empty string, convert to empty list
2340
2454
# We rely on ConfigObj providing us with a list already
2759
2880
super(BranchStore, self).save()
2883
class ControlStore(LockableIniFileStore):
2885
def __init__(self, bzrdir):
2886
super(ControlStore, self).__init__(bzrdir.transport,
2888
lock_dir_name='branch_lock')
2762
2891
class SectionMatcher(object):
2763
2892
"""Select sections into a given Store.
2765
This intended to be used to postpone getting an iterable of sections from a
2894
This is intended to be used to postpone getting an iterable of sections
2769
2898
def __init__(self, store):
2778
2907
if self.match(s):
2781
def match(self, secion):
2910
def match(self, section):
2911
"""Does the proposed section match.
2913
:param section: A Section object.
2915
:returns: True if the section matches, False otherwise.
2782
2917
raise NotImplementedError(self.match)
2920
class NameMatcher(SectionMatcher):
2922
def __init__(self, store, section_id):
2923
super(NameMatcher, self).__init__(store)
2924
self.section_id = section_id
2926
def match(self, section):
2927
return section.id == self.section_id
2785
2930
class LocationSection(Section):
2787
2932
def __init__(self, section, length, extra_path):
2812
2957
# We slightly diverge from LocalConfig here by allowing the no-name
2813
2958
# section as the most generic one and the lower priority.
2814
2959
no_name_section = None
2816
2961
# Filter out the no_name_section so _iter_for_location_by_parts can be
2817
2962
# used (it assumes all sections have a name).
2818
2963
for section in self.store.get_sections():
2819
2964
if section.id is None:
2820
2965
no_name_section = section
2822
sections.append(section)
2967
all_sections.append(section)
2823
2968
# Unfortunately _iter_for_location_by_parts deals with section names so
2824
2969
# we have to resync.
2825
2970
filtered_sections = _iter_for_location_by_parts(
2826
[s.id for s in sections], self.location)
2827
iter_sections = iter(sections)
2971
[s.id for s in all_sections], self.location)
2972
iter_all_sections = iter(all_sections)
2828
2973
matching_sections = []
2829
2974
if no_name_section is not None:
2830
2975
matching_sections.append(
2831
2976
LocationSection(no_name_section, 0, self.location))
2832
2977
for section_id, extra_path, length in filtered_sections:
2833
# a section id is unique for a given store so it's safe to iterate
2835
section = iter_sections.next()
2836
if section_id == section.id:
2837
matching_sections.append(
2838
LocationSection(section, length, extra_path))
2978
# a section id is unique for a given store so it's safe to take the
2979
# first matching section while iterating. Also, all filtered
2980
# sections are part of 'all_sections' and will always be found
2983
section = iter_all_sections.next()
2984
if section_id == section.id:
2985
matching_sections.append(
2986
LocationSection(section, length, extra_path))
2839
2988
return matching_sections
2841
2990
def get_sections(self):
2912
3078
except KeyError:
2913
3079
# Not registered
2915
if (opt is not None and opt.from_unicode is not None
2916
and value is not None):
2917
# If a value exists and the option provides a converter, use it
2919
converted = opt.from_unicode(value)
2920
except (ValueError, TypeError):
2921
# Invalid values are ignored
2923
if converted is None and opt.invalid is not None:
2924
# The conversion failed
2925
if opt.invalid == 'warning':
2926
trace.warning('Value "%s" is not valid for "%s"',
2928
elif opt.invalid == 'error':
2929
raise errors.ConfigOptionValueError(name, value)
3081
def expand_and_convert(val):
3082
# This may need to be called twice if the value is None or ends up
3083
# being None during expansion or conversion.
3086
if isinstance(val, basestring):
3087
val = self._expand_options_in_string(val)
3089
trace.warning('Cannot expand "%s":'
3090
' %s does not support option expansion'
3091
% (name, type(val)))
3093
val = opt.convert_from_unicode(val)
3095
value = expand_and_convert(value)
3096
if opt is not None and value is None:
2932
3097
# If the option is registered, it may provide a default value
2934
value = opt.get_default()
3098
value = opt.get_default()
3099
value = expand_and_convert(value)
2935
3100
for hook in ConfigHooks['get']:
2936
3101
hook(self, name, value)
3104
def expand_options(self, string, env=None):
3105
"""Expand option references in the string in the configuration context.
3107
:param string: The string containing option(s) to expand.
3109
:param env: An option dict defining additional configuration options or
3110
overriding existing ones.
3112
:returns: The expanded string.
3114
return self._expand_options_in_string(string, env)
3116
def _expand_options_in_string(self, string, env=None, _refs=None):
3117
"""Expand options in the string in the configuration context.
3119
:param string: The string to be expanded.
3121
:param env: An option dict defining additional configuration options or
3122
overriding existing ones.
3124
:param _refs: Private list (FIFO) containing the options being expanded
3127
:returns: The expanded string.
3130
# Not much to expand there
3133
# What references are currently resolved (to detect loops)
3136
# We need to iterate until no more refs appear ({{foo}} will need two
3137
# iterations for example).
3139
raw_chunks = Stack._option_ref_re.split(result)
3140
if len(raw_chunks) == 1:
3141
# Shorcut the trivial case: no refs
3144
# Split will isolate refs so that every other chunk is a ref
3145
chunk_is_ref = False
3146
for chunk in raw_chunks:
3147
if not chunk_is_ref:
3148
chunks.append(chunk)
3153
raise errors.OptionExpansionLoop(string, _refs)
3155
value = self._expand_option(name, env, _refs)
3157
raise errors.ExpandingUnknownOption(name, string)
3158
chunks.append(value)
3160
chunk_is_ref = False
3161
result = ''.join(chunks)
3164
def _expand_option(self, name, env, _refs):
3165
if env is not None and name in env:
3166
# Special case, values provided in env takes precedence over
3170
# FIXME: This is a limited implementation, what we really need is a
3171
# way to query the bzr config for the value of an option,
3172
# respecting the scope rules (That is, once we implement fallback
3173
# configs, getting the option value should restart from the top
3174
# config, not the current one) -- vila 20101222
3175
value = self.get(name, expand=False)
3176
value = self._expand_options_in_string(value, env, _refs)
2939
3179
def _get_mutable_section(self):
2940
3180
"""Get the MutableSection for the Stack.
3023
3267
self.branch = branch
3270
class RemoteControlStack(_CompatibleStack):
3271
"""Remote control-only options stack."""
3273
def __init__(self, bzrdir):
3274
cstore = ControlStore(bzrdir)
3275
super(RemoteControlStack, self).__init__(
3276
[cstore.get_sections],
3278
self.bzrdir = bzrdir
3281
class RemoteBranchStack(_CompatibleStack):
3282
"""Remote branch-only options stack."""
3284
def __init__(self, branch):
3285
bstore = BranchStore(branch)
3286
super(RemoteBranchStack, self).__init__(
3287
[bstore.get_sections],
3289
self.branch = branch
3026
3292
class cmd_config(commands.Command):
3027
3293
__doc__ = """Display, set or remove a configuration option.