55
55
turns on create_signatures.
56
56
create_signatures - this option controls whether bzr will always create
57
57
gpg signatures or not on commits. There is an unused
58
option which in future is expected to work if
58
option which in future is expected to work if
59
59
branch settings require signatures.
60
60
log_format - this option sets the default log format. Possible values are
61
61
long, short, line, or a plugin can register new formats.
241
239
return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
244
def get_mail_client(self):
245
"""Get a mail client to use"""
246
selected_client = self.get_user_option('mail_client')
247
_registry = mail_client.mail_client_registry
249
mail_client_class = _registry.get(selected_client)
251
raise errors.UnknownMailClient(selected_client)
252
return mail_client_class(self)
254
242
def _get_signature_checking(self):
255
243
"""Template method to override signature checking policy."""
1527
1515
def config_dir():
1528
"""Return per-user configuration directory.
1516
"""Return per-user configuration directory as unicode string
1530
1518
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1531
1519
and Linux. On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1534
1522
TODO: Global option --config-dir to override this.
1536
base = os.environ.get('BZR_HOME', None)
1524
base = osutils.path_from_environ('BZR_HOME')
1537
1525
if sys.platform == 'win32':
1538
# environ variables on Windows are in user encoding/mbcs. So decode
1540
if base is not None:
1541
base = base.decode('mbcs')
1543
base = win32utils.get_appdata_location_unicode()
1545
base = os.environ.get('HOME', None)
1546
if base is not None:
1547
base = base.decode('mbcs')
1549
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1527
base = win32utils.get_appdata_location()
1529
base = win32utils.get_home_location()
1530
# GZ 2012-02-01: Really the two level subdirs only make sense inside
1531
# APPDATA, but hard to move. See bug 348640 for more.
1551
1532
return osutils.pathjoin(base, 'bazaar', '2.0')
1553
if base is not None:
1554
base = base.decode(osutils._fs_enc)
1555
if sys.platform == 'darwin':
1557
# this takes into account $HOME
1558
base = os.path.expanduser("~")
1559
return osutils.pathjoin(base, '.bazaar')
1562
xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1534
# GZ 2012-02-01: What should OSX use instead of XDG if anything?
1535
if sys.platform != 'darwin':
1536
xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1563
1537
if xdg_dir is None:
1564
xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1538
xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1565
1539
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1566
1540
if osutils.isdir(xdg_dir):
1568
1542
"Using configuration in XDG directory %s." % xdg_dir)
1570
base = os.path.expanduser("~")
1571
return osutils.pathjoin(base, ".bazaar")
1544
base = osutils._get_home_dir()
1545
return osutils.pathjoin(base, ".bazaar")
1574
1548
def config_filename():
2397
2371
raise AssertionError('%r is not supported as a default value'
2399
2373
self.default_from_env = default_from_env
2401
2375
self.from_unicode = from_unicode
2402
2376
self.unquote = unquote
2403
2377
if invalid and invalid not in ('warning', 'error'):
2404
2378
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2405
2379
self.invalid = invalid
2407
2385
def convert_from_unicode(self, store, unicode_value):
2408
2386
if self.unquote and store is not None and unicode_value is not None:
2409
2387
unicode_value = store.unquote(unicode_value)
2530
class RegistryOption(Option):
2531
"""Option for a choice from a registry."""
2533
def __init__(self, name, registry, default_from_env=None,
2534
help=None, invalid=None):
2535
"""A registry based Option definition.
2537
This overrides the base class so the conversion from a unicode string
2538
can take quoting into account.
2540
super(RegistryOption, self).__init__(
2541
name, default=lambda: unicode(registry.default_key),
2542
default_from_env=default_from_env,
2543
from_unicode=self.from_unicode, help=help,
2544
invalid=invalid, unquote=False)
2545
self.registry = registry
2547
def from_unicode(self, unicode_str):
2548
if not isinstance(unicode_str, basestring):
2551
return self.registry.get(unicode_str)
2554
"Invalid value %s for %s."
2555
"See help for a list of possible values." % (unicode_str,
2560
ret = [self._help, "\n\nThe following values are supported:\n"]
2561
for key in self.registry.keys():
2562
ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
2552
2566
class OptionRegistry(registry.Registry):
2553
2567
"""Register config options by their name.
2645
2659
Whether revisions associated with tags should be fetched.
2661
option_registry.register_lazy(
2662
'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2647
2663
option_registry.register(
2648
2664
Option('bzr.workingtree.worth_saving_limit', default=10,
2649
2665
from_unicode=int_from_store, invalid='warning',
2657
2673
a file has been touched.
2659
2675
option_registry.register(
2676
Option('bugtracker', default=None,
2678
Default bug tracker to use.
2680
This bug tracker will be used for example when marking bugs
2681
as fixed using ``bzr commit --fixes``, if no explicit
2682
bug tracker was specified.
2684
option_registry.register(
2660
2685
Option('check_signatures', default=CHECK_IF_POSSIBLE,
2661
2686
from_unicode=signature_policy_from_unicode,
2764
2789
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2765
2790
may be provided by plugins.
2792
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
2767
2794
option_registry.register(
2768
2795
Option('output_encoding',
2769
2796
help= 'Unicode encoding for output'
2866
2893
option_registry.register(
2867
2894
Option('submit_to',
2868
2895
help='''Where submissions from this branch are mailed to.'''))
2896
option_registry.register(
2897
ListOption('suppress_warnings',
2899
help="List of warning classes to suppress."))
2900
option_registry.register(
2901
Option('validate_signatures_in_log', default=False,
2902
from_unicode=bool_from_store, invalid='warning',
2903
help='''Whether to validate signatures in bzr log.'''))
2904
option_registry.register_lazy('ssl.ca_certs',
2905
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2907
option_registry.register_lazy('ssl.cert_reqs',
2908
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2871
2911
class Section(object):
3114
3154
class IniFileStore(Store):
3115
3155
"""A config Store using ConfigObj for storage.
3117
:ivar transport: The transport object where the config file is located.
3119
:ivar file_name: The config file basename in the transport directory.
3121
3157
:ivar _config_obj: Private member to hold the ConfigObj instance used to
3122
3158
serialize/deserialize the config file.
3253
3289
value = self._config_obj._unquote(value)
3292
def external_url(self):
3293
# Since an IniFileStore can be used without a file (at least in tests),
3294
# it's better to provide something than raising a NotImplementedError.
3295
# All daughter classes are supposed to provide an implementation
3297
return 'In-Process Store, no URL'
3257
3299
class TransportIniFileStore(IniFileStore):
3258
3300
"""IniFileStore that loads files from a transport.
3302
:ivar transport: The transport object where the config file is located.
3304
:ivar file_name: The config file basename in the transport directory.
3261
3307
def __init__(self, transport, file_name):
3422
3468
class LocationSection(Section):
3424
def __init__(self, section, length, extra_path):
3470
def __init__(self, section, extra_path):
3425
3471
super(LocationSection, self).__init__(section.id, section.options)
3426
self.length = length
3427
3472
self.extra_path = extra_path
3428
3473
self.locals = {'relpath': extra_path,
3429
3474
'basename': urlutils.basename(extra_path)}
3499
class StartingPathMatcher(SectionMatcher):
3500
"""Select sections for a given location respecting the Store order."""
3502
# FIXME: Both local paths and urls can be used for section names as well as
3503
# ``location`` to stay consistent with ``LocationMatcher`` which itself
3504
# inherited the fuzziness from the previous ``LocationConfig``
3505
# implementation. We probably need to revisit which encoding is allowed for
3506
# both ``location`` and section names and how we normalize
3507
# them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
3508
# related too. -- vila 2012-01-04
3510
def __init__(self, store, location):
3511
super(StartingPathMatcher, self).__init__(store)
3512
if location.startswith('file://'):
3513
location = urlutils.local_path_from_url(location)
3514
self.location = location
3516
def get_sections(self):
3517
"""Get all sections matching ``location`` in the store.
3519
The most generic sections are described first in the store, then more
3520
specific ones can be provided for reduced scopes.
3522
The returned section are therefore returned in the reversed order so
3523
the most specific ones can be found first.
3525
location_parts = self.location.rstrip('/').split('/')
3528
# Later sections are more specific, they should be returned first
3529
for _, section in reversed(list(store.get_sections())):
3530
if section.id is None:
3531
# The no-name section is always included if present
3532
yield store, LocationSection(section, self.location)
3534
section_path = section.id
3535
if section_path.startswith('file://'):
3536
# the location is already a local path or URL, convert the
3537
# section id to the same format
3538
section_path = urlutils.local_path_from_url(section_path)
3539
if (self.location.startswith(section_path)
3540
or fnmatch.fnmatch(self.location, section_path)):
3541
section_parts = section_path.rstrip('/').split('/')
3542
extra_path = '/'.join(location_parts[len(section_parts):])
3543
yield store, LocationSection(section, extra_path)
3454
3546
class LocationMatcher(SectionMatcher):
3456
3548
def __init__(self, store, location):
3480
3572
matching_sections = []
3481
3573
if no_name_section is not None:
3482
3574
matching_sections.append(
3483
LocationSection(no_name_section, 0, self.location))
3575
(0, LocationSection(no_name_section, self.location)))
3484
3576
for section_id, extra_path, length in filtered_sections:
3485
3577
# a section id is unique for a given store so it's safe to take the
3486
3578
# first matching section while iterating. Also, all filtered
3490
3582
section = iter_all_sections.next()
3491
3583
if section_id == section.id:
3492
3584
matching_sections.append(
3493
LocationSection(section, length, extra_path))
3585
(length, LocationSection(section, extra_path)))
3495
3587
return matching_sections
3499
3591
matching_sections = self._get_matching_sections()
3500
3592
# We want the longest (aka more specific) locations first
3501
3593
sections = sorted(matching_sections,
3502
key=lambda section: (section.length, section.id),
3594
key=lambda (length, section): (length, section.id),
3504
3596
# Sections mentioning 'ignore_parents' restrict the selection
3505
for section in sections:
3597
for _, section in sections:
3506
3598
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3507
3599
ignore = section.get('ignore_parents', None)
3508
3600
if ignore is not None: