1201
1229
if policy_key in self._get_parser()[section]:
1202
1230
del self._get_parser()[section][policy_key]
1204
1233
def set_user_option(self, option, value, store=STORE_LOCATION):
1205
1234
"""Save option and its value in the configuration."""
1206
1235
if store not in [STORE_LOCATION,
1207
1236
STORE_LOCATION_NORECURSE,
1208
1237
STORE_LOCATION_APPENDPATH]:
1209
1238
raise ValueError('bad storage policy %r for %r' %
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)
1241
location = self.location
1242
if location.endswith('/'):
1243
location = location[:-1]
1244
parser = self._get_parser()
1245
if not location in parser and not location + '/' in parser:
1246
parser[location] = {}
1247
elif location + '/' in parser:
1248
location = location + '/'
1249
parser[location][option]=value
1250
# the allowed values of store match the config policies
1251
self._set_option_policy(location, option, store)
1252
self._write_config_file()
1253
for hook in OldConfigHooks['set']:
1254
hook(self, option, value)
1229
1257
class BranchConfig(Config):
1395
1424
return self._get_best_value('_acceptable_keys')
1427
def ensure_config_dir_exists(path=None):
1428
"""Make sure a configuration directory exists.
1429
This makes sure that the directory exists.
1430
On windows, since configuration directories are 2 levels deep,
1431
it makes sure both the directory and the parent directory exists.
1435
if not os.path.isdir(path):
1436
if sys.platform == 'win32':
1437
parent_dir = os.path.dirname(path)
1438
if not os.path.isdir(parent_dir):
1439
trace.mutter('creating config parent directory: %r', parent_dir)
1440
os.mkdir(parent_dir)
1441
trace.mutter('creating config directory: %r', path)
1443
osutils.copy_ownership_from_path(path)
1446
def bazaar_config_dir():
1447
"""Return per-user configuration directory as unicode string
1449
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1450
and Linux. On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1451
that will be used instead.
1453
TODO: Global option --config-dir to override this.
1455
base = osutils.path_from_environ('BZR_HOME')
1456
if sys.platform == 'win32':
1458
base = win32utils.get_appdata_location()
1460
base = win32utils.get_home_location()
1461
# GZ 2012-02-01: Really the two level subdirs only make sense inside
1462
# APPDATA, but hard to move. See bug 348640 for more.
1463
return osutils.pathjoin(base, 'bazaar', '2.0')
1465
xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1467
xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1468
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1469
if osutils.isdir(xdg_dir):
1471
"Using configuration in XDG directory %s." % xdg_dir)
1473
base = osutils._get_home_dir()
1474
return osutils.pathjoin(base, ".bazaar")
1478
"""Return per-user configuration directory as unicode string
1480
By default this is %APPDATA%/breezy on Windows, $XDG_CONFIG_HOME/breezy on
1481
Mac OS X and Linux. If the breezy config directory doesn't exist but
1482
the bazaar one (see bazaar_config_dir()) does, use that instead.
1484
TODO: Global option --config-dir to override this.
1486
base = osutils.path_from_environ('BRZ_HOME')
1487
if sys.platform == 'win32':
1489
base = win32utils.get_appdata_location()
1491
base = win32utils.get_home_location()
1492
# GZ 2012-02-01: Really the two level subdirs only make sense inside
1493
# APPDATA, but hard to move. See bug 348640 for more.
1495
base = osutils.path_from_environ('XDG_CONFIG_HOME')
1497
base = osutils.pathjoin(osutils._get_home_dir(), ".config")
1498
breezy_dir = osutils.pathjoin(base, 'breezy')
1499
if osutils.isdir(breezy_dir):
1501
# If the breezy directory doesn't exist, but the bazaar one does, use that:
1502
bazaar_dir = bazaar_config_dir()
1503
if osutils.isdir(bazaar_dir):
1505
"Using Bazaar configuration directory (%s)", bazaar_dir)
1510
def config_filename():
1511
"""Return per-user configuration ini file filename."""
1512
return osutils.pathjoin(config_dir(), 'bazaar.conf')
1515
def locations_config_filename():
1516
"""Return per-user configuration ini file filename."""
1517
return osutils.pathjoin(config_dir(), 'locations.conf')
1520
def authentication_config_filename():
1521
"""Return per-user authentication ini file filename."""
1522
return osutils.pathjoin(config_dir(), 'authentication.conf')
1525
def user_ignore_config_filename():
1526
"""Return the user default ignore filename"""
1527
return osutils.pathjoin(config_dir(), 'ignore')
1531
"""Return the directory name to store crash files.
1533
This doesn't implicitly create it.
1535
On Windows it's in the config directory; elsewhere it's /var/crash
1536
which may be monitored by apport. It can be overridden by
1539
if sys.platform == 'win32':
1540
return osutils.pathjoin(config_dir(), 'Crash')
1542
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1544
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1547
def xdg_cache_dir():
1548
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1549
# Possibly this should be different on Windows?
1550
e = os.environ.get('XDG_CACHE_HOME', None)
1554
return os.path.expanduser('~/.cache')
1557
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1558
"""If possible, return the assumed default email domain.
1560
:returns: string mail domain, or None.
1562
if sys.platform == 'win32':
1563
# No implementation yet; patches welcome
1566
f = open(mailname_file)
1567
except (IOError, OSError) as e:
1570
domain = f.readline().strip()
1576
def default_email():
1577
v = os.environ.get('BRZ_EMAIL')
1580
v = v.decode(osutils.get_user_encoding())
1582
v = os.environ.get('EMAIL')
1585
v = v.decode(osutils.get_user_encoding())
1587
name, email = _auto_user_id()
1589
return u'%s <%s>' % (name, email)
1595
def _auto_user_id():
1596
"""Calculate automatic user identification.
1598
:returns: (realname, email), either of which may be None if they can't be
1601
Only used when none is set in the environment or the id file.
1603
This only returns an email address if we can be fairly sure the
1604
address is reasonable, ie if /etc/mailname is set on unix.
1606
This doesn't use the FQDN as the default domain because that may be
1607
slow, and it doesn't use the hostname alone because that's not normally
1608
a reasonable address.
1610
if sys.platform == 'win32':
1611
# No implementation to reliably determine Windows default mail
1612
# address; please add one.
1615
default_mail_domain = _get_default_mail_domain()
1616
if not default_mail_domain:
1622
w = pwd.getpwuid(uid)
1624
trace.mutter('no passwd entry for uid %d?' % uid)
1627
# we try utf-8 first, because on many variants (like Linux),
1628
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
1629
# false positives. (many users will have their user encoding set to
1630
# latin-1, which cannot raise UnicodeError.)
1632
gecos = w.pw_gecos.decode('utf-8')
1634
except UnicodeError:
1636
encoding = osutils.get_user_encoding()
1637
gecos = w.pw_gecos.decode(encoding)
1638
except UnicodeError as e:
1639
trace.mutter("cannot decode passwd entry %s" % w)
1642
username = w.pw_name.decode(encoding)
1643
except UnicodeError as e:
1644
trace.mutter("cannot decode passwd entry %s" % w)
1647
comma = gecos.find(',')
1651
realname = gecos[:comma]
1653
return realname, (username + '@' + default_mail_domain)
1398
1656
def parse_username(username):
1399
1657
"""Parse e-mail username and return a (name, address) tuple."""
1400
1658
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1401
1659
if match is None:
1402
1660
return (username, '')
1403
return (match.group(1), match.group(2))
1662
return (match.group(1), match.group(2))
1406
1665
def extract_email_address(e):
1498
1766
trace.mutter('Unable to stat %r: %r', self._filename, e)
1500
1768
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):
1769
if ((stat.S_IXOTH | stat.S_IWOTH | stat.S_IROTH | stat.S_IXGRP |
1770
stat.S_IWGRP | stat.S_IRGRP ) & mode):
1503
1771
# Only warn once
1504
if (self._filename not in _authentication_config_permission_errors and
1505
not GlobalConfig().suppress_warning(
1772
if (not self._filename in _authentication_config_permission_errors
1773
and not GlobalConfig().suppress_warning(
1506
1774
'insecure_permissions')):
1507
1775
trace.warning("The file '%s' has insecure "
1508
"file permissions. Saved passwords may be accessible "
1509
"by other users.", self._filename)
1776
"file permissions. Saved passwords may be accessible "
1777
"by other users.", self._filename)
1510
1778
_authentication_config_permission_errors.add(self._filename)
1512
1780
def _save(self):
1513
1781
"""Save the config file, only tests should use it for now."""
1514
1782
conf_dir = os.path.dirname(self._filename)
1515
bedding.ensure_config_dir_exists(conf_dir)
1516
fd = os.open(self._filename, os.O_RDWR | os.O_CREAT, 0o600)
1783
ensure_config_dir_exists(conf_dir)
1784
fd = os.open(self._filename, os.O_RDWR|os.O_CREAT, 0o600)
1518
1786
f = os.fdopen(fd, 'wb')
1519
1787
self._get_config().write(f)
2507
2760
option_registry.register(
2508
2761
ListOption('debug_flags', default=[],
2509
help='Debug flags to activate.'))
2762
help='Debug flags to activate.'))
2510
2763
option_registry.register(
2511
2764
Option('default_format', default='2a',
2512
2765
help='Format used when creating branches.'))
2513
2766
option_registry.register(
2767
Option('dpush_strict', default=None,
2768
from_unicode=bool_from_store,
2770
The default value for ``dpush --strict``.
2772
If present, defines the ``--strict`` option default value for checking
2773
uncommitted changes before pushing into a different VCS without any
2774
custom bzr metadata.
2776
option_registry.register(
2514
2777
Option('editor',
2515
2778
help='The command called to launch an editor to enter a message.'))
2516
2779
option_registry.register(
2517
Option('email', override_from_env=['BRZ_EMAIL', 'BZR_EMAIL'],
2518
default=bedding.default_email, help='The users identity'))
2780
Option('email', override_from_env=['BRZ_EMAIL'], default=default_email,
2781
help='The users identity'))
2519
2782
option_registry.register(
2520
2783
Option('gpg_signing_key',