16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
"""Configuration that affects the behaviour of Bazaar.
21
Currently this configuration resides in ~/.bazaar/bazaar.conf
22
and ~/.bazaar/locations.conf, which is written to by bzr.
24
In bazaar.conf the following options may be set:
19
"""Configuration that affects the behaviour of Breezy.
21
Currently this configuration resides in ~/.config/breezy/breezy.conf
22
and ~/.config/breezy/locations.conf, which is written to by brz.
24
If the first location doesn't exist, then brz falls back to reading
25
Bazaar configuration files in ~/.bazaar or ~/.config/bazaar.
27
In breezy.conf the following options may be set:
26
29
editor=name-of-program
27
30
email=Your Name <your@email.address>
28
31
check_signatures=require|ignore|check-available(default)
29
32
create_signatures=always|never|when-required(default)
30
gpg_signing_command=name-of-program
31
33
log_format=name-of-format
32
34
validate_signatures_in_log=true|false(default)
33
35
acceptable_keys=pattern1,pattern2
153
class OptionExpansionLoop(errors.BzrError):
155
_fmt = 'Loop involving %(refs)r while expanding "%(string)s".'
157
def __init__(self, string, refs):
159
self.refs = '->'.join(refs)
162
class ExpandingUnknownOption(errors.BzrError):
164
_fmt = 'Option "%(name)s" is not defined while expanding "%(string)s".'
166
def __init__(self, name, string):
171
class IllegalOptionName(errors.BzrError):
173
_fmt = 'Option "%(name)s" is not allowed.'
175
def __init__(self, name):
179
class ConfigContentError(errors.BzrError):
181
_fmt = "Config file %(filename)s is not UTF-8 encoded\n"
183
def __init__(self, filename):
184
self.filename = filename
187
class ParseConfigError(errors.BzrError):
189
_fmt = "Error(s) parsing config file %(filename)s:\n%(errors)s"
191
def __init__(self, errors, filename):
192
self.filename = filename
193
self.errors = '\n'.join(e.msg for e in errors)
196
class ConfigOptionValueError(errors.BzrError):
198
_fmt = ('Bad value "%(value)s" for option "%(name)s".\n'
199
'See ``brz help %(name)s``')
201
def __init__(self, name, value):
202
errors.BzrError.__init__(self, name=name, value=value)
205
class NoEmailInUsername(errors.BzrError):
207
_fmt = "%(username)r does not seem to contain a reasonable email address"
209
def __init__(self, username):
210
self.username = username
213
class NoSuchConfig(errors.BzrError):
215
_fmt = ('The "%(config_id)s" configuration does not exist.')
217
def __init__(self, config_id):
218
errors.BzrError.__init__(self, config_id=config_id)
221
class NoSuchConfigOption(errors.BzrError):
223
_fmt = ('The "%(option_name)s" configuration option does not exist.')
225
def __init__(self, option_name):
226
errors.BzrError.__init__(self, option_name=option_name)
155
229
def signature_policy_from_unicode(signature_string):
156
230
"""Convert a string to a signing policy."""
157
231
if signature_string.lower() == 'check-available':
400
495
l = self.get_user_option(option_name, expand=expand)
401
if isinstance(l, (str, unicode)):
496
if isinstance(l, str):
402
497
# A single value, most probably the user forgot (or didn't care to
403
498
# add) the final ','
407
@deprecated_method(deprecated_in((2, 5, 0)))
408
def get_user_option_as_int_from_SI(self, option_name, default=None):
409
"""Get a generic option from a human readable size in SI units, e.g 10MB
411
Accepted suffixes are K,M,G. It is case-insensitive and may be followed
412
by a trailing b (i.e. Kb, MB). This is intended to be practical and not
415
:return Integer, expanded to its base-10 value if a proper SI unit is
416
found. If the option doesn't exist, or isn't a value in
417
SI units, return default (which defaults to None)
419
val = self.get_user_option(option_name)
420
if isinstance(val, list):
425
p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
429
val = int(m.group(1))
430
if m.group(2) is not None:
431
if m.group(2).lower() == 'k':
433
elif m.group(2).lower() == 'm':
435
elif m.group(2).lower() == 'g':
438
ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
439
' value {1!r} is not an SI unit.').format(
446
@deprecated_method(deprecated_in((2, 5, 0)))
447
def gpg_signing_command(self):
448
"""What program should be used to sign signatures?"""
449
result = self._gpg_signing_command()
454
def _gpg_signing_command(self):
455
"""See gpg_signing_command()."""
458
@deprecated_method(deprecated_in((2, 5, 0)))
459
def log_format(self):
460
"""What log format should be used"""
461
result = self._log_format()
466
502
def _log_format(self):
467
503
"""See log_format()."""
513
530
Something similar to 'Martin Pool <mbp@sourcefrog.net>'
515
$BZR_EMAIL can be set to override this, then
532
$BRZ_EMAIL or $BZR_EMAIL can be set to override this, then
516
533
the concrete policy type is checked, and finally
517
534
$EMAIL is examined.
518
If no username can be found, errors.NoWhoami exception is raised.
535
If no username can be found, NoWhoami exception is raised.
520
v = os.environ.get('BZR_EMAIL')
537
v = os.environ.get('BRZ_EMAIL') or os.environ.get('BZR_EMAIL')
522
return v.decode(osutils.get_user_encoding())
523
540
v = self._get_user_id()
526
return default_email()
528
def ensure_username(self):
529
"""Raise errors.NoWhoami if username is not set.
531
This method relies on the username() function raising the error.
535
@deprecated_method(deprecated_in((2, 5, 0)))
536
def signature_checking(self):
537
"""What is the current policy for signature checking?."""
538
policy = self._get_signature_checking()
539
if policy is not None:
541
return CHECK_IF_POSSIBLE
543
@deprecated_method(deprecated_in((2, 5, 0)))
544
def signing_policy(self):
545
"""What is the current policy for signature checking?."""
546
policy = self._get_signing_policy()
547
if policy is not None:
549
return SIGN_WHEN_REQUIRED
551
@deprecated_method(deprecated_in((2, 5, 0)))
552
def signature_needed(self):
553
"""Is a signature needed when committing ?."""
554
policy = self._get_signing_policy()
556
policy = self._get_signature_checking()
557
if policy is not None:
558
#this warning should go away once check_signatures is
559
#implemented (if not before)
560
trace.warning("Please use create_signatures,"
561
" not check_signatures to set signing policy.")
562
elif policy == SIGN_ALWAYS:
566
@deprecated_method(deprecated_in((2, 5, 0)))
567
def gpg_signing_key(self):
568
"""GPG user-id to sign commits"""
569
key = self.get_user_option('gpg_signing_key')
570
if key == "default" or key == None:
571
return self.user_email()
543
return bedding.default_email()
575
545
def get_alias(self, value):
576
546
return self._get_alias(value)
693
666
'Invoked when a config option is removed.'
694
667
' The signature is (config, name).',
696
671
OldConfigHooks = _OldConfigHooks()
699
674
class IniBasedConfig(Config):
700
675
"""A configuration policy that draws from ini files."""
702
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
677
def __init__(self, file_name=None):
704
678
"""Base class for configuration files using an ini-like syntax.
706
680
:param file_name: The configuration file path.
708
682
super(IniBasedConfig, self).__init__()
709
683
self.file_name = file_name
710
if symbol_versioning.deprecated_passed(get_filename):
711
symbol_versioning.warn(
712
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
713
' Use file_name instead.',
716
if get_filename is not None:
717
self.file_name = get_filename()
719
self.file_name = file_name
684
self.file_name = file_name
720
685
self._content = None
721
686
self._parser = None
1266
1201
if policy_key in self._get_parser()[section]:
1267
1202
del self._get_parser()[section][policy_key]
1270
1204
def set_user_option(self, option, value, store=STORE_LOCATION):
1271
1205
"""Save option and its value in the configuration."""
1272
1206
if store not in [STORE_LOCATION,
1273
1207
STORE_LOCATION_NORECURSE,
1274
1208
STORE_LOCATION_APPENDPATH]:
1275
1209
raise ValueError('bad storage policy %r for %r' %
1278
location = self.location
1279
if location.endswith('/'):
1280
location = location[:-1]
1281
parser = self._get_parser()
1282
if not location in parser and not location + '/' in parser:
1283
parser[location] = {}
1284
elif location + '/' in parser:
1285
location = location + '/'
1286
parser[location][option]=value
1287
# the allowed values of store match the config policies
1288
self._set_option_policy(location, option, store)
1289
self._write_config_file()
1290
for hook in OldConfigHooks['set']:
1291
hook(self, option, value)
1211
with self.lock_write():
1213
location = self.location
1214
if location.endswith('/'):
1215
location = location[:-1]
1216
parser = self._get_parser()
1217
if location not in parser and not location + '/' in parser:
1218
parser[location] = {}
1219
elif location + '/' in parser:
1220
location = location + '/'
1221
parser[location][option] = value
1222
# the allowed values of store match the config policies
1223
self._set_option_policy(location, option, store)
1224
self._write_config_file()
1225
for hook in OldConfigHooks['set']:
1226
hook(self, option, value)
1294
1229
class BranchConfig(Config):
1465
1395
return self._get_best_value('_acceptable_keys')
1468
def ensure_config_dir_exists(path=None):
1469
"""Make sure a configuration directory exists.
1470
This makes sure that the directory exists.
1471
On windows, since configuration directories are 2 levels deep,
1472
it makes sure both the directory and the parent directory exists.
1476
if not os.path.isdir(path):
1477
if sys.platform == 'win32':
1478
parent_dir = os.path.dirname(path)
1479
if not os.path.isdir(parent_dir):
1480
trace.mutter('creating config parent directory: %r', parent_dir)
1481
os.mkdir(parent_dir)
1482
trace.mutter('creating config directory: %r', path)
1484
osutils.copy_ownership_from_path(path)
1488
"""Return per-user configuration directory as unicode string
1490
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1491
and Linux. On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1492
that will be used instead.
1494
TODO: Global option --config-dir to override this.
1496
base = osutils.path_from_environ('BZR_HOME')
1497
if sys.platform == 'win32':
1499
base = win32utils.get_appdata_location()
1501
base = win32utils.get_home_location()
1502
# GZ 2012-02-01: Really the two level subdirs only make sense inside
1503
# APPDATA, but hard to move. See bug 348640 for more.
1504
return osutils.pathjoin(base, 'bazaar', '2.0')
1506
xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1508
xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1509
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1510
if osutils.isdir(xdg_dir):
1512
"Using configuration in XDG directory %s." % xdg_dir)
1514
base = osutils._get_home_dir()
1515
return osutils.pathjoin(base, ".bazaar")
1518
def config_filename():
1519
"""Return per-user configuration ini file filename."""
1520
return osutils.pathjoin(config_dir(), 'bazaar.conf')
1523
def locations_config_filename():
1524
"""Return per-user configuration ini file filename."""
1525
return osutils.pathjoin(config_dir(), 'locations.conf')
1528
def authentication_config_filename():
1529
"""Return per-user authentication ini file filename."""
1530
return osutils.pathjoin(config_dir(), 'authentication.conf')
1533
def user_ignore_config_filename():
1534
"""Return the user default ignore filename"""
1535
return osutils.pathjoin(config_dir(), 'ignore')
1539
"""Return the directory name to store crash files.
1541
This doesn't implicitly create it.
1543
On Windows it's in the config directory; elsewhere it's /var/crash
1544
which may be monitored by apport. It can be overridden by
1547
if sys.platform == 'win32':
1548
return osutils.pathjoin(config_dir(), 'Crash')
1550
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1552
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1555
def xdg_cache_dir():
1556
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1557
# Possibly this should be different on Windows?
1558
e = os.environ.get('XDG_CACHE_HOME', None)
1562
return os.path.expanduser('~/.cache')
1565
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1566
"""If possible, return the assumed default email domain.
1568
:returns: string mail domain, or None.
1570
if sys.platform == 'win32':
1571
# No implementation yet; patches welcome
1574
f = open(mailname_file)
1575
except (IOError, OSError), e:
1578
domain = f.readline().strip()
1584
def default_email():
1585
v = os.environ.get('BZR_EMAIL')
1587
return v.decode(osutils.get_user_encoding())
1588
v = os.environ.get('EMAIL')
1590
return v.decode(osutils.get_user_encoding())
1591
name, email = _auto_user_id()
1593
return u'%s <%s>' % (name, email)
1596
raise errors.NoWhoami()
1599
def _auto_user_id():
1600
"""Calculate automatic user identification.
1602
:returns: (realname, email), either of which may be None if they can't be
1605
Only used when none is set in the environment or the id file.
1607
This only returns an email address if we can be fairly sure the
1608
address is reasonable, ie if /etc/mailname is set on unix.
1610
This doesn't use the FQDN as the default domain because that may be
1611
slow, and it doesn't use the hostname alone because that's not normally
1612
a reasonable address.
1614
if sys.platform == 'win32':
1615
# No implementation to reliably determine Windows default mail
1616
# address; please add one.
1619
default_mail_domain = _get_default_mail_domain()
1620
if not default_mail_domain:
1626
w = pwd.getpwuid(uid)
1628
trace.mutter('no passwd entry for uid %d?' % uid)
1631
# we try utf-8 first, because on many variants (like Linux),
1632
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
1633
# false positives. (many users will have their user encoding set to
1634
# latin-1, which cannot raise UnicodeError.)
1636
gecos = w.pw_gecos.decode('utf-8')
1638
except UnicodeError:
1640
encoding = osutils.get_user_encoding()
1641
gecos = w.pw_gecos.decode(encoding)
1642
except UnicodeError, e:
1643
trace.mutter("cannot decode passwd entry %s" % w)
1646
username = w.pw_name.decode(encoding)
1647
except UnicodeError, e:
1648
trace.mutter("cannot decode passwd entry %s" % w)
1651
comma = gecos.find(',')
1655
realname = gecos[:comma]
1657
return realname, (username + '@' + default_mail_domain)
1660
1398
def parse_username(username):
1661
1399
"""Parse e-mail username and return a (name, address) tuple."""
1662
1400
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1663
1401
if match is None:
1664
1402
return (username, '')
1666
return (match.group(1), match.group(2))
1403
return (match.group(1), match.group(2))
1669
1406
def extract_email_address(e):
1697
1435
return self._config._get_configobj()
1699
1437
def get_option(self, name, section=None, default=None):
1700
self.branch.lock_read()
1438
with self.branch.lock_read():
1702
1439
return self._config.get_option(name, section, default)
1704
self.branch.unlock()
1706
1441
def set_option(self, value, name, section=None):
1707
1442
"""Set a per-branch configuration option"""
1708
1443
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1709
1444
# higher levels providing the right lock -- vila 20101004
1710
self.branch.lock_write()
1445
with self.branch.lock_write():
1712
1446
self._config.set_option(value, name, section)
1714
self.branch.unlock()
1716
1448
def remove_option(self, option_name, section_name=None):
1717
1449
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1718
1450
# higher levels providing the right lock -- vila 20101004
1719
self.branch.lock_write()
1451
with self.branch.lock_write():
1721
1452
self._config.remove_option(option_name, section_name)
1723
self.branch.unlock()
1455
_authentication_config_permission_errors = set()
1726
1458
class AuthenticationConfig(object):
1751
1483
# Note: the encoding below declares that the file itself is utf-8
1752
1484
# encoded, but the values in the ConfigObj are always Unicode.
1753
1485
self._config = ConfigObj(self._input, encoding='utf-8')
1754
except configobj.ConfigObjError, e:
1755
raise errors.ParseConfigError(e.errors, e.config.filename)
1486
except configobj.ConfigObjError as e:
1487
raise ParseConfigError(e.errors, e.config.filename)
1756
1488
except UnicodeError:
1757
raise errors.ConfigContentError(self._filename)
1489
raise ConfigContentError(self._filename)
1758
1490
return self._config
1492
def _check_permissions(self):
1493
"""Check permission of auth file are user read/write able only."""
1495
st = os.stat(self._filename)
1496
except OSError as e:
1497
if e.errno != errno.ENOENT:
1498
trace.mutter('Unable to stat %r: %r', self._filename, e)
1500
mode = stat.S_IMODE(st.st_mode)
1501
if ((stat.S_IXOTH | stat.S_IWOTH | stat.S_IROTH | stat.S_IXGRP
1502
| stat.S_IWGRP | stat.S_IRGRP) & mode):
1504
if (self._filename not in _authentication_config_permission_errors and
1505
not GlobalConfig().suppress_warning(
1506
'insecure_permissions')):
1507
trace.warning("The file '%s' has insecure "
1508
"file permissions. Saved passwords may be accessible "
1509
"by other users.", self._filename)
1510
_authentication_config_permission_errors.add(self._filename)
1760
1512
def _save(self):
1761
1513
"""Save the config file, only tests should use it for now."""
1762
1514
conf_dir = os.path.dirname(self._filename)
1763
ensure_config_dir_exists(conf_dir)
1764
f = file(self._filename, 'wb')
1515
bedding.ensure_config_dir_exists(conf_dir)
1516
fd = os.open(self._filename, os.O_RDWR | os.O_CREAT, 0o600)
1518
f = os.fdopen(fd, 'wb')
1766
1519
self._get_config().write(f)
2737
2507
option_registry.register(
2738
2508
ListOption('debug_flags', default=[],
2739
help='Debug flags to activate.'))
2509
help='Debug flags to activate.'))
2740
2510
option_registry.register(
2741
2511
Option('default_format', default='2a',
2742
2512
help='Format used when creating branches.'))
2743
2513
option_registry.register(
2744
Option('dpush_strict', default=None,
2745
from_unicode=bool_from_store,
2747
The default value for ``dpush --strict``.
2749
If present, defines the ``--strict`` option default value for checking
2750
uncommitted changes before pushing into a different VCS without any
2751
custom bzr metadata.
2753
option_registry.register(
2754
2514
Option('editor',
2755
2515
help='The command called to launch an editor to enter a message.'))
2756
2516
option_registry.register(
2757
Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
2758
help='The users identity'))
2759
option_registry.register(
2760
Option('gpg_signing_command',
2763
Program to use use for creating signatures.
2765
This should support at least the -u and --clearsign options.
2517
Option('email', override_from_env=['BRZ_EMAIL', 'BZR_EMAIL'],
2518
default=bedding.default_email, help='The users identity'))
2767
2519
option_registry.register(
2768
2520
Option('gpg_signing_key',
2866
2610
lost if the machine crashes. See also dirstate.fdatasync.
2868
2612
option_registry.register_lazy('smtp_server',
2869
'bzrlib.smtp_connection', 'smtp_server')
2613
'breezy.smtp_connection', 'smtp_server')
2870
2614
option_registry.register_lazy('smtp_password',
2871
'bzrlib.smtp_connection', 'smtp_password')
2615
'breezy.smtp_connection', 'smtp_password')
2872
2616
option_registry.register_lazy('smtp_username',
2873
'bzrlib.smtp_connection', 'smtp_username')
2617
'breezy.smtp_connection', 'smtp_username')
2874
2618
option_registry.register(
2875
2619
Option('selftest.timeout',
2877
from_unicode=int_from_store,
2878
help='Abort selftest if one test takes longer than this many seconds',
2621
from_unicode=int_from_store,
2622
help='Abort selftest if one test takes longer than this many seconds',
2881
2625
option_registry.register(
2882
2626
Option('send_strict', default=None,
2911
2659
help='''Where submissions from this branch are mailed to.'''))
2912
2660
option_registry.register(
2913
2661
ListOption('suppress_warnings',
2915
help="List of warning classes to suppress."))
2663
help="List of warning classes to suppress."))
2916
2664
option_registry.register(
2917
2665
Option('validate_signatures_in_log', default=False,
2918
2666
from_unicode=bool_from_store, invalid='warning',
2919
help='''Whether to validate signatures in bzr log.'''))
2667
help='''Whether to validate signatures in brz log.'''))
2920
2668
option_registry.register_lazy('ssl.ca_certs',
2921
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2669
'breezy.transport.http', 'opt_ssl_ca_certs')
2923
2671
option_registry.register_lazy('ssl.cert_reqs',
2924
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2672
'breezy.transport.http', 'opt_ssl_cert_reqs')
2927
2675
class Section(object):