27
27
email=Your Name <your@email.address>
28
28
check_signatures=require|ignore|check-available(default)
29
29
create_signatures=always|never|when-required(default)
30
gpg_signing_command=name-of-program
31
30
log_format=name-of-format
32
31
validate_signatures_in_log=true|false(default)
33
32
acceptable_keys=pattern1,pattern2
158
class OptionExpansionLoop(errors.BzrError):
160
_fmt = 'Loop involving %(refs)r while expanding "%(string)s".'
162
def __init__(self, string, refs):
164
self.refs = '->'.join(refs)
167
class ExpandingUnknownOption(errors.BzrError):
169
_fmt = 'Option "%(name)s" is not defined while expanding "%(string)s".'
171
def __init__(self, name, string):
176
class IllegalOptionName(errors.BzrError):
178
_fmt = 'Option "%(name)s" is not allowed.'
180
def __init__(self, name):
184
class ConfigContentError(errors.BzrError):
186
_fmt = "Config file %(filename)s is not UTF-8 encoded\n"
188
def __init__(self, filename):
189
self.filename = filename
192
class ParseConfigError(errors.BzrError):
194
_fmt = "Error(s) parsing config file %(filename)s:\n%(errors)s"
196
def __init__(self, errors, filename):
197
self.filename = filename
198
self.errors = '\n'.join(e.msg for e in errors)
201
class ConfigOptionValueError(errors.BzrError):
203
_fmt = ('Bad value "%(value)s" for option "%(name)s".\n'
204
'See ``brz help %(name)s``')
206
def __init__(self, name, value):
207
errors.BzrError.__init__(self, name=name, value=value)
210
class NoEmailInUsername(errors.BzrError):
212
_fmt = "%(username)r does not seem to contain a reasonable email address"
214
def __init__(self, username):
215
self.username = username
218
class NoSuchConfig(errors.BzrError):
220
_fmt = ('The "%(config_id)s" configuration does not exist.')
222
def __init__(self, config_id):
223
errors.BzrError.__init__(self, config_id=config_id)
226
class NoSuchConfigOption(errors.BzrError):
228
_fmt = ('The "%(option_name)s" configuration option does not exist.')
230
def __init__(self, option_name):
231
errors.BzrError.__init__(self, option_name=option_name)
234
class NoWhoami(errors.BzrError):
236
_fmt = ('Unable to determine your name.\n'
237
"Please, set your name with the 'whoami' command.\n"
238
'E.g. brz whoami "Your Name <name@example.com>"')
157
241
def signature_policy_from_unicode(signature_string):
158
242
"""Convert a string to a signing policy."""
159
243
if signature_string.lower() == 'check-available':
342
426
name = chunk[1:-1]
343
427
if name in _ref_stack:
344
raise errors.OptionExpansionLoop(string, _ref_stack)
428
raise OptionExpansionLoop(string, _ref_stack)
345
429
_ref_stack.append(name)
346
430
value = self._expand_option(name, env, _ref_stack)
347
431
if value is None:
348
raise errors.ExpandingUnknownOption(name, string)
432
raise ExpandingUnknownOption(name, string)
349
433
if isinstance(value, list):
350
434
list_value = True
351
435
chunks.extend(value)
474
558
$BRZ_EMAIL can be set to override this, then
475
559
the concrete policy type is checked, and finally
476
560
$EMAIL is examined.
477
If no username can be found, errors.NoWhoami exception is raised.
561
If no username can be found, NoWhoami exception is raised.
479
563
v = os.environ.get('BRZ_EMAIL')
666
750
self._parser = ConfigObj(co_input, encoding='utf-8')
667
751
except configobj.ConfigObjError as e:
668
raise errors.ParseConfigError(e.errors, e.config.filename)
752
raise ParseConfigError(e.errors, e.config.filename)
669
753
except UnicodeDecodeError:
670
raise errors.ConfigContentError(self.file_name)
754
raise ConfigContentError(self.file_name)
671
755
# Make sure self.reload() will use the right file name
672
756
self._parser.filename = self.file_name
673
757
for hook in OldConfigHooks['load']:
1312
1392
def remove_user_option(self, option_name, section_name=None):
1313
1393
self._get_branch_data_config().remove_option(option_name, section_name)
1315
def _gpg_signing_command(self):
1316
"""See Config.gpg_signing_command."""
1317
return self._get_safe_value('_gpg_signing_command')
1319
1395
def _post_commit(self):
1320
1396
"""See Config.post_commit."""
1321
1397
return self._get_safe_value('_post_commit')
1672
1752
# encoded, but the values in the ConfigObj are always Unicode.
1673
1753
self._config = ConfigObj(self._input, encoding='utf-8')
1674
1754
except configobj.ConfigObjError as e:
1675
raise errors.ParseConfigError(e.errors, e.config.filename)
1755
raise ParseConfigError(e.errors, e.config.filename)
1676
1756
except UnicodeError:
1677
raise errors.ConfigContentError(self._filename)
1757
raise ConfigContentError(self._filename)
1678
1758
return self._config
1760
def _check_permissions(self):
1761
"""Check permission of auth file are user read/write able only."""
1763
st = os.stat(self._filename)
1764
except OSError as e:
1765
if e.errno != errno.ENOENT:
1766
trace.mutter('Unable to stat %r: %r', self._filename, e)
1768
mode = stat.S_IMODE(st.st_mode)
1769
if ((stat.S_IXOTH | stat.S_IWOTH | stat.S_IROTH | stat.S_IXGRP |
1770
stat.S_IWGRP | stat.S_IRGRP ) & mode):
1772
if (not self._filename in _authentication_config_permission_errors
1773
and not GlobalConfig().suppress_warning(
1774
'insecure_permissions')):
1775
trace.warning("The file '%s' has insecure "
1776
"file permissions. Saved passwords may be accessible "
1777
"by other users.", self._filename)
1778
_authentication_config_permission_errors.add(self._filename)
1680
1780
def _save(self):
1681
1781
"""Save the config file, only tests should use it for now."""
1682
1782
conf_dir = os.path.dirname(self._filename)
1683
1783
ensure_config_dir_exists(conf_dir)
1684
f = file(self._filename, 'wb')
1784
fd = os.open(self._filename, os.O_RDWR|os.O_CREAT, 0o600)
1786
f = os.fdopen(fd, 'wb')
1686
1787
self._get_config().write(f)
2185
2286
conf = ConfigObj(f, encoding='utf-8')
2186
2287
except configobj.ConfigObjError as e:
2187
raise errors.ParseConfigError(e.errors, self._external_url())
2288
raise ParseConfigError(e.errors, self._external_url())
2188
2289
except UnicodeDecodeError:
2189
raise errors.ConfigContentError(self._external_url())
2290
raise ConfigContentError(self._external_url())
2302
2403
trace.warning('Value "%s" is not valid for "%s"',
2303
2404
unicode_value, self.name)
2304
2405
elif self.invalid == 'error':
2305
raise errors.ConfigOptionValueError(self.name, unicode_value)
2406
raise ConfigOptionValueError(self.name, unicode_value)
2306
2407
return converted
2308
2409
def get_override(self):
2500
2603
:param option_name: The name to validate.
2502
2605
if _option_ref_re.match('{%s}' % option_name) is None:
2503
raise errors.IllegalOptionName(option_name)
2606
raise IllegalOptionName(option_name)
2505
2608
def register(self, option):
2506
2609
"""Register a new option to its name.
2677
2780
Option('email', override_from_env=['BRZ_EMAIL'], default=default_email,
2678
2781
help='The users identity'))
2679
2782
option_registry.register(
2680
Option('gpg_signing_command',
2683
Program to use use for creating signatures.
2685
This should support at least the -u and --clearsign options.
2687
option_registry.register(
2688
2783
Option('gpg_signing_key',
2693
2788
This defaults to the first key associated with the users email.
2695
2790
option_registry.register(
2696
Option('ignore_missing_extensions', default=False,
2697
from_unicode=bool_from_store,
2699
Control the missing extensions warning display.
2701
The warning will not be emitted if set to True.
2703
option_registry.register(
2704
2791
Option('language',
2705
2792
help='Language to translate messages into.'))
2706
2793
option_registry.register(
3149
3236
list_values=False)
3150
3237
except configobj.ConfigObjError as e:
3151
3238
self._config_obj = None
3152
raise errors.ParseConfigError(e.errors, self.external_url())
3239
raise ParseConfigError(e.errors, self.external_url())
3153
3240
except UnicodeDecodeError:
3154
raise errors.ConfigContentError(self.external_url())
3241
raise ConfigContentError(self.external_url())
3156
3243
def save_changes(self):
3157
3244
if not self.is_loaded():
3201
3288
except errors.NoSuchFile:
3202
3289
# The file doesn't exist, let's pretend it was empty
3203
self._load_from_string('')
3290
self._load_from_string(b'')
3204
3291
if section_id in self.dirty_sections:
3205
3292
# We already created a mutable section for this id
3206
3293
return self.dirty_sections[section_id]
3713
3800
expanded = True
3714
3801
name = chunk[1:-1]
3715
3802
if name in _refs:
3716
raise errors.OptionExpansionLoop(string, _refs)
3803
raise OptionExpansionLoop(string, _refs)
3717
3804
_refs.append(name)
3718
3805
value = self._expand_option(name, env, _refs)
3719
3806
if value is None:
3720
raise errors.ExpandingUnknownOption(name, string)
3807
raise ExpandingUnknownOption(name, string)
3721
3808
chunks.append(value)
3723
3810
result = ''.join(chunks)
4133
4220
value = self._quote_multiline(value)
4134
4221
self.outf.write('%s\n' % (value,))
4136
raise errors.NoSuchConfigOption(name)
4223
raise NoSuchConfigOption(name)
4138
4225
def _show_matching_options(self, name, directory, scope):
4139
4226
name = lazy_regex.lazy_compile(name)