~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

(gz) Never raise KnownFailure in tests,
 use knownFailure method instead (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
77
77
import sys
78
78
 
79
79
 
80
 
import bzrlib
81
80
from bzrlib.decorators import needs_write_lock
82
81
from bzrlib.lazy_import import lazy_import
83
82
lazy_import(globals(), """
87
86
 
88
87
from bzrlib import (
89
88
    atomicfile,
90
 
    controldir,
 
89
    bzrdir,
91
90
    debug,
92
91
    errors,
93
92
    lazy_regex,
94
 
    library_state,
95
93
    lockdir,
96
94
    mail_client,
97
95
    mergetools,
103
101
    urlutils,
104
102
    win32utils,
105
103
    )
106
 
from bzrlib.i18n import gettext
107
104
from bzrlib.util.configobj import configobj
108
105
""")
109
106
from bzrlib import (
110
107
    commands,
111
108
    hooks,
112
 
    lazy_regex,
113
109
    registry,
114
110
    )
115
111
from bzrlib.symbol_versioning import (
176
172
# FIXME: Until we can guarantee that each config file is loaded once and
177
173
# only once for a given bzrlib session, we don't want to re-read the file every
178
174
# time we query for an option so we cache the value (bad ! watch out for tests
179
 
# needing to restore the proper value). -- vila 20110219
 
175
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
176
# yell at mgz^W vila and the RM if this is still present at that time
 
177
# -- vila 20110219
180
178
_expand_default_value = None
181
179
def _get_expand_default_value():
182
180
    global _expand_default_value
417
415
            # add) the final ','
418
416
            l = [l]
419
417
        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
 
        
459
418
 
460
419
    def gpg_signing_command(self):
461
420
        """What program should be used to sign signatures?"""
625
584
        for (oname, value, section, conf_id, parser) in self._get_options():
626
585
            if oname.startswith('bzr.mergetool.'):
627
586
                tool_name = oname[len('bzr.mergetool.'):]
628
 
                tools[tool_name] = self.get_user_option(oname)
 
587
                tools[tool_name] = value
629
588
        trace.mutter('loaded merge tools: %r' % tools)
630
589
        return tools
631
590
 
1028
987
        # local transports are not shared. But if/when we start using
1029
988
        # LockableConfig for other kind of transports, we will need to reuse
1030
989
        # whatever connection is already established -- vila 20100929
1031
 
        self.transport = transport.get_transport_from_path(self.dir)
 
990
        self.transport = transport.get_transport(self.dir)
1032
991
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
1033
992
 
1034
993
    def _create_from_string(self, unicode_bytes, save):
1400
1359
            return (self.branch._transport.get_bytes("email")
1401
1360
                    .decode(osutils.get_user_encoding())
1402
1361
                    .rstrip("\r\n"))
1403
 
        except (errors.NoSuchFile, errors.PermissionDenied), e:
 
1362
        except errors.NoSuchFile, e:
1404
1363
            pass
1405
1364
 
1406
1365
        return self._get_best_value('_get_user_id')
1554
1513
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1555
1514
                                  ' or HOME set')
1556
1515
        return osutils.pathjoin(base, 'bazaar', '2.0')
1557
 
    else:
1558
 
        if base is not None:
1559
 
            base = base.decode(osutils._fs_enc)
1560
 
    if sys.platform == 'darwin':
 
1516
    elif sys.platform == 'darwin':
1561
1517
        if base is None:
1562
1518
            # this takes into account $HOME
1563
1519
            base = os.path.expanduser("~")
1564
1520
        return osutils.pathjoin(base, '.bazaar')
1565
1521
    else:
1566
1522
        if base is None:
 
1523
 
1567
1524
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1568
1525
            if xdg_dir is None:
1569
1526
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1572
1529
                trace.mutter(
1573
1530
                    "Using configuration in XDG directory %s." % xdg_dir)
1574
1531
                return xdg_dir
 
1532
 
1575
1533
            base = os.path.expanduser("~")
1576
1534
        return osutils.pathjoin(base, ".bazaar")
1577
1535
 
2281
2239
            return f
2282
2240
        except errors.NoSuchFile:
2283
2241
            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()
2289
2242
 
2290
2243
    def _external_url(self):
2291
2244
        return urlutils.join(self._transport.external_url(), self._filename)
2318
2271
    The option *values* are stored in config files and found in sections.
2319
2272
 
2320
2273
    Here we define various properties about the option itself, its default
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.
 
2274
    value, in which config files it can be stored, etc (TBC).
2323
2275
    """
2324
2276
 
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 = []
 
2277
    def __init__(self, name, default=None):
2356
2278
        self.name = name
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
 
2279
        self.default = default
2398
2280
 
2399
2281
    def get_default(self):
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('log_format', default='long',
2576
 
           help= '''\
2577
 
Log format to use when displaying revisions.
2578
 
 
2579
 
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2580
 
may be provided by plugins.
2581
 
'''))
2582
 
option_registry.register(
2583
 
    Option('output_encoding',
2584
 
           help= 'Unicode encoding for output'
2585
 
           ' (terminal encoding if not specified).'))
2586
 
option_registry.register(
2587
 
    Option('push_strict', default=None,
2588
 
           from_unicode=bool_from_store,
2589
 
           help='''\
2590
 
The default value for ``push --strict``.
2591
 
 
2592
 
If present, defines the ``--strict`` option default value for checking
2593
 
uncommitted changes before sending a merge directive.
2594
 
'''))
2595
 
option_registry.register(
2596
 
    Option('repository.fdatasync', default=True,
2597
 
           from_unicode=bool_from_store,
2598
 
           help='''\
2599
 
Flush repository changes onto physical disk?
2600
 
 
2601
 
If true (default), repository changes are flushed through the OS buffers
2602
 
to physical disk.  This is somewhat slower, but means data should not be
2603
 
lost if the machine crashes.  See also dirstate.fdatasync.
2604
 
'''))
2605
 
 
2606
 
option_registry.register(
2607
 
    Option('selftest.timeout',
2608
 
        default='600',
2609
 
        from_unicode=int_from_store,
2610
 
        help='Abort selftest if one test takes longer than this many seconds',
2611
 
        ))
2612
 
 
2613
 
option_registry.register(
2614
 
    Option('send_strict', default=None,
2615
 
           from_unicode=bool_from_store,
2616
 
           help='''\
2617
 
The default value for ``send --strict``.
2618
 
 
2619
 
If present, defines the ``--strict`` option default value for checking
2620
 
uncommitted changes before pushing.
2621
 
'''))
2622
 
 
2623
 
option_registry.register(
2624
 
    Option('serve.client_timeout',
2625
 
           default=300.0, from_unicode=float_from_store,
2626
 
           help="If we wait for a new request from a client for more than"
2627
 
                " X seconds, consider the client idle, and hangup."))
 
2282
        return self.default
 
2283
 
 
2284
 
 
2285
# Options registry
 
2286
 
 
2287
option_registry = registry.Registry()
 
2288
 
 
2289
 
 
2290
option_registry.register(
 
2291
    'editor', Option('editor'),
 
2292
    help='The command called to launch an editor to enter a message.')
 
2293
 
 
2294
option_registry.register(
 
2295
    'dirstate.fdatasync', Option('dirstate.fdatasync', default=True),
 
2296
    help='Flush dirstate changes onto physical disk?')
 
2297
 
 
2298
option_registry.register(
 
2299
    'repository.fdatasync',
 
2300
    Option('repository.fdatasync', default=True),
 
2301
    help='Flush repository changes onto physical disk?')
2628
2302
 
2629
2303
 
2630
2304
class Section(object):
2640
2314
        # We re-use the dict-like object received
2641
2315
        self.options = options
2642
2316
 
2643
 
    def get(self, name, default=None, expand=True):
 
2317
    def get(self, name, default=None):
2644
2318
        return self.options.get(name, default)
2645
2319
 
2646
 
    def iter_option_names(self):
2647
 
        for k in self.options.iterkeys():
2648
 
            yield k
2649
 
 
2650
2320
    def __repr__(self):
2651
2321
        # Mostly for debugging use
2652
2322
        return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2721
2391
    def get_sections(self):
2722
2392
        """Returns an ordered iterable of existing sections.
2723
2393
 
2724
 
        :returns: An iterable of (store, section).
 
2394
        :returns: An iterable of (name, dict).
2725
2395
        """
2726
2396
        raise NotImplementedError(self.get_sections)
2727
2397
 
2728
 
    def get_mutable_section(self, section_id=None):
 
2398
    def get_mutable_section(self, section_name=None):
2729
2399
        """Returns the specified mutable section.
2730
2400
 
2731
 
        :param section_id: The section identifier
 
2401
        :param section_name: The section identifier
2732
2402
        """
2733
2403
        raise NotImplementedError(self.get_mutable_section)
2734
2404
 
2738
2408
                                    self.external_url())
2739
2409
 
2740
2410
 
2741
 
class CommandLineStore(Store):
2742
 
    "A store to carry command line overrides for the config options."""
2743
 
 
2744
 
    def __init__(self, opts=None):
2745
 
        super(CommandLineStore, self).__init__()
2746
 
        if opts is None:
2747
 
            opts = {}
2748
 
        self.options = {}
2749
 
 
2750
 
    def _reset(self):
2751
 
        # The dict should be cleared but not replaced so it can be shared.
2752
 
        self.options.clear()
2753
 
 
2754
 
    def _from_cmdline(self, overrides):
2755
 
        # Reset before accepting new definitions
2756
 
        self._reset()
2757
 
        for over in overrides:
2758
 
            try:
2759
 
                name, value = over.split('=', 1)
2760
 
            except ValueError:
2761
 
                raise errors.BzrCommandError(
2762
 
                    gettext("Invalid '%s', should be of the form 'name=value'")
2763
 
                    % (over,))
2764
 
            self.options[name] = value
2765
 
 
2766
 
    def external_url(self):
2767
 
        # Not an url but it makes debugging easier and is never needed
2768
 
        # otherwise
2769
 
        return 'cmdline'
2770
 
 
2771
 
    def get_sections(self):
2772
 
        yield self,  self.readonly_section_class('cmdline_overrides',
2773
 
                                                 self.options)
2774
 
 
2775
 
 
2776
2411
class IniFileStore(Store):
2777
2412
    """A config Store using ConfigObj for storage.
2778
2413
 
2784
2419
        serialize/deserialize the config file.
2785
2420
    """
2786
2421
 
2787
 
    def __init__(self):
 
2422
    def __init__(self, transport, file_name):
2788
2423
        """A config Store using ConfigObj for storage.
 
2424
 
 
2425
        :param transport: The transport object where the config file is located.
 
2426
 
 
2427
        :param file_name: The config file basename in the transport directory.
2789
2428
        """
2790
2429
        super(IniFileStore, self).__init__()
 
2430
        self.transport = transport
 
2431
        self.file_name = file_name
2791
2432
        self._config_obj = None
2792
2433
 
2793
2434
    def is_loaded(self):
2796
2437
    def unload(self):
2797
2438
        self._config_obj = None
2798
2439
 
2799
 
    def _load_content(self):
2800
 
        """Load the config file bytes.
2801
 
 
2802
 
        This should be provided by subclasses
2803
 
 
2804
 
        :return: Byte string
2805
 
        """
2806
 
        raise NotImplementedError(self._load_content)
2807
 
 
2808
 
    def _save_content(self, content):
2809
 
        """Save the config file bytes.
2810
 
 
2811
 
        This should be provided by subclasses
2812
 
 
2813
 
        :param content: Config file bytes to write
2814
 
        """
2815
 
        raise NotImplementedError(self._save_content)
2816
 
 
2817
2440
    def load(self):
2818
2441
        """Load the store from the associated file."""
2819
2442
        if self.is_loaded():
2820
2443
            return
2821
 
        content = self._load_content()
 
2444
        content = self.transport.get_bytes(self.file_name)
2822
2445
        self._load_from_string(content)
2823
2446
        for hook in ConfigHooks['load']:
2824
2447
            hook(self)
2833
2456
        co_input = StringIO(bytes)
2834
2457
        try:
2835
2458
            # The config files are always stored utf8-encoded
2836
 
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
2837
 
                                         list_values=False)
 
2459
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
2838
2460
        except configobj.ConfigObjError, e:
2839
2461
            self._config_obj = None
2840
2462
            raise errors.ParseConfigError(e.errors, self.external_url())
2847
2469
            return
2848
2470
        out = StringIO()
2849
2471
        self._config_obj.write(out)
2850
 
        self._save_content(out.getvalue())
 
2472
        self.transport.put_bytes(self.file_name, out.getvalue())
2851
2473
        for hook in ConfigHooks['save']:
2852
2474
            hook(self)
2853
2475
 
 
2476
    def external_url(self):
 
2477
        # FIXME: external_url should really accepts an optional relpath
 
2478
        # parameter (bug #750169) :-/ -- vila 2011-04-04
 
2479
        # The following will do in the interim but maybe we don't want to
 
2480
        # expose a path here but rather a config ID and its associated
 
2481
        # object </hand wawe>.
 
2482
        return urlutils.join(self.transport.external_url(), self.file_name)
 
2483
 
2854
2484
    def get_sections(self):
2855
2485
        """Get the configobj section in the file order.
2856
2486
 
2857
 
        :returns: An iterable of (store, section).
 
2487
        :returns: An iterable of (name, dict).
2858
2488
        """
2859
2489
        # We need a loaded store
2860
2490
        try:
2861
2491
            self.load()
2862
 
        except (errors.NoSuchFile, errors.PermissionDenied):
2863
 
            # If the file can't be read, there is no sections
 
2492
        except errors.NoSuchFile:
 
2493
            # If the file doesn't exist, there is no sections
2864
2494
            return
2865
2495
        cobj = self._config_obj
2866
2496
        if cobj.scalars:
2867
 
            yield self, self.readonly_section_class(None, cobj)
 
2497
            yield self.readonly_section_class(None, cobj)
2868
2498
        for section_name in cobj.sections:
2869
 
            yield (self,
2870
 
                   self.readonly_section_class(section_name,
2871
 
                                               cobj[section_name]))
 
2499
            yield self.readonly_section_class(section_name, cobj[section_name])
2872
2500
 
2873
 
    def get_mutable_section(self, section_id=None):
 
2501
    def get_mutable_section(self, section_name=None):
2874
2502
        # We need a loaded store
2875
2503
        try:
2876
2504
            self.load()
2877
2505
        except errors.NoSuchFile:
2878
2506
            # The file doesn't exist, let's pretend it was empty
2879
2507
            self._load_from_string('')
2880
 
        if section_id is None:
 
2508
        if section_name is None:
2881
2509
            section = self._config_obj
2882
2510
        else:
2883
 
            section = self._config_obj.setdefault(section_id, {})
2884
 
        return self.mutable_section_class(section_id, section)
2885
 
 
2886
 
 
2887
 
class TransportIniFileStore(IniFileStore):
2888
 
    """IniFileStore that loads files from a transport.
2889
 
    """
2890
 
 
2891
 
    def __init__(self, transport, file_name):
2892
 
        """A Store using a ini file on a Transport
2893
 
 
2894
 
        :param transport: The transport object where the config file is located.
2895
 
        :param file_name: The config file basename in the transport directory.
2896
 
        """
2897
 
        super(TransportIniFileStore, self).__init__()
2898
 
        self.transport = transport
2899
 
        self.file_name = file_name
2900
 
 
2901
 
    def _load_content(self):
2902
 
        try:
2903
 
            return self.transport.get_bytes(self.file_name)
2904
 
        except errors.PermissionDenied:
2905
 
            trace.warning("Permission denied while trying to load "
2906
 
                          "configuration store %s.", self.external_url())
2907
 
            raise
2908
 
 
2909
 
    def _save_content(self, content):
2910
 
        self.transport.put_bytes(self.file_name, content)
2911
 
 
2912
 
    def external_url(self):
2913
 
        # FIXME: external_url should really accepts an optional relpath
2914
 
        # parameter (bug #750169) :-/ -- vila 2011-04-04
2915
 
        # The following will do in the interim but maybe we don't want to
2916
 
        # expose a path here but rather a config ID and its associated
2917
 
        # object </hand wawe>.
2918
 
        return urlutils.join(self.transport.external_url(), self.file_name)
 
2511
            section = self._config_obj.setdefault(section_name, {})
 
2512
        return self.mutable_section_class(section_name, section)
2919
2513
 
2920
2514
 
2921
2515
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2924
2518
# they may face the same issue.
2925
2519
 
2926
2520
 
2927
 
class LockableIniFileStore(TransportIniFileStore):
 
2521
class LockableIniFileStore(IniFileStore):
2928
2522
    """A ConfigObjStore using locks on save to ensure store integrity."""
2929
2523
 
2930
2524
    def __init__(self, transport, file_name, lock_dir_name=None):
2977
2571
class GlobalStore(LockableIniFileStore):
2978
2572
 
2979
2573
    def __init__(self, possible_transports=None):
2980
 
        t = transport.get_transport_from_path(
2981
 
            config_dir(), possible_transports=possible_transports)
 
2574
        t = transport.get_transport_from_path(config_dir(),
 
2575
                                    possible_transports=possible_transports)
2982
2576
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
2983
 
        self.id = 'bazaar'
2984
2577
 
2985
2578
 
2986
2579
class LocationStore(LockableIniFileStore):
2987
2580
 
2988
2581
    def __init__(self, possible_transports=None):
2989
 
        t = transport.get_transport_from_path(
2990
 
            config_dir(), possible_transports=possible_transports)
 
2582
        t = transport.get_transport_from_path(config_dir(),
 
2583
                                    possible_transports=possible_transports)
2991
2584
        super(LocationStore, self).__init__(t, 'locations.conf')
2992
 
        self.id = 'locations'
2993
 
 
2994
 
 
2995
 
class BranchStore(TransportIniFileStore):
 
2585
 
 
2586
 
 
2587
class BranchStore(IniFileStore):
2996
2588
 
2997
2589
    def __init__(self, branch):
2998
2590
        super(BranchStore, self).__init__(branch.control_transport,
2999
2591
                                          'branch.conf')
3000
2592
        self.branch = branch
3001
 
        self.id = 'branch'
3002
2593
 
3003
2594
    def lock_write(self, token=None):
3004
2595
        return self.branch.lock_write(token)
3015
2606
        super(BranchStore, self).save()
3016
2607
 
3017
2608
 
3018
 
class ControlStore(LockableIniFileStore):
3019
 
 
3020
 
    def __init__(self, bzrdir):
3021
 
        super(ControlStore, self).__init__(bzrdir.transport,
3022
 
                                          'control.conf',
3023
 
                                           lock_dir_name='branch_lock')
3024
 
 
3025
 
 
3026
2609
class SectionMatcher(object):
3027
2610
    """Select sections into a given Store.
3028
2611
 
3029
 
    This is intended to be used to postpone getting an iterable of sections
3030
 
    from a store.
 
2612
    This intended to be used to postpone getting an iterable of sections from a
 
2613
    store.
3031
2614
    """
3032
2615
 
3033
2616
    def __init__(self, store):
3038
2621
        # sections.
3039
2622
        sections = self.store.get_sections()
3040
2623
        # Walk the revisions in the order provided
3041
 
        for store, s in sections:
 
2624
        for s in sections:
3042
2625
            if self.match(s):
3043
 
                yield store, s
3044
 
 
3045
 
    def match(self, section):
3046
 
        """Does the proposed section match.
3047
 
 
3048
 
        :param section: A Section object.
3049
 
 
3050
 
        :returns: True if the section matches, False otherwise.
3051
 
        """
 
2626
                yield s
 
2627
 
 
2628
    def match(self, secion):
3052
2629
        raise NotImplementedError(self.match)
3053
2630
 
3054
2631
 
3055
 
class NameMatcher(SectionMatcher):
3056
 
 
3057
 
    def __init__(self, store, section_id):
3058
 
        super(NameMatcher, self).__init__(store)
3059
 
        self.section_id = section_id
3060
 
 
3061
 
    def match(self, section):
3062
 
        return section.id == self.section_id
3063
 
 
3064
 
 
3065
2632
class LocationSection(Section):
3066
2633
 
3067
2634
    def __init__(self, section, length, extra_path):
3068
2635
        super(LocationSection, self).__init__(section.id, section.options)
3069
2636
        self.length = length
3070
2637
        self.extra_path = extra_path
3071
 
        self.locals = {'relpath': extra_path,
3072
 
                       'basename': urlutils.basename(extra_path)}
3073
2638
 
3074
 
    def get(self, name, default=None, expand=True):
 
2639
    def get(self, name, default=None):
3075
2640
        value = super(LocationSection, self).get(name, default)
3076
 
        if value is not None and expand:
 
2641
        if value is not None:
3077
2642
            policy_name = self.get(name + ':policy', None)
3078
2643
            policy = _policy_value.get(policy_name, POLICY_NONE)
3079
2644
            if policy == POLICY_APPENDPATH:
3080
2645
                value = urlutils.join(value, self.extra_path)
3081
 
            # expand section local options right now (since POLICY_APPENDPATH
3082
 
            # will never add options references, it's ok to expand after it).
3083
 
            chunks = []
3084
 
            for is_ref, chunk in iter_option_refs(value):
3085
 
                if not is_ref:
3086
 
                    chunks.append(chunk)
3087
 
                else:
3088
 
                    ref = chunk[1:-1]
3089
 
                    if ref in self.locals:
3090
 
                        chunks.append(self.locals[ref])
3091
 
                    else:
3092
 
                        chunks.append(chunk)
3093
 
            value = ''.join(chunks)
3094
2646
        return value
3095
2647
 
3096
2648
 
3107
2659
        # We slightly diverge from LocalConfig here by allowing the no-name
3108
2660
        # section as the most generic one and the lower priority.
3109
2661
        no_name_section = None
3110
 
        all_sections = []
 
2662
        sections = []
3111
2663
        # Filter out the no_name_section so _iter_for_location_by_parts can be
3112
2664
        # used (it assumes all sections have a name).
3113
 
        for _, section in self.store.get_sections():
 
2665
        for section in self.store.get_sections():
3114
2666
            if section.id is None:
3115
2667
                no_name_section = section
3116
2668
            else:
3117
 
                all_sections.append(section)
 
2669
                sections.append(section)
3118
2670
        # Unfortunately _iter_for_location_by_parts deals with section names so
3119
2671
        # we have to resync.
3120
2672
        filtered_sections = _iter_for_location_by_parts(
3121
 
            [s.id for s in all_sections], self.location)
3122
 
        iter_all_sections = iter(all_sections)
 
2673
            [s.id for s in sections], self.location)
 
2674
        iter_sections = iter(sections)
3123
2675
        matching_sections = []
3124
2676
        if no_name_section is not None:
3125
2677
            matching_sections.append(
3126
2678
                LocationSection(no_name_section, 0, self.location))
3127
2679
        for section_id, extra_path, length in filtered_sections:
3128
 
            # a section id is unique for a given store so it's safe to take the
3129
 
            # first matching section while iterating. Also, all filtered
3130
 
            # sections are part of 'all_sections' and will always be found
3131
 
            # there.
3132
 
            while True:
3133
 
                section = iter_all_sections.next()
3134
 
                if section_id == section.id:
3135
 
                    matching_sections.append(
3136
 
                        LocationSection(section, length, extra_path))
3137
 
                    break
 
2680
            # a section id is unique for a given store so it's safe to iterate
 
2681
            # again
 
2682
            section = iter_sections.next()
 
2683
            if section_id == section.id:
 
2684
                matching_sections.append(
 
2685
                    LocationSection(section, length, extra_path))
3138
2686
        return matching_sections
3139
2687
 
3140
2688
    def get_sections(self):
3153
2701
            if ignore:
3154
2702
                break
3155
2703
            # Finally, we have a valid section
3156
 
            yield self.store, section
3157
 
 
3158
 
 
3159
 
_option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
3160
 
"""Describes an expandable option reference.
3161
 
 
3162
 
We want to match the most embedded reference first.
3163
 
 
3164
 
I.e. for '{{foo}}' we will get '{foo}',
3165
 
for '{bar{baz}}' we will get '{baz}'
3166
 
"""
3167
 
 
3168
 
def iter_option_refs(string):
3169
 
    # Split isolate refs so every other chunk is a ref
3170
 
    is_ref = False
3171
 
    for chunk  in _option_ref_re.split(string):
3172
 
        yield is_ref, chunk
3173
 
        is_ref = not is_ref
 
2704
            yield section
3174
2705
 
3175
2706
 
3176
2707
class Stack(object):
3177
2708
    """A stack of configurations where an option can be defined"""
3178
2709
 
3179
 
    def __init__(self, sections_def, store=None, mutable_section_id=None):
 
2710
    def __init__(self, sections_def, store=None, mutable_section_name=None):
3180
2711
        """Creates a stack of sections with an optional store for changes.
3181
2712
 
3182
2713
        :param sections_def: A list of Section or callables that returns an
3186
2717
        :param store: The optional Store where modifications will be
3187
2718
            recorded. If none is specified, no modifications can be done.
3188
2719
 
3189
 
        :param mutable_section_id: The id of the MutableSection where changes
3190
 
            are recorded. This requires the ``store`` parameter to be
 
2720
        :param mutable_section_name: The name of the MutableSection where
 
2721
            changes are recorded. This requires the ``store`` parameter to be
3191
2722
            specified.
3192
2723
        """
3193
2724
        self.sections_def = sections_def
3194
2725
        self.store = store
3195
 
        self.mutable_section_id = mutable_section_id
 
2726
        self.mutable_section_name = mutable_section_name
3196
2727
 
3197
 
    def get(self, name, expand=None):
 
2728
    def get(self, name):
3198
2729
        """Return the *first* option value found in the sections.
3199
2730
 
3200
2731
        This is where we guarantee that sections coming from Store are loaded
3202
2733
        option exists or get its value, which in turn may require to discover
3203
2734
        in which sections it can be defined. Both of these (section and option
3204
2735
        existence) require loading the store (even partially).
3205
 
 
3206
 
        :param name: The queried option.
3207
 
 
3208
 
        :param expand: Whether options references should be expanded.
3209
 
 
3210
 
        :returns: The value of the option.
3211
2736
        """
3212
2737
        # FIXME: No caching of options nor sections yet -- vila 20110503
3213
 
        if expand is None:
3214
 
            expand = _get_expand_default_value()
3215
2738
        value = None
3216
2739
        # Ensuring lazy loading is achieved by delaying section matching (which
3217
2740
        # implies querying the persistent storage) until it can't be avoided
3218
2741
        # anymore by using callables to describe (possibly empty) section
3219
2742
        # lists.
3220
 
        for sections in self.sections_def:
3221
 
            for store, section in sections():
 
2743
        for section_or_callable in self.sections_def:
 
2744
            # Each section can expand to multiple ones when a callable is used
 
2745
            if callable(section_or_callable):
 
2746
                sections = section_or_callable()
 
2747
            else:
 
2748
                sections = [section_or_callable]
 
2749
            for section in sections:
3222
2750
                value = section.get(name)
3223
2751
                if value is not None:
3224
2752
                    break
3225
2753
            if value is not None:
3226
2754
                break
3227
 
        # If the option is registered, it may provide additional info about
3228
 
        # value handling
3229
 
        try:
3230
 
            opt = option_registry.get(name)
3231
 
        except KeyError:
3232
 
            # Not registered
3233
 
            opt = None
3234
 
        def expand_and_convert(val):
3235
 
            # This may need to be called twice if the value is None or ends up
3236
 
            # being None during expansion or conversion.
3237
 
            if val is not None:
3238
 
                if expand:
3239
 
                    if isinstance(val, basestring):
3240
 
                        val = self._expand_options_in_string(val)
3241
 
                    else:
3242
 
                        trace.warning('Cannot expand "%s":'
3243
 
                                      ' %s does not support option expansion'
3244
 
                                      % (name, type(val)))
3245
 
                if opt is not None:
3246
 
                    val = opt.convert_from_unicode(val)
3247
 
            return val
3248
 
        value = expand_and_convert(value)
3249
 
        if opt is not None and value is None:
 
2755
        if value is None:
3250
2756
            # If the option is registered, it may provide a default value
3251
 
            value = opt.get_default()
3252
 
            value = expand_and_convert(value)
 
2757
            try:
 
2758
                opt = option_registry.get(name)
 
2759
            except KeyError:
 
2760
                # Not registered
 
2761
                opt = None
 
2762
            if opt is not None:
 
2763
                value = opt.get_default()
3253
2764
        for hook in ConfigHooks['get']:
3254
2765
            hook(self, name, value)
3255
2766
        return value
3256
2767
 
3257
 
    def expand_options(self, string, env=None):
3258
 
        """Expand option references in the string in the configuration context.
3259
 
 
3260
 
        :param string: The string containing option(s) to expand.
3261
 
 
3262
 
        :param env: An option dict defining additional configuration options or
3263
 
            overriding existing ones.
3264
 
 
3265
 
        :returns: The expanded string.
3266
 
        """
3267
 
        return self._expand_options_in_string(string, env)
3268
 
 
3269
 
    def _expand_options_in_string(self, string, env=None, _refs=None):
3270
 
        """Expand options in the string in the configuration context.
3271
 
 
3272
 
        :param string: The string to be expanded.
3273
 
 
3274
 
        :param env: An option dict defining additional configuration options or
3275
 
            overriding existing ones.
3276
 
 
3277
 
        :param _refs: Private list (FIFO) containing the options being expanded
3278
 
            to detect loops.
3279
 
 
3280
 
        :returns: The expanded string.
3281
 
        """
3282
 
        if string is None:
3283
 
            # Not much to expand there
3284
 
            return None
3285
 
        if _refs is None:
3286
 
            # What references are currently resolved (to detect loops)
3287
 
            _refs = []
3288
 
        result = string
3289
 
        # We need to iterate until no more refs appear ({{foo}} will need two
3290
 
        # iterations for example).
3291
 
        expanded = True
3292
 
        while expanded:
3293
 
            expanded = False
3294
 
            chunks = []
3295
 
            for is_ref, chunk in iter_option_refs(result):
3296
 
                if not is_ref:
3297
 
                    chunks.append(chunk)
3298
 
                else:
3299
 
                    expanded = True
3300
 
                    name = chunk[1:-1]
3301
 
                    if name in _refs:
3302
 
                        raise errors.OptionExpansionLoop(string, _refs)
3303
 
                    _refs.append(name)
3304
 
                    value = self._expand_option(name, env, _refs)
3305
 
                    if value is None:
3306
 
                        raise errors.ExpandingUnknownOption(name, string)
3307
 
                    chunks.append(value)
3308
 
                    _refs.pop()
3309
 
            result = ''.join(chunks)
3310
 
        return result
3311
 
 
3312
 
    def _expand_option(self, name, env, _refs):
3313
 
        if env is not None and name in env:
3314
 
            # Special case, values provided in env takes precedence over
3315
 
            # anything else
3316
 
            value = env[name]
3317
 
        else:
3318
 
            value = self.get(name, expand=False)
3319
 
            value = self._expand_options_in_string(value, env, _refs)
3320
 
        return value
3321
 
 
3322
2768
    def _get_mutable_section(self):
3323
2769
        """Get the MutableSection for the Stack.
3324
2770
 
3325
2771
        This is where we guarantee that the mutable section is lazily loaded:
3326
2772
        this means we won't load the corresponding store before setting a value
3327
2773
        or deleting an option. In practice the store will often be loaded but
3328
 
        this helps catching some programming errors.
 
2774
        this allows helps catching some programming errors.
3329
2775
        """
3330
 
        section = self.store.get_mutable_section(self.mutable_section_id)
 
2776
        section = self.store.get_mutable_section(self.mutable_section_name)
3331
2777
        return section
3332
2778
 
3333
2779
    def set(self, name, value):
3348
2794
        # Mostly for debugging use
3349
2795
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3350
2796
 
3351
 
    def _get_overrides(self):
3352
 
        # Hack around library_state.initialize never called
3353
 
        if bzrlib.global_state is not None:
3354
 
            return bzrlib.global_state.cmdline_overrides.get_sections()
3355
 
        return []
3356
 
 
3357
2797
 
3358
2798
class _CompatibleStack(Stack):
3359
2799
    """Place holder for compatibility with previous design.
3364
2804
    One assumption made here is that the daughter classes will all use Stores
3365
2805
    derived from LockableIniFileStore).
3366
2806
 
3367
 
    It implements set() and remove () by re-loading the store before applying
3368
 
    the modification and saving it.
 
2807
    It implements set() by re-loading the store before applying the
 
2808
    modification and saving it.
3369
2809
 
3370
2810
    The long term plan being to implement a single write by store to save
3371
2811
    all modifications, this class should not be used in the interim.
3378
2818
        # Force a write to persistent storage
3379
2819
        self.store.save()
3380
2820
 
3381
 
    def remove(self, name):
3382
 
        # Force a reload
3383
 
        self.store.unload()
3384
 
        super(_CompatibleStack, self).remove(name)
3385
 
        # Force a write to persistent storage
3386
 
        self.store.save()
3387
 
 
3388
2821
 
3389
2822
class GlobalStack(_CompatibleStack):
3390
 
    """Global options only stack."""
3391
2823
 
3392
2824
    def __init__(self):
3393
2825
        # Get a GlobalStore
3394
2826
        gstore = GlobalStore()
3395
 
        super(GlobalStack, self).__init__(
3396
 
            [self._get_overrides, NameMatcher(gstore, 'DEFAULT').get_sections],
3397
 
            gstore, mutable_section_id='DEFAULT')
 
2827
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3398
2828
 
3399
2829
 
3400
2830
class LocationStack(_CompatibleStack):
3401
 
    """Per-location options falling back to global options stack."""
3402
2831
 
3403
2832
    def __init__(self, location):
3404
2833
        """Make a new stack for a location and global configuration.
3405
2834
        
3406
2835
        :param location: A URL prefix to """
3407
2836
        lstore = LocationStore()
3408
 
        if location.startswith('file://'):
3409
 
            location = urlutils.local_path_from_url(location)
3410
2837
        matcher = LocationMatcher(lstore, location)
3411
2838
        gstore = GlobalStore()
3412
2839
        super(LocationStack, self).__init__(
3413
 
            [self._get_overrides,
3414
 
             matcher.get_sections, NameMatcher(gstore, 'DEFAULT').get_sections],
3415
 
            lstore, mutable_section_id=location)
3416
 
 
 
2840
            [matcher.get_sections, gstore.get_sections], lstore)
3417
2841
 
3418
2842
class BranchStack(_CompatibleStack):
3419
 
    """Per-location options falling back to branch then global options stack."""
3420
2843
 
3421
2844
    def __init__(self, branch):
3422
 
        bstore = branch._get_config_store()
 
2845
        bstore = BranchStore(branch)
3423
2846
        lstore = LocationStore()
3424
2847
        matcher = LocationMatcher(lstore, branch.base)
3425
2848
        gstore = GlobalStore()
3426
2849
        super(BranchStack, self).__init__(
3427
 
            [self._get_overrides,
3428
 
             matcher.get_sections, bstore.get_sections,
3429
 
             NameMatcher(gstore, 'DEFAULT').get_sections],
3430
 
            bstore)
3431
 
        self.branch = branch
3432
 
 
3433
 
 
3434
 
class RemoteControlStack(_CompatibleStack):
3435
 
    """Remote control-only options stack."""
3436
 
 
3437
 
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3438
 
    # with the stack used for remote bzr dirs. RemoteControlStack only uses
3439
 
    # control.conf and is used only for stack options.
3440
 
 
3441
 
    def __init__(self, bzrdir):
3442
 
        cstore = bzrdir._get_config_store()
3443
 
        super(RemoteControlStack, self).__init__(
3444
 
            [cstore.get_sections],
3445
 
            cstore)
3446
 
        self.bzrdir = bzrdir
3447
 
 
3448
 
 
3449
 
class RemoteBranchStack(_CompatibleStack):
3450
 
    """Remote branch-only options stack."""
3451
 
 
3452
 
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3453
 
    # with the stack used for remote branches. RemoteBranchStack only uses
3454
 
    # branch.conf and is used only for the stack options.
3455
 
 
3456
 
    def __init__(self, branch):
3457
 
        bstore = branch._get_config_store()
3458
 
        super(RemoteBranchStack, self).__init__(
3459
 
            [bstore.get_sections],
3460
 
            bstore)
3461
 
        self.branch = branch
3462
 
 
3463
 
# Use a an empty dict to initialize an empty configobj avoiding all
3464
 
# parsing and encoding checks
3465
 
_quoting_config = configobj.ConfigObj(
3466
 
    {}, encoding='utf-8', interpolation=False)
 
2850
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
 
2851
            bstore)
 
2852
        self.branch = branch
 
2853
 
3467
2854
 
3468
2855
class cmd_config(commands.Command):
3469
2856
    __doc__ = """Display, set or remove a configuration option.
3486
2873
    takes_options = [
3487
2874
        'directory',
3488
2875
        # FIXME: This should be a registry option so that plugins can register
3489
 
        # their own config files (or not) and will also address
3490
 
        # http://pad.lv/788991 -- vila 20101115
 
2876
        # their own config files (or not) -- vila 20101002
3491
2877
        commands.Option('scope', help='Reduce the scope to the specified'
3492
 
                        ' configuration file.',
 
2878
                        ' configuration file',
3493
2879
                        type=unicode),
3494
2880
        commands.Option('all',
3495
2881
            help='Display all the defined values for the matching options.',
3496
2882
            ),
3497
2883
        commands.Option('remove', help='Remove the option from'
3498
 
                        ' the configuration file.'),
 
2884
                        ' the configuration file'),
3499
2885
        ]
3500
2886
 
3501
2887
    _see_also = ['configuration']
3531
2917
                # Set the option value
3532
2918
                self._set_config_option(name, value, directory, scope)
3533
2919
 
3534
 
    def _get_stack(self, directory, scope=None):
3535
 
        """Get the configuration stack specified by ``directory`` and ``scope``.
 
2920
    def _get_configs(self, directory, scope=None):
 
2921
        """Iterate the configurations specified by ``directory`` and ``scope``.
3536
2922
 
3537
2923
        :param directory: Where the configurations are derived from.
3538
2924
 
3539
2925
        :param scope: A specific config to start from.
3540
2926
        """
3541
 
        # FIXME: scope should allow access to plugin-specific stacks (even
3542
 
        # reduced to the plugin-specific store), related to
3543
 
        # http://pad.lv/788991 -- vila 2011-11-15
3544
2927
        if scope is not None:
3545
2928
            if scope == 'bazaar':
3546
 
                return GlobalStack()
 
2929
                yield GlobalConfig()
3547
2930
            elif scope == 'locations':
3548
 
                return LocationStack(directory)
 
2931
                yield LocationConfig(directory)
3549
2932
            elif scope == 'branch':
3550
 
                (_, br, _) = (
3551
 
                    controldir.ControlDir.open_containing_tree_or_branch(
3552
 
                        directory))
3553
 
                return br.get_config_stack()
3554
 
            raise errors.NoSuchConfig(scope)
 
2933
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2934
                    directory)
 
2935
                yield br.get_config()
3555
2936
        else:
3556
2937
            try:
3557
 
                (_, br, _) = (
3558
 
                    controldir.ControlDir.open_containing_tree_or_branch(
3559
 
                        directory))
3560
 
                return br.get_config_stack()
 
2938
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2939
                    directory)
 
2940
                yield br.get_config()
3561
2941
            except errors.NotBranchError:
3562
 
                return LocationStack(directory)
 
2942
                yield LocationConfig(directory)
 
2943
                yield GlobalConfig()
3563
2944
 
3564
2945
    def _show_value(self, name, directory, scope):
3565
 
        conf = self._get_stack(directory, scope)
3566
 
        value = conf.get(name, expand=True)
3567
 
        if value is not None:
3568
 
            # Quote the value appropriately
3569
 
            value = _quoting_config._quote(value)
3570
 
            self.outf.write('%s\n' % (value,))
3571
 
        else:
 
2946
        displayed = False
 
2947
        for c in self._get_configs(directory, scope):
 
2948
            if displayed:
 
2949
                break
 
2950
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2951
                if name == oname:
 
2952
                    # Display only the first value and exit
 
2953
 
 
2954
                    # FIXME: We need to use get_user_option to take policies
 
2955
                    # into account and we need to make sure the option exists
 
2956
                    # too (hence the two for loops), this needs a better API
 
2957
                    # -- vila 20101117
 
2958
                    value = c.get_user_option(name)
 
2959
                    # Quote the value appropriately
 
2960
                    value = parser._quote(value)
 
2961
                    self.outf.write('%s\n' % (value,))
 
2962
                    displayed = True
 
2963
                    break
 
2964
        if not displayed:
3572
2965
            raise errors.NoSuchConfigOption(name)
3573
2966
 
3574
2967
    def _show_matching_options(self, name, directory, scope):
3577
2970
        # avoid the delay introduced by the lazy regexp.  But, we still do
3578
2971
        # want the nicer errors raised by lazy_regex.
3579
2972
        name._compile_and_collapse()
3580
 
        cur_store_id = None
 
2973
        cur_conf_id = None
3581
2974
        cur_section = None
3582
 
        conf = self._get_stack(directory, scope)
3583
 
        for sections in conf.sections_def:
3584
 
            for store, section in sections():
3585
 
                for oname in section.iter_option_names():
3586
 
                    if name.search(oname):
3587
 
                        if cur_store_id != store.id:
3588
 
                            # Explain where the options are defined
3589
 
                            self.outf.write('%s:\n' % (store.id,))
3590
 
                            cur_store_id = store.id
3591
 
                            cur_section = None
3592
 
                        if (section.id not in (None, 'DEFAULT')
3593
 
                            and cur_section != section.id):
3594
 
                            # Display the section if it's not the default (or
3595
 
                            # only) one.
3596
 
                            self.outf.write('  [%s]\n' % (section.id,))
3597
 
                            cur_section = section.id
3598
 
                        value = section.get(oname, expand=False)
3599
 
                        value = _quoting_config._quote(value)
3600
 
                        self.outf.write('  %s = %s\n' % (oname, value))
 
2975
        for c in self._get_configs(directory, scope):
 
2976
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2977
                if name.search(oname):
 
2978
                    if cur_conf_id != conf_id:
 
2979
                        # Explain where the options are defined
 
2980
                        self.outf.write('%s:\n' % (conf_id,))
 
2981
                        cur_conf_id = conf_id
 
2982
                        cur_section = None
 
2983
                    if (section not in (None, 'DEFAULT')
 
2984
                        and cur_section != section):
 
2985
                        # Display the section if it's not the default (or only)
 
2986
                        # one.
 
2987
                        self.outf.write('  [%s]\n' % (section,))
 
2988
                        cur_section = section
 
2989
                    self.outf.write('  %s = %s\n' % (oname, value))
3601
2990
 
3602
2991
    def _set_config_option(self, name, value, directory, scope):
3603
 
        conf = self._get_stack(directory, scope)
3604
 
        conf.set(name, value)
 
2992
        for conf in self._get_configs(directory, scope):
 
2993
            conf.set_user_option(name, value)
 
2994
            break
 
2995
        else:
 
2996
            raise errors.NoSuchConfig(scope)
3605
2997
 
3606
2998
    def _remove_config_option(self, name, directory, scope):
3607
2999
        if name is None:
3608
3000
            raise errors.BzrCommandError(
3609
3001
                '--remove expects an option to remove.')
3610
 
        conf = self._get_stack(directory, scope)
3611
 
        try:
3612
 
            conf.remove(name)
3613
 
        except KeyError:
 
3002
        removed = False
 
3003
        for conf in self._get_configs(directory, scope):
 
3004
            for (section_name, section, conf_id) in conf._get_sections():
 
3005
                if scope is not None and conf_id != scope:
 
3006
                    # Not the right configuration file
 
3007
                    continue
 
3008
                if name in section:
 
3009
                    if conf_id != conf.config_id():
 
3010
                        conf = self._get_configs(directory, conf_id).next()
 
3011
                    # We use the first section in the first config where the
 
3012
                    # option is defined to remove it
 
3013
                    conf.remove_user_option(name, section_name)
 
3014
                    removed = True
 
3015
                    break
 
3016
            break
 
3017
        else:
 
3018
            raise errors.NoSuchConfig(scope)
 
3019
        if not removed:
3614
3020
            raise errors.NoSuchConfigOption(name)
3615
3021
 
3616
 
 
3617
3022
# Test registries
3618
3023
#
3619
3024
# We need adapters that can build a Store or a Stack in a test context. Test
3622
3027
# ready-to-use store or stack.  Plugins that define new store/stacks can also
3623
3028
# register themselves here to be tested against the tests defined in
3624
3029
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3625
 
# for the same test.
 
3030
# for the same tests.
3626
3031
 
3627
3032
# The registered object should be a callable receiving a test instance
3628
3033
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store