~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2011-10-04 22:20:49 UTC
  • mto: This revision was merged to the branch mainline in revision 6190.
  • Revision ID: jelmer@samba.org-20111004222049-d9glniyleu0pppzd
Add a load_plugin_translations method.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
log_format=name-of-format
32
32
validate_signatures_in_log=true|false(default)
33
33
acceptable_keys=pattern1,pattern2
 
34
gpg_signing_key=amy@example.com
34
35
 
35
36
in locations.conf, you specify the url of a branch and options for it.
36
37
Wildcards may be used - * and ? as normal in shell completion. Options
76
77
import sys
77
78
 
78
79
 
 
80
import bzrlib
79
81
from bzrlib.decorators import needs_write_lock
80
82
from bzrlib.lazy_import import lazy_import
81
83
lazy_import(globals(), """
89
91
    debug,
90
92
    errors,
91
93
    lazy_regex,
 
94
    library_state,
92
95
    lockdir,
93
96
    mail_client,
94
97
    mergetools,
100
103
    urlutils,
101
104
    win32utils,
102
105
    )
 
106
from bzrlib.i18n import gettext
103
107
from bzrlib.util.configobj import configobj
104
108
""")
105
109
from bzrlib import (
106
110
    commands,
107
111
    hooks,
 
112
    lazy_regex,
108
113
    registry,
109
114
    )
110
115
from bzrlib.symbol_versioning import (
171
176
# FIXME: Until we can guarantee that each config file is loaded once and
172
177
# only once for a given bzrlib session, we don't want to re-read the file every
173
178
# time we query for an option so we cache the value (bad ! watch out for tests
174
 
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
175
 
# yell at mgz^W vila and the RM if this is still present at that time
176
 
# -- vila 20110219
 
179
# needing to restore the proper value). -- vila 20110219
177
180
_expand_default_value = None
178
181
def _get_expand_default_value():
179
182
    global _expand_default_value
414
417
            # add) the final ','
415
418
            l = [l]
416
419
        return l
 
420
        
 
421
    def get_user_option_as_int_from_SI(self,  option_name,  default=None):
 
422
        """Get a generic option from a human readable size in SI units, e.g 10MB
 
423
        
 
424
        Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
425
        by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
426
        pedantic.
 
427
        
 
428
        :return Integer, expanded to its base-10 value if a proper SI unit is 
 
429
            found. If the option doesn't exist, or isn't a value in 
 
430
            SI units, return default (which defaults to None)
 
431
        """
 
432
        val = self.get_user_option(option_name)
 
433
        if isinstance(val, list):
 
434
            val = val[0]
 
435
        if val is None:
 
436
            val = default
 
437
        else:
 
438
            p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
 
439
            try:
 
440
                m = p.match(val)
 
441
                if m is not None:
 
442
                    val = int(m.group(1))
 
443
                    if m.group(2) is not None:
 
444
                        if m.group(2).lower() == 'k':
 
445
                            val *= 10**3
 
446
                        elif m.group(2).lower() == 'm':
 
447
                            val *= 10**6
 
448
                        elif m.group(2).lower() == 'g':
 
449
                            val *= 10**9
 
450
                else:
 
451
                    ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
 
452
                                               ' value {1!r} is not an SI unit.').format(
 
453
                                                option_name, val))
 
454
                    val = default
 
455
            except TypeError:
 
456
                val = default
 
457
        return val
 
458
        
417
459
 
418
460
    def gpg_signing_command(self):
419
461
        """What program should be used to sign signatures?"""
536
578
            return True
537
579
        return False
538
580
 
 
581
    def gpg_signing_key(self):
 
582
        """GPG user-id to sign commits"""
 
583
        key = self.get_user_option('gpg_signing_key')
 
584
        if key == "default" or key == None:
 
585
            return self.user_email()
 
586
        else:
 
587
            return key
 
588
 
539
589
    def get_alias(self, value):
540
590
        return self._get_alias(value)
541
591
 
575
625
        for (oname, value, section, conf_id, parser) in self._get_options():
576
626
            if oname.startswith('bzr.mergetool.'):
577
627
                tool_name = oname[len('bzr.mergetool.'):]
578
 
                tools[tool_name] = value
 
628
                tools[tool_name] = self.get_user_option(oname)
579
629
        trace.mutter('loaded merge tools: %r' % tools)
580
630
        return tools
581
631
 
978
1028
        # local transports are not shared. But if/when we start using
979
1029
        # LockableConfig for other kind of transports, we will need to reuse
980
1030
        # whatever connection is already established -- vila 20100929
981
 
        self.transport = transport.get_transport(self.dir)
 
1031
        self.transport = transport.get_transport_from_path(self.dir)
982
1032
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
983
1033
 
984
1034
    def _create_from_string(self, unicode_bytes, save):
1350
1400
            return (self.branch._transport.get_bytes("email")
1351
1401
                    .decode(osutils.get_user_encoding())
1352
1402
                    .rstrip("\r\n"))
1353
 
        except errors.NoSuchFile, e:
 
1403
        except (errors.NoSuchFile, errors.PermissionDenied), e:
1354
1404
            pass
1355
1405
 
1356
1406
        return self._get_best_value('_get_user_id')
1504
1554
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1505
1555
                                  ' or HOME set')
1506
1556
        return osutils.pathjoin(base, 'bazaar', '2.0')
1507
 
    elif sys.platform == 'darwin':
 
1557
    else:
 
1558
        if base is not None:
 
1559
            base = base.decode(osutils._fs_enc)
 
1560
    if sys.platform == 'darwin':
1508
1561
        if base is None:
1509
1562
            # this takes into account $HOME
1510
1563
            base = os.path.expanduser("~")
1511
1564
        return osutils.pathjoin(base, '.bazaar')
1512
1565
    else:
1513
1566
        if base is None:
1514
 
 
1515
1567
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1516
1568
            if xdg_dir is None:
1517
1569
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1520
1572
                trace.mutter(
1521
1573
                    "Using configuration in XDG directory %s." % xdg_dir)
1522
1574
                return xdg_dir
1523
 
 
1524
1575
            base = os.path.expanduser("~")
1525
1576
        return osutils.pathjoin(base, ".bazaar")
1526
1577
 
2230
2281
            return f
2231
2282
        except errors.NoSuchFile:
2232
2283
            return StringIO()
 
2284
        except errors.PermissionDenied, e:
 
2285
            trace.warning("Permission denied while trying to open "
 
2286
                "configuration file %s.", urlutils.unescape_for_display(
 
2287
                urlutils.join(self._transport.base, self._filename), "utf-8"))
 
2288
            return StringIO()
2233
2289
 
2234
2290
    def _external_url(self):
2235
2291
        return urlutils.join(self._transport.external_url(), self._filename)
2262
2318
    The option *values* are stored in config files and found in sections.
2263
2319
 
2264
2320
    Here we define various properties about the option itself, its default
2265
 
    value, in which config files it can be stored, etc (TBC).
 
2321
    value, how to convert it from stores, what to do when invalid values are
 
2322
    encoutered, in which config files it can be stored.
2266
2323
    """
2267
2324
 
2268
 
    def __init__(self, name, default=None):
 
2325
    def __init__(self, name, default=None, default_from_env=None,
 
2326
                 help=None,
 
2327
                 from_unicode=None, invalid=None):
 
2328
        """Build an option definition.
 
2329
 
 
2330
        :param name: the name used to refer to the option.
 
2331
 
 
2332
        :param default: the default value to use when none exist in the config
 
2333
            stores. This is either a string that ``from_unicode`` will convert
 
2334
            into the proper type or a python object that can be stringified (so
 
2335
            only the empty list is supported for example).
 
2336
 
 
2337
        :param default_from_env: A list of environment variables which can
 
2338
           provide a default value. 'default' will be used only if none of the
 
2339
           variables specified here are set in the environment.
 
2340
 
 
2341
        :param help: a doc string to explain the option to the user.
 
2342
 
 
2343
        :param from_unicode: a callable to convert the unicode string
 
2344
            representing the option value in a store. This is not called for
 
2345
            the default value.
 
2346
 
 
2347
        :param invalid: the action to be taken when an invalid value is
 
2348
            encountered in a store. This is called only when from_unicode is
 
2349
            invoked to convert a string and returns None or raise ValueError or
 
2350
            TypeError. Accepted values are: None (ignore invalid values),
 
2351
            'warning' (emit a warning), 'error' (emit an error message and
 
2352
            terminates).
 
2353
        """
 
2354
        if default_from_env is None:
 
2355
            default_from_env = []
2269
2356
        self.name = name
2270
 
        self.default = default
 
2357
        # Convert the default value to a unicode string so all values are
 
2358
        # strings internally before conversion (via from_unicode) is attempted.
 
2359
        if default is None:
 
2360
            self.default = None
 
2361
        elif isinstance(default, list):
 
2362
            # Only the empty list is supported
 
2363
            if default:
 
2364
                raise AssertionError(
 
2365
                    'Only empty lists are supported as default values')
 
2366
            self.default = u','
 
2367
        elif isinstance(default, (str, unicode, bool, int, float)):
 
2368
            # Rely on python to convert strings, booleans and integers
 
2369
            self.default = u'%s' % (default,)
 
2370
        else:
 
2371
            # other python objects are not expected
 
2372
            raise AssertionError('%r is not supported as a default value'
 
2373
                                 % (default,))
 
2374
        self.default_from_env = default_from_env
 
2375
        self.help = help
 
2376
        self.from_unicode = from_unicode
 
2377
        if invalid and invalid not in ('warning', 'error'):
 
2378
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
 
2379
        self.invalid = invalid
 
2380
 
 
2381
    def convert_from_unicode(self, unicode_value):
 
2382
        if self.from_unicode is None or unicode_value is None:
 
2383
            # Don't convert or nothing to convert
 
2384
            return unicode_value
 
2385
        try:
 
2386
            converted = self.from_unicode(unicode_value)
 
2387
        except (ValueError, TypeError):
 
2388
            # Invalid values are ignored
 
2389
            converted = None
 
2390
        if converted is None and self.invalid is not None:
 
2391
            # The conversion failed
 
2392
            if self.invalid == 'warning':
 
2393
                trace.warning('Value "%s" is not valid for "%s"',
 
2394
                              unicode_value, self.name)
 
2395
            elif self.invalid == 'error':
 
2396
                raise errors.ConfigOptionValueError(self.name, unicode_value)
 
2397
        return converted
2271
2398
 
2272
2399
    def get_default(self):
2273
 
        return self.default
2274
 
 
2275
 
 
2276
 
# Options registry
2277
 
 
2278
 
option_registry = registry.Registry()
2279
 
 
2280
 
 
2281
 
option_registry.register(
2282
 
    'editor', Option('editor'),
2283
 
    help='The command called to launch an editor to enter a message.')
 
2400
        value = None
 
2401
        for var in self.default_from_env:
 
2402
            try:
 
2403
                # If the env variable is defined, its value is the default one
 
2404
                value = os.environ[var]
 
2405
                break
 
2406
            except KeyError:
 
2407
                continue
 
2408
        if value is None:
 
2409
            # Otherwise, fallback to the value defined at registration
 
2410
            value = self.default
 
2411
        return value
 
2412
 
 
2413
    def get_help_text(self, additional_see_also=None, plain=True):
 
2414
        result = self.help
 
2415
        from bzrlib import help_topics
 
2416
        result += help_topics._format_see_also(additional_see_also)
 
2417
        if plain:
 
2418
            result = help_topics.help_as_plain_text(result)
 
2419
        return result
 
2420
 
 
2421
 
 
2422
# Predefined converters to get proper values from store
 
2423
 
 
2424
def bool_from_store(unicode_str):
 
2425
    return ui.bool_from_string(unicode_str)
 
2426
 
 
2427
 
 
2428
def int_from_store(unicode_str):
 
2429
    return int(unicode_str)
 
2430
 
 
2431
 
 
2432
def float_from_store(unicode_str):
 
2433
    return float(unicode_str)
 
2434
 
 
2435
 
 
2436
 
 
2437
# Use a an empty dict to initialize an empty configobj avoiding all
 
2438
# parsing and encoding checks
 
2439
_list_converter_config = configobj.ConfigObj(
 
2440
    {}, encoding='utf-8', list_values=True, interpolation=False)
 
2441
 
 
2442
 
 
2443
def list_from_store(unicode_str):
 
2444
    if not isinstance(unicode_str, basestring):
 
2445
        raise TypeError
 
2446
    # Now inject our string directly as unicode. All callers got their value
 
2447
    # from configobj, so values that need to be quoted are already properly
 
2448
    # quoted.
 
2449
    _list_converter_config.reset()
 
2450
    _list_converter_config._parse([u"list=%s" % (unicode_str,)])
 
2451
    maybe_list = _list_converter_config['list']
 
2452
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
 
2453
    if isinstance(maybe_list, basestring):
 
2454
        if maybe_list:
 
2455
            # A single value, most probably the user forgot (or didn't care to
 
2456
            # add) the final ','
 
2457
            l = [maybe_list]
 
2458
        else:
 
2459
            # The empty string, convert to empty list
 
2460
            l = []
 
2461
    else:
 
2462
        # We rely on ConfigObj providing us with a list already
 
2463
        l = maybe_list
 
2464
    return l
 
2465
 
 
2466
 
 
2467
class OptionRegistry(registry.Registry):
 
2468
    """Register config options by their name.
 
2469
 
 
2470
    This overrides ``registry.Registry`` to simplify registration by acquiring
 
2471
    some information from the option object itself.
 
2472
    """
 
2473
 
 
2474
    def register(self, option):
 
2475
        """Register a new option to its name.
 
2476
 
 
2477
        :param option: The option to register. Its name is used as the key.
 
2478
        """
 
2479
        super(OptionRegistry, self).register(option.name, option,
 
2480
                                             help=option.help)
 
2481
 
 
2482
    def register_lazy(self, key, module_name, member_name):
 
2483
        """Register a new option to be loaded on request.
 
2484
 
 
2485
        :param key: the key to request the option later. Since the registration
 
2486
            is lazy, it should be provided and match the option name.
 
2487
 
 
2488
        :param module_name: the python path to the module. Such as 'os.path'.
 
2489
 
 
2490
        :param member_name: the member of the module to return.  If empty or 
 
2491
                None, get() will return the module itself.
 
2492
        """
 
2493
        super(OptionRegistry, self).register_lazy(key,
 
2494
                                                  module_name, member_name)
 
2495
 
 
2496
    def get_help(self, key=None):
 
2497
        """Get the help text associated with the given key"""
 
2498
        option = self.get(key)
 
2499
        the_help = option.help
 
2500
        if callable(the_help):
 
2501
            return the_help(self, key)
 
2502
        return the_help
 
2503
 
 
2504
 
 
2505
option_registry = OptionRegistry()
 
2506
 
 
2507
 
 
2508
# Registered options in lexicographical order
 
2509
 
 
2510
option_registry.register(
 
2511
    Option('bzr.workingtree.worth_saving_limit', default=10,
 
2512
           from_unicode=int_from_store,  invalid='warning',
 
2513
           help='''\
 
2514
How many changes before saving the dirstate.
 
2515
 
 
2516
-1 means that we will never rewrite the dirstate file for only
 
2517
stat-cache changes. Regardless of this setting, we will always rewrite
 
2518
the dirstate file if a file is added/removed/renamed/etc. This flag only
 
2519
affects the behavior of updating the dirstate file after we notice that
 
2520
a file has been touched.
 
2521
'''))
 
2522
option_registry.register(
 
2523
    Option('dirstate.fdatasync', default=True,
 
2524
           from_unicode=bool_from_store,
 
2525
           help='''\
 
2526
Flush dirstate changes onto physical disk?
 
2527
 
 
2528
If true (default), working tree metadata changes are flushed through the
 
2529
OS buffers to physical disk.  This is somewhat slower, but means data
 
2530
should not be lost if the machine crashes.  See also repository.fdatasync.
 
2531
'''))
 
2532
option_registry.register(
 
2533
    Option('debug_flags', default=[], from_unicode=list_from_store,
 
2534
           help='Debug flags to activate.'))
 
2535
option_registry.register(
 
2536
    Option('default_format', default='2a',
 
2537
           help='Format used when creating branches.'))
 
2538
option_registry.register(
 
2539
    Option('dpush_strict', default=None,
 
2540
           from_unicode=bool_from_store,
 
2541
           help='''\
 
2542
The default value for ``dpush --strict``.
 
2543
 
 
2544
If present, defines the ``--strict`` option default value for checking
 
2545
uncommitted changes before pushing into a different VCS without any
 
2546
custom bzr metadata.
 
2547
'''))
 
2548
option_registry.register(
 
2549
    Option('editor',
 
2550
           help='The command called to launch an editor to enter a message.'))
 
2551
option_registry.register(
 
2552
    Option('ignore_missing_extensions', default=False,
 
2553
           from_unicode=bool_from_store,
 
2554
           help='''\
 
2555
Control the missing extensions warning display.
 
2556
 
 
2557
The warning will not be emitted if set to True.
 
2558
'''))
 
2559
option_registry.register(
 
2560
    Option('language',
 
2561
           help='Language to translate messages into.'))
 
2562
option_registry.register(
 
2563
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
 
2564
           help='''\
 
2565
Steal locks that appears to be dead.
 
2566
 
 
2567
If set to True, bzr will check if a lock is supposed to be held by an
 
2568
active process from the same user on the same machine. If the user and
 
2569
machine match, but no process with the given PID is active, then bzr
 
2570
will automatically break the stale lock, and create a new lock for
 
2571
this process.
 
2572
Otherwise, bzr will prompt as normal to break the lock.
 
2573
'''))
 
2574
option_registry.register(
 
2575
    Option('output_encoding',
 
2576
           help= 'Unicode encoding for output'
 
2577
           ' (terminal encoding if not specified).'))
 
2578
option_registry.register(
 
2579
    Option('push_strict', default=None,
 
2580
           from_unicode=bool_from_store,
 
2581
           help='''\
 
2582
The default value for ``push --strict``.
 
2583
 
 
2584
If present, defines the ``--strict`` option default value for checking
 
2585
uncommitted changes before sending a merge directive.
 
2586
'''))
 
2587
option_registry.register(
 
2588
    Option('repository.fdatasync', default=True,
 
2589
           from_unicode=bool_from_store,
 
2590
           help='''\
 
2591
Flush repository changes onto physical disk?
 
2592
 
 
2593
If true (default), repository changes are flushed through the OS buffers
 
2594
to physical disk.  This is somewhat slower, but means data should not be
 
2595
lost if the machine crashes.  See also dirstate.fdatasync.
 
2596
'''))
 
2597
option_registry.register(
 
2598
    Option('send_strict', default=None,
 
2599
           from_unicode=bool_from_store,
 
2600
           help='''\
 
2601
The default value for ``send --strict``.
 
2602
 
 
2603
If present, defines the ``--strict`` option default value for checking
 
2604
uncommitted changes before pushing.
 
2605
'''))
 
2606
 
 
2607
option_registry.register(
 
2608
    Option('serve.client_timeout',
 
2609
           default=300.0, from_unicode=float_from_store,
 
2610
           help="If we wait for a new request from a client for more than"
 
2611
                " X seconds, consider the client idle, and hangup."))
2284
2612
 
2285
2613
 
2286
2614
class Section(object):
2329
2657
        del self.options[name]
2330
2658
 
2331
2659
 
 
2660
class CommandLineSection(MutableSection):
 
2661
    """A section used to carry command line overrides for the config options."""
 
2662
 
 
2663
    def __init__(self, opts=None):
 
2664
        if opts is None:
 
2665
            opts = {}
 
2666
        super(CommandLineSection, self).__init__('cmdline-overrides', opts)
 
2667
 
 
2668
    def _reset(self):
 
2669
        # The dict should be cleared but not replaced so it can be shared.
 
2670
        self.options.clear()
 
2671
 
 
2672
    def _from_cmdline(self, overrides):
 
2673
        # Reset before accepting new definitions
 
2674
        self._reset()
 
2675
        for over in overrides:
 
2676
            try:
 
2677
                name, value = over.split('=', 1)
 
2678
            except ValueError:
 
2679
                raise errors.BzrCommandError(
 
2680
                    gettext("Invalid '%s', should be of the form 'name=value'")
 
2681
                    % (over,))
 
2682
            self.set(name, value)
 
2683
 
 
2684
 
2332
2685
class Store(object):
2333
2686
    """Abstract interface to persistent storage for configuration options."""
2334
2687
 
2423
2776
        """Load the store from the associated file."""
2424
2777
        if self.is_loaded():
2425
2778
            return
2426
 
        content = self.transport.get_bytes(self.file_name)
 
2779
        try:
 
2780
            content = self.transport.get_bytes(self.file_name)
 
2781
        except errors.PermissionDenied:
 
2782
            trace.warning("Permission denied while trying to load "
 
2783
                          "configuration store %s.", self.external_url())
 
2784
            raise
2427
2785
        self._load_from_string(content)
2428
2786
        for hook in ConfigHooks['load']:
2429
2787
            hook(self)
2438
2796
        co_input = StringIO(bytes)
2439
2797
        try:
2440
2798
            # The config files are always stored utf8-encoded
2441
 
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
 
2799
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
 
2800
                                         list_values=False)
2442
2801
        except configobj.ConfigObjError, e:
2443
2802
            self._config_obj = None
2444
2803
            raise errors.ParseConfigError(e.errors, self.external_url())
2471
2830
        # We need a loaded store
2472
2831
        try:
2473
2832
            self.load()
2474
 
        except errors.NoSuchFile:
2475
 
            # If the file doesn't exist, there is no sections
 
2833
        except (errors.NoSuchFile, errors.PermissionDenied):
 
2834
            # If the file can't be read, there is no sections
2476
2835
            return
2477
2836
        cobj = self._config_obj
2478
2837
        if cobj.scalars:
2553
2912
class GlobalStore(LockableIniFileStore):
2554
2913
 
2555
2914
    def __init__(self, possible_transports=None):
2556
 
        t = transport.get_transport(config_dir(),
2557
 
                                    possible_transports=possible_transports)
 
2915
        t = transport.get_transport_from_path(
 
2916
            config_dir(), possible_transports=possible_transports)
2558
2917
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
2559
2918
 
2560
2919
 
2561
2920
class LocationStore(LockableIniFileStore):
2562
2921
 
2563
2922
    def __init__(self, possible_transports=None):
2564
 
        t = transport.get_transport(config_dir(),
2565
 
                                    possible_transports=possible_transports)
 
2923
        t = transport.get_transport_from_path(
 
2924
            config_dir(), possible_transports=possible_transports)
2566
2925
        super(LocationStore, self).__init__(t, 'locations.conf')
2567
2926
 
2568
2927
 
2588
2947
        super(BranchStore, self).save()
2589
2948
 
2590
2949
 
 
2950
class ControlStore(LockableIniFileStore):
 
2951
 
 
2952
    def __init__(self, bzrdir):
 
2953
        super(ControlStore, self).__init__(bzrdir.transport,
 
2954
                                          'control.conf',
 
2955
                                           lock_dir_name='branch_lock')
 
2956
 
 
2957
 
2591
2958
class SectionMatcher(object):
2592
2959
    """Select sections into a given Store.
2593
2960
 
2594
 
    This intended to be used to postpone getting an iterable of sections from a
2595
 
    store.
 
2961
    This is intended to be used to postpone getting an iterable of sections
 
2962
    from a store.
2596
2963
    """
2597
2964
 
2598
2965
    def __init__(self, store):
2607
2974
            if self.match(s):
2608
2975
                yield s
2609
2976
 
2610
 
    def match(self, secion):
 
2977
    def match(self, section):
 
2978
        """Does the proposed section match.
 
2979
 
 
2980
        :param section: A Section object.
 
2981
 
 
2982
        :returns: True if the section matches, False otherwise.
 
2983
        """
2611
2984
        raise NotImplementedError(self.match)
2612
2985
 
2613
2986
 
 
2987
class NameMatcher(SectionMatcher):
 
2988
 
 
2989
    def __init__(self, store, section_id):
 
2990
        super(NameMatcher, self).__init__(store)
 
2991
        self.section_id = section_id
 
2992
 
 
2993
    def match(self, section):
 
2994
        return section.id == self.section_id
 
2995
 
 
2996
 
2614
2997
class LocationSection(Section):
2615
2998
 
2616
2999
    def __init__(self, section, length, extra_path):
2641
3024
        # We slightly diverge from LocalConfig here by allowing the no-name
2642
3025
        # section as the most generic one and the lower priority.
2643
3026
        no_name_section = None
2644
 
        sections = []
 
3027
        all_sections = []
2645
3028
        # Filter out the no_name_section so _iter_for_location_by_parts can be
2646
3029
        # used (it assumes all sections have a name).
2647
3030
        for section in self.store.get_sections():
2648
3031
            if section.id is None:
2649
3032
                no_name_section = section
2650
3033
            else:
2651
 
                sections.append(section)
 
3034
                all_sections.append(section)
2652
3035
        # Unfortunately _iter_for_location_by_parts deals with section names so
2653
3036
        # we have to resync.
2654
3037
        filtered_sections = _iter_for_location_by_parts(
2655
 
            [s.id for s in sections], self.location)
2656
 
        iter_sections = iter(sections)
 
3038
            [s.id for s in all_sections], self.location)
 
3039
        iter_all_sections = iter(all_sections)
2657
3040
        matching_sections = []
2658
3041
        if no_name_section is not None:
2659
3042
            matching_sections.append(
2660
3043
                LocationSection(no_name_section, 0, self.location))
2661
3044
        for section_id, extra_path, length in filtered_sections:
2662
 
            # a section id is unique for a given store so it's safe to iterate
2663
 
            # again
2664
 
            section = iter_sections.next()
2665
 
            if section_id == section.id:
2666
 
                matching_sections.append(
2667
 
                    LocationSection(section, length, extra_path))
 
3045
            # a section id is unique for a given store so it's safe to take the
 
3046
            # first matching section while iterating. Also, all filtered
 
3047
            # sections are part of 'all_sections' and will always be found
 
3048
            # there.
 
3049
            while True:
 
3050
                section = iter_all_sections.next()
 
3051
                if section_id == section.id:
 
3052
                    matching_sections.append(
 
3053
                        LocationSection(section, length, extra_path))
 
3054
                    break
2668
3055
        return matching_sections
2669
3056
 
2670
3057
    def get_sections(self):
2689
3076
class Stack(object):
2690
3077
    """A stack of configurations where an option can be defined"""
2691
3078
 
 
3079
    _option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
 
3080
    """Describes an exandable option reference.
 
3081
 
 
3082
    We want to match the most embedded reference first.
 
3083
 
 
3084
    I.e. for '{{foo}}' we will get '{foo}',
 
3085
    for '{bar{baz}}' we will get '{baz}'
 
3086
    """
 
3087
 
2692
3088
    def __init__(self, sections_def, store=None, mutable_section_name=None):
2693
3089
        """Creates a stack of sections with an optional store for changes.
2694
3090
 
2707
3103
        self.store = store
2708
3104
        self.mutable_section_name = mutable_section_name
2709
3105
 
2710
 
    def get(self, name):
 
3106
    def get(self, name, expand=None):
2711
3107
        """Return the *first* option value found in the sections.
2712
3108
 
2713
3109
        This is where we guarantee that sections coming from Store are loaded
2715
3111
        option exists or get its value, which in turn may require to discover
2716
3112
        in which sections it can be defined. Both of these (section and option
2717
3113
        existence) require loading the store (even partially).
 
3114
 
 
3115
        :param name: The queried option.
 
3116
 
 
3117
        :param expand: Whether options references should be expanded.
 
3118
 
 
3119
        :returns: The value of the option.
2718
3120
        """
2719
3121
        # FIXME: No caching of options nor sections yet -- vila 20110503
 
3122
        if expand is None:
 
3123
            expand = _get_expand_default_value()
2720
3124
        value = None
2721
3125
        # Ensuring lazy loading is achieved by delaying section matching (which
2722
3126
        # implies querying the persistent storage) until it can't be avoided
2734
3138
                    break
2735
3139
            if value is not None:
2736
3140
                break
2737
 
        if value is None:
 
3141
        # If the option is registered, it may provide additional info about
 
3142
        # value handling
 
3143
        try:
 
3144
            opt = option_registry.get(name)
 
3145
        except KeyError:
 
3146
            # Not registered
 
3147
            opt = None
 
3148
        def expand_and_convert(val):
 
3149
            # This may need to be called twice if the value is None or ends up
 
3150
            # being None during expansion or conversion.
 
3151
            if val is not None:
 
3152
                if expand:
 
3153
                    if isinstance(val, basestring):
 
3154
                        val = self._expand_options_in_string(val)
 
3155
                    else:
 
3156
                        trace.warning('Cannot expand "%s":'
 
3157
                                      ' %s does not support option expansion'
 
3158
                                      % (name, type(val)))
 
3159
                if opt is not None:
 
3160
                    val = opt.convert_from_unicode(val)
 
3161
            return val
 
3162
        value = expand_and_convert(value)
 
3163
        if opt is not None and value is None:
2738
3164
            # If the option is registered, it may provide a default value
2739
 
            try:
2740
 
                opt = option_registry.get(name)
2741
 
            except KeyError:
2742
 
                # Not registered
2743
 
                opt = None
2744
 
            if opt is not None:
2745
 
                value = opt.get_default()
 
3165
            value = opt.get_default()
 
3166
            value = expand_and_convert(value)
2746
3167
        for hook in ConfigHooks['get']:
2747
3168
            hook(self, name, value)
2748
3169
        return value
2749
3170
 
 
3171
    def expand_options(self, string, env=None):
 
3172
        """Expand option references in the string in the configuration context.
 
3173
 
 
3174
        :param string: The string containing option(s) to expand.
 
3175
 
 
3176
        :param env: An option dict defining additional configuration options or
 
3177
            overriding existing ones.
 
3178
 
 
3179
        :returns: The expanded string.
 
3180
        """
 
3181
        return self._expand_options_in_string(string, env)
 
3182
 
 
3183
    def _expand_options_in_string(self, string, env=None, _refs=None):
 
3184
        """Expand options in the string in the configuration context.
 
3185
 
 
3186
        :param string: The string to be expanded.
 
3187
 
 
3188
        :param env: An option dict defining additional configuration options or
 
3189
            overriding existing ones.
 
3190
 
 
3191
        :param _refs: Private list (FIFO) containing the options being expanded
 
3192
            to detect loops.
 
3193
 
 
3194
        :returns: The expanded string.
 
3195
        """
 
3196
        if string is None:
 
3197
            # Not much to expand there
 
3198
            return None
 
3199
        if _refs is None:
 
3200
            # What references are currently resolved (to detect loops)
 
3201
            _refs = []
 
3202
        result = string
 
3203
        # We need to iterate until no more refs appear ({{foo}} will need two
 
3204
        # iterations for example).
 
3205
        while True:
 
3206
            raw_chunks = Stack._option_ref_re.split(result)
 
3207
            if len(raw_chunks) == 1:
 
3208
                # Shorcut the trivial case: no refs
 
3209
                return result
 
3210
            chunks = []
 
3211
            # Split will isolate refs so that every other chunk is a ref
 
3212
            chunk_is_ref = False
 
3213
            for chunk in raw_chunks:
 
3214
                if not chunk_is_ref:
 
3215
                    chunks.append(chunk)
 
3216
                    chunk_is_ref = True
 
3217
                else:
 
3218
                    name = chunk[1:-1]
 
3219
                    if name in _refs:
 
3220
                        raise errors.OptionExpansionLoop(string, _refs)
 
3221
                    _refs.append(name)
 
3222
                    value = self._expand_option(name, env, _refs)
 
3223
                    if value is None:
 
3224
                        raise errors.ExpandingUnknownOption(name, string)
 
3225
                    chunks.append(value)
 
3226
                    _refs.pop()
 
3227
                    chunk_is_ref = False
 
3228
            result = ''.join(chunks)
 
3229
        return result
 
3230
 
 
3231
    def _expand_option(self, name, env, _refs):
 
3232
        if env is not None and name in env:
 
3233
            # Special case, values provided in env takes precedence over
 
3234
            # anything else
 
3235
            value = env[name]
 
3236
        else:
 
3237
            # FIXME: This is a limited implementation, what we really need is a
 
3238
            # way to query the bzr config for the value of an option,
 
3239
            # respecting the scope rules (That is, once we implement fallback
 
3240
            # configs, getting the option value should restart from the top
 
3241
            # config, not the current one) -- vila 20101222
 
3242
            value = self.get(name, expand=False)
 
3243
            value = self._expand_options_in_string(value, env, _refs)
 
3244
        return value
 
3245
 
2750
3246
    def _get_mutable_section(self):
2751
3247
        """Get the MutableSection for the Stack.
2752
3248
 
2776
3272
        # Mostly for debugging use
2777
3273
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2778
3274
 
 
3275
    def _get_overrides(self):
 
3276
        # Hack around library_state.initialize never called
 
3277
        if bzrlib.global_state is not None:
 
3278
            return [bzrlib.global_state.cmdline_overrides]
 
3279
        return []
 
3280
 
2779
3281
 
2780
3282
class _CompatibleStack(Stack):
2781
3283
    """Place holder for compatibility with previous design.
2802
3304
 
2803
3305
 
2804
3306
class GlobalStack(_CompatibleStack):
 
3307
    """Global options only stack."""
2805
3308
 
2806
3309
    def __init__(self):
2807
3310
        # Get a GlobalStore
2808
3311
        gstore = GlobalStore()
2809
 
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
 
3312
        super(GlobalStack, self).__init__(
 
3313
            [self._get_overrides, gstore.get_sections],
 
3314
            gstore)
2810
3315
 
2811
3316
 
2812
3317
class LocationStack(_CompatibleStack):
 
3318
    """Per-location options falling back to global options stack."""
2813
3319
 
2814
3320
    def __init__(self, location):
 
3321
        """Make a new stack for a location and global configuration.
 
3322
        
 
3323
        :param location: A URL prefix to """
2815
3324
        lstore = LocationStore()
2816
3325
        matcher = LocationMatcher(lstore, location)
2817
3326
        gstore = GlobalStore()
2818
3327
        super(LocationStack, self).__init__(
2819
 
            [matcher.get_sections, gstore.get_sections], lstore)
 
3328
            [self._get_overrides,
 
3329
             matcher.get_sections, gstore.get_sections],
 
3330
            lstore)
 
3331
 
2820
3332
 
2821
3333
class BranchStack(_CompatibleStack):
 
3334
    """Per-location options falling back to branch then global options stack."""
2822
3335
 
2823
3336
    def __init__(self, branch):
2824
3337
        bstore = BranchStore(branch)
2826
3339
        matcher = LocationMatcher(lstore, branch.base)
2827
3340
        gstore = GlobalStore()
2828
3341
        super(BranchStack, self).__init__(
2829
 
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
 
3342
            [self._get_overrides,
 
3343
             matcher.get_sections, bstore.get_sections, gstore.get_sections],
 
3344
            bstore)
 
3345
        self.branch = branch
 
3346
 
 
3347
 
 
3348
class RemoteControlStack(_CompatibleStack):
 
3349
    """Remote control-only options stack."""
 
3350
 
 
3351
    def __init__(self, bzrdir):
 
3352
        cstore = ControlStore(bzrdir)
 
3353
        super(RemoteControlStack, self).__init__(
 
3354
            [cstore.get_sections],
 
3355
            cstore)
 
3356
        self.bzrdir = bzrdir
 
3357
 
 
3358
 
 
3359
class RemoteBranchStack(_CompatibleStack):
 
3360
    """Remote branch-only options stack."""
 
3361
 
 
3362
    def __init__(self, branch):
 
3363
        bstore = BranchStore(branch)
 
3364
        super(RemoteBranchStack, self).__init__(
 
3365
            [bstore.get_sections],
2830
3366
            bstore)
2831
3367
        self.branch = branch
2832
3368