159
158
return self[section][name]
162
# FIXME: Until we can guarantee that each config file is loaded once and and
161
# FIXME: Until we can guarantee that each config file is loaded once and
163
162
# only once for a given bzrlib session, we don't want to re-read the file every
164
163
# time we query for an option so we cache the value (bad ! watch out for tests
165
164
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
370
369
% (option_name,))
372
371
value = self._expand_options_in_string(value)
372
for hook in OldConfigHooks['get']:
373
hook(self, option_name, value)
375
def get_user_option_as_bool(self, option_name, expand=None):
376
"""Get a generic option as a boolean - no special process, no default.
376
def get_user_option_as_bool(self, option_name, expand=None, default=None):
377
"""Get a generic option as a boolean.
379
:param expand: Allow expanding references to other config values.
380
:param default: Default value if nothing is configured
378
381
:return None if the option doesn't exist or its value can't be
379
382
interpreted as a boolean. Returns True or False otherwise.
381
384
s = self.get_user_option(option_name, expand=expand)
383
386
# The option doesn't exist
385
388
val = ui.bool_from_string(s)
387
390
# The value can't be interpreted as a boolean
492
495
if policy is None:
493
496
policy = self._get_signature_checking()
494
497
if policy is not None:
498
#this warning should go away once check_signatures is
499
#implemented (if not before)
495
500
trace.warning("Please use create_signatures,"
496
501
" not check_signatures to set signing policy.")
497
if policy == CHECK_ALWAYS:
499
502
elif policy == SIGN_ALWAYS:
546
549
def find_merge_tool(self, name):
547
# We fake a defaults mechanism here by checking if the given name can
550
# We fake a defaults mechanism here by checking if the given name can
548
551
# be found in the known_merge_tools if it's not found in the config.
549
552
# This should be done through the proposed config defaults mechanism
550
553
# when it becomes available in the future.
554
557
return command_line
560
class _ConfigHooks(hooks.Hooks):
561
"""A dict mapping hook names and a list of callables for configs.
565
"""Create the default hooks.
567
These are all empty initially, because by default nothing should get
570
super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
571
self.add_hook('load',
572
'Invoked when a config store is loaded.'
573
' The signature is (store).',
575
self.add_hook('save',
576
'Invoked when a config store is saved.'
577
' The signature is (store).',
579
# The hooks for config options
581
'Invoked when a config option is read.'
582
' The signature is (stack, name, value).',
585
'Invoked when a config option is set.'
586
' The signature is (stack, name, value).',
588
self.add_hook('remove',
589
'Invoked when a config option is removed.'
590
' The signature is (stack, name).',
592
ConfigHooks = _ConfigHooks()
595
class _OldConfigHooks(hooks.Hooks):
596
"""A dict mapping hook names and a list of callables for configs.
600
"""Create the default hooks.
602
These are all empty initially, because by default nothing should get
605
super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
606
self.add_hook('load',
607
'Invoked when a config store is loaded.'
608
' The signature is (config).',
610
self.add_hook('save',
611
'Invoked when a config store is saved.'
612
' The signature is (config).',
614
# The hooks for config options
616
'Invoked when a config option is read.'
617
' The signature is (config, name, value).',
620
'Invoked when a config option is set.'
621
' The signature is (config, name, value).',
623
self.add_hook('remove',
624
'Invoked when a config option is removed.'
625
' The signature is (config, name).',
627
OldConfigHooks = _OldConfigHooks()
557
630
class IniBasedConfig(Config):
558
631
"""A configuration policy that draws from ini files."""
619
692
self._parser = ConfigObj(co_input, encoding='utf-8')
620
693
except configobj.ConfigObjError, e:
621
694
raise errors.ParseConfigError(e.errors, e.config.filename)
695
except UnicodeDecodeError:
696
raise errors.ConfigContentError(self.file_name)
622
697
# Make sure self.reload() will use the right file name
623
698
self._parser.filename = self.file_name
699
for hook in OldConfigHooks['load']:
624
701
return self._parser
626
703
def reload(self):
951
1034
self._get_parser().setdefault(section, {})[option] = value
952
1035
self._write_config_file()
1036
for hook in OldConfigHooks['set']:
1037
hook(self, option, value)
955
1039
def _get_sections(self, name=None):
956
1040
"""See IniBasedConfig._get_sections()."""
1152
1236
# the allowed values of store match the config policies
1153
1237
self._set_option_policy(location, option, store)
1154
1238
self._write_config_file()
1239
for hook in OldConfigHooks['set']:
1240
hook(self, option, value)
1157
1243
class BranchConfig(Config):
1635
1723
section[option_name] = value
1638
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1726
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1640
1728
"""Returns the matching credentials from authentication.conf file.
2054
2142
section_obj = configobj[section]
2055
2143
except KeyError:
2057
return section_obj.get(name, default)
2145
value = section_obj.get(name, default)
2146
for hook in OldConfigHooks['get']:
2147
hook(self, name, value)
2059
2150
def set_option(self, value, name, section=None):
2060
2151
"""Set the value associated with a named option.
2076
2169
del configobj[option_name]
2078
2171
del configobj[section_name][option_name]
2172
for hook in OldConfigHooks['remove']:
2173
hook(self, option_name)
2079
2174
self._set_configobj(configobj)
2081
2176
def _get_config_file(self):
2083
return StringIO(self._transport.get_bytes(self._filename))
2178
f = StringIO(self._transport.get_bytes(self._filename))
2179
for hook in OldConfigHooks['load']:
2084
2182
except errors.NoSuchFile:
2085
2183
return StringIO()
2185
def _external_url(self):
2186
return urlutils.join(self._transport.external_url(), self._filename)
2087
2188
def _get_configobj(self):
2088
2189
f = self._get_config_file()
2090
return ConfigObj(f, encoding='utf-8')
2192
conf = ConfigObj(f, encoding='utf-8')
2193
except configobj.ConfigObjError, e:
2194
raise errors.ParseConfigError(e.errors, self._external_url())
2195
except UnicodeDecodeError:
2196
raise errors.ConfigContentError(self._external_url())
2094
2201
def _set_configobj(self, configobj):
2095
2202
out_file = StringIO()
2096
2203
configobj.write(out_file)
2097
2204
out_file.seek(0)
2098
2205
self._transport.put_file(self._filename, out_file)
2206
for hook in OldConfigHooks['save']:
2101
2210
class Option(object):
2189
2298
"""Loads the Store from persistent storage."""
2190
2299
raise NotImplementedError(self.load)
2192
def _load_from_string(self, str_or_unicode):
2301
def _load_from_string(self, bytes):
2193
2302
"""Create a store from a string in configobj syntax.
2195
:param str_or_unicode: A string representing the file content. This will
2196
be encoded to suit store needs internally.
2198
This is for tests and should not be used in production unless a
2199
convincing use case can be demonstrated :)
2304
:param bytes: A string representing the file content.
2201
2306
raise NotImplementedError(self._load_from_string)
2272
2377
content = self.transport.get_bytes(self.file_name)
2273
2378
self._load_from_string(content)
2379
for hook in ConfigHooks['load']:
2275
def _load_from_string(self, str_or_unicode):
2382
def _load_from_string(self, bytes):
2276
2383
"""Create a config store from a string.
2278
:param str_or_unicode: A string representing the file content. This will
2279
be utf-8 encoded internally.
2281
This is for tests and should not be used in production unless a
2282
convincing use case can be demonstrated :)
2385
:param bytes: A string representing the file content.
2284
2387
if self.is_loaded():
2285
2388
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2286
co_input = StringIO(str_or_unicode.encode('utf-8'))
2389
co_input = StringIO(bytes)
2288
2391
# The config files are always stored utf8-encoded
2289
2392
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2290
2393
except configobj.ConfigObjError, e:
2291
2394
self._config_obj = None
2292
2395
raise errors.ParseConfigError(e.errors, self.external_url())
2396
except UnicodeDecodeError:
2397
raise errors.ConfigContentError(self.external_url())
2294
2399
def save(self):
2295
2400
if not self.is_loaded():
2604
2713
"""Set a new value for the option."""
2605
2714
section = self._get_mutable_section()
2606
2715
section.set(name, value)
2716
for hook in ConfigHooks['set']:
2717
hook(self, name, value)
2608
2719
def remove(self, name):
2609
2720
"""Remove an existing option."""
2610
2721
section = self._get_mutable_section()
2611
2722
section.remove(name)
2723
for hook in ConfigHooks['remove']:
2613
2726
def __repr__(self):
2614
2727
# Mostly for debugging use
2701
2814
' the configuration file'),
2817
_see_also = ['configuration']
2704
2819
@commands.display_command
2705
2820
def run(self, name=None, all=False, directory=None, scope=None,