~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

(jelmer) Deprecate Repository.iter_reverse_revision_history(). (Jelmer
 Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
create_signatures=always|never|when-required(default)
30
30
gpg_signing_command=name-of-program
31
31
log_format=name-of-format
32
 
validate_signatures_in_log=true|false(default)
33
 
acceptable_keys=pattern1,pattern2
34
 
gpg_signing_key=amy@example.com
35
32
 
36
33
in locations.conf, you specify the url of a branch and options for it.
37
34
Wildcards may be used - * and ? as normal in shell completion. Options
42
39
email= as above
43
40
check_signatures= as above
44
41
create_signatures= as above.
45
 
validate_signatures_in_log=as above
46
 
acceptable_keys=as above
47
42
 
48
43
explanation of options
49
44
----------------------
50
45
editor - this option sets the pop up editor to use during commits.
51
46
email - this option sets the user id bzr will use when committing.
52
 
check_signatures - this option will control whether bzr will require good gpg
 
47
check_signatures - this option controls whether bzr will require good gpg
53
48
                   signatures, ignore them, or check them if they are
54
 
                   present.  Currently it is unused except that check_signatures
55
 
                   turns on create_signatures.
 
49
                   present.
56
50
create_signatures - this option controls whether bzr will always create
57
 
                    gpg signatures or not on commits.  There is an unused
58
 
                    option which in future is expected to work if               
59
 
                    branch settings require signatures.
 
51
                    gpg signatures, never create them, or create them if the
 
52
                    branch is configured to require them.
60
53
log_format - this option sets the default log format.  Possible values are
61
54
             long, short, line, or a plugin can register new formats.
62
 
validate_signatures_in_log - show GPG signature validity in log output
63
 
acceptable_keys - comma separated list of key patterns acceptable for
64
 
                  verify-signatures command
65
55
 
66
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
67
57
 
77
67
import sys
78
68
 
79
69
 
80
 
import bzrlib
81
70
from bzrlib.decorators import needs_write_lock
82
71
from bzrlib.lazy_import import lazy_import
83
72
lazy_import(globals(), """
87
76
 
88
77
from bzrlib import (
89
78
    atomicfile,
90
 
    controldir,
 
79
    bzrdir,
91
80
    debug,
92
81
    errors,
93
 
    lazy_regex,
94
 
    library_state,
95
82
    lockdir,
96
83
    mail_client,
97
84
    mergetools,
103
90
    urlutils,
104
91
    win32utils,
105
92
    )
106
 
from bzrlib.i18n import gettext
107
93
from bzrlib.util.configobj import configobj
108
94
""")
109
95
from bzrlib import (
110
96
    commands,
111
97
    hooks,
112
 
    lazy_regex,
113
98
    registry,
114
99
    )
115
100
from bzrlib.symbol_versioning import (
176
161
# FIXME: Until we can guarantee that each config file is loaded once and
177
162
# only once for a given bzrlib session, we don't want to re-read the file every
178
163
# 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
 
164
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
165
# yell at mgz^W vila and the RM if this is still present at that time
 
166
# -- vila 20110219
180
167
_expand_default_value = None
181
168
def _get_expand_default_value():
182
169
    global _expand_default_value
417
404
            # add) the final ','
418
405
            l = [l]
419
406
        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
407
 
460
408
    def gpg_signing_command(self):
461
409
        """What program should be used to sign signatures?"""
479
427
        """See log_format()."""
480
428
        return None
481
429
 
482
 
    def validate_signatures_in_log(self):
483
 
        """Show GPG signature validity in log"""
484
 
        result = self._validate_signatures_in_log()
485
 
        if result == "true":
486
 
            result = True
487
 
        else:
488
 
            result = False
489
 
        return result
490
 
 
491
 
    def _validate_signatures_in_log(self):
492
 
        """See validate_signatures_in_log()."""
493
 
        return None
494
 
 
495
 
    def acceptable_keys(self):
496
 
        """Comma separated list of key patterns acceptable to 
497
 
        verify-signatures command"""
498
 
        result = self._acceptable_keys()
499
 
        return result
500
 
 
501
 
    def _acceptable_keys(self):
502
 
        """See acceptable_keys()."""
503
 
        return None
504
 
 
505
430
    def post_commit(self):
506
431
        """An ordered list of python functions to call.
507
432
 
578
503
            return True
579
504
        return False
580
505
 
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
 
 
589
506
    def get_alias(self, value):
590
507
        return self._get_alias(value)
591
508
 
625
542
        for (oname, value, section, conf_id, parser) in self._get_options():
626
543
            if oname.startswith('bzr.mergetool.'):
627
544
                tool_name = oname[len('bzr.mergetool.'):]
628
 
                tools[tool_name] = self.get_user_option(oname)
 
545
                tools[tool_name] = value
629
546
        trace.mutter('loaded merge tools: %r' % tools)
630
547
        return tools
631
548
 
775
692
            self._parser = ConfigObj(co_input, encoding='utf-8')
776
693
        except configobj.ConfigObjError, e:
777
694
            raise errors.ParseConfigError(e.errors, e.config.filename)
778
 
        except UnicodeDecodeError:
779
 
            raise errors.ConfigContentError(self.file_name)
780
695
        # Make sure self.reload() will use the right file name
781
696
        self._parser.filename = self.file_name
782
697
        for hook in OldConfigHooks['load']:
913
828
        """See Config.log_format."""
914
829
        return self._get_user_option('log_format')
915
830
 
916
 
    def _validate_signatures_in_log(self):
917
 
        """See Config.validate_signatures_in_log."""
918
 
        return self._get_user_option('validate_signatures_in_log')
919
 
 
920
 
    def _acceptable_keys(self):
921
 
        """See Config.acceptable_keys."""
922
 
        return self._get_user_option('acceptable_keys')
923
 
 
924
831
    def _post_commit(self):
925
832
        """See Config.post_commit."""
926
833
        return self._get_user_option('post_commit')
1028
935
        # local transports are not shared. But if/when we start using
1029
936
        # LockableConfig for other kind of transports, we will need to reuse
1030
937
        # whatever connection is already established -- vila 20100929
1031
 
        self.transport = transport.get_transport_from_path(self.dir)
 
938
        self.transport = transport.get_transport(self.dir)
1032
939
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
1033
940
 
1034
941
    def _create_from_string(self, unicode_bytes, save):
1400
1307
            return (self.branch._transport.get_bytes("email")
1401
1308
                    .decode(osutils.get_user_encoding())
1402
1309
                    .rstrip("\r\n"))
1403
 
        except (errors.NoSuchFile, errors.PermissionDenied), e:
 
1310
        except errors.NoSuchFile, e:
1404
1311
            pass
1405
1312
 
1406
1313
        return self._get_best_value('_get_user_id')
1501
1408
        """See Config.log_format."""
1502
1409
        return self._get_best_value('_log_format')
1503
1410
 
1504
 
    def _validate_signatures_in_log(self):
1505
 
        """See Config.validate_signatures_in_log."""
1506
 
        return self._get_best_value('_validate_signatures_in_log')
1507
 
 
1508
 
    def _acceptable_keys(self):
1509
 
        """See Config.acceptable_keys."""
1510
 
        return self._get_best_value('_acceptable_keys')
1511
 
 
1512
1411
 
1513
1412
def ensure_config_dir_exists(path=None):
1514
1413
    """Make sure a configuration directory exists.
1554
1453
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1555
1454
                                  ' or HOME set')
1556
1455
        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':
 
1456
    elif sys.platform == 'darwin':
1561
1457
        if base is None:
1562
1458
            # this takes into account $HOME
1563
1459
            base = os.path.expanduser("~")
1564
1460
        return osutils.pathjoin(base, '.bazaar')
1565
1461
    else:
1566
1462
        if base is None:
 
1463
 
1567
1464
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1568
1465
            if xdg_dir is None:
1569
1466
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1572
1469
                trace.mutter(
1573
1470
                    "Using configuration in XDG directory %s." % xdg_dir)
1574
1471
                return xdg_dir
 
1472
 
1575
1473
            base = os.path.expanduser("~")
1576
1474
        return osutils.pathjoin(base, ".bazaar")
1577
1475
 
1799
1697
            self._config = ConfigObj(self._input, encoding='utf-8')
1800
1698
        except configobj.ConfigObjError, e:
1801
1699
            raise errors.ParseConfigError(e.errors, e.config.filename)
1802
 
        except UnicodeError:
1803
 
            raise errors.ConfigContentError(self._filename)
1804
1700
        return self._config
1805
1701
 
1806
1702
    def _save(self):
2281
2177
            return f
2282
2178
        except errors.NoSuchFile:
2283
2179
            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
 
 
2290
 
    def _external_url(self):
2291
 
        return urlutils.join(self._transport.external_url(), self._filename)
2292
2180
 
2293
2181
    def _get_configobj(self):
2294
2182
        f = self._get_config_file()
2295
2183
        try:
2296
 
            try:
2297
 
                conf = ConfigObj(f, encoding='utf-8')
2298
 
            except configobj.ConfigObjError, e:
2299
 
                raise errors.ParseConfigError(e.errors, self._external_url())
2300
 
            except UnicodeDecodeError:
2301
 
                raise errors.ConfigContentError(self._external_url())
 
2184
            return ConfigObj(f, encoding='utf-8')
2302
2185
        finally:
2303
2186
            f.close()
2304
 
        return conf
2305
2187
 
2306
2188
    def _set_configobj(self, configobj):
2307
2189
        out_file = StringIO()
2318
2200
    The option *values* are stored in config files and found in sections.
2319
2201
 
2320
2202
    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.
 
2203
    value, in which config files it can be stored, etc (TBC).
2323
2204
    """
2324
2205
 
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 = []
 
2206
    def __init__(self, name, default=None):
2356
2207
        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
 
2208
        self.default = default
2398
2209
 
2399
2210
    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."))
 
2211
        return self.default
 
2212
 
 
2213
 
 
2214
# Options registry
 
2215
 
 
2216
option_registry = registry.Registry()
 
2217
 
 
2218
 
 
2219
option_registry.register(
 
2220
    'editor', Option('editor'),
 
2221
    help='The command called to launch an editor to enter a message.')
2628
2222
 
2629
2223
 
2630
2224
class Section(object):
2640
2234
        # We re-use the dict-like object received
2641
2235
        self.options = options
2642
2236
 
2643
 
    def get(self, name, default=None, expand=True):
 
2237
    def get(self, name, default=None):
2644
2238
        return self.options.get(name, default)
2645
2239
 
2646
 
    def iter_option_names(self):
2647
 
        for k in self.options.iterkeys():
2648
 
            yield k
2649
 
 
2650
2240
    def __repr__(self):
2651
2241
        # Mostly for debugging use
2652
2242
        return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2695
2285
        """Loads the Store from persistent storage."""
2696
2286
        raise NotImplementedError(self.load)
2697
2287
 
2698
 
    def _load_from_string(self, bytes):
 
2288
    def _load_from_string(self, str_or_unicode):
2699
2289
        """Create a store from a string in configobj syntax.
2700
2290
 
2701
 
        :param bytes: A string representing the file content.
 
2291
        :param str_or_unicode: A string representing the file content. This will
 
2292
            be encoded to suit store needs internally.
 
2293
 
 
2294
        This is for tests and should not be used in production unless a
 
2295
        convincing use case can be demonstrated :)
2702
2296
        """
2703
2297
        raise NotImplementedError(self._load_from_string)
2704
2298
 
2721
2315
    def get_sections(self):
2722
2316
        """Returns an ordered iterable of existing sections.
2723
2317
 
2724
 
        :returns: An iterable of (store, section).
 
2318
        :returns: An iterable of (name, dict).
2725
2319
        """
2726
2320
        raise NotImplementedError(self.get_sections)
2727
2321
 
2728
 
    def get_mutable_section(self, section_id=None):
 
2322
    def get_mutable_section(self, section_name=None):
2729
2323
        """Returns the specified mutable section.
2730
2324
 
2731
 
        :param section_id: The section identifier
 
2325
        :param section_name: The section identifier
2732
2326
        """
2733
2327
        raise NotImplementedError(self.get_mutable_section)
2734
2328
 
2738
2332
                                    self.external_url())
2739
2333
 
2740
2334
 
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
2335
class IniFileStore(Store):
2777
2336
    """A config Store using ConfigObj for storage.
2778
2337
 
2784
2343
        serialize/deserialize the config file.
2785
2344
    """
2786
2345
 
2787
 
    def __init__(self):
 
2346
    def __init__(self, transport, file_name):
2788
2347
        """A config Store using ConfigObj for storage.
 
2348
 
 
2349
        :param transport: The transport object where the config file is located.
 
2350
 
 
2351
        :param file_name: The config file basename in the transport directory.
2789
2352
        """
2790
2353
        super(IniFileStore, self).__init__()
 
2354
        self.transport = transport
 
2355
        self.file_name = file_name
2791
2356
        self._config_obj = None
2792
2357
 
2793
2358
    def is_loaded(self):
2796
2361
    def unload(self):
2797
2362
        self._config_obj = None
2798
2363
 
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
2364
    def load(self):
2818
2365
        """Load the store from the associated file."""
2819
2366
        if self.is_loaded():
2820
2367
            return
2821
 
        content = self._load_content()
 
2368
        content = self.transport.get_bytes(self.file_name)
2822
2369
        self._load_from_string(content)
2823
2370
        for hook in ConfigHooks['load']:
2824
2371
            hook(self)
2825
2372
 
2826
 
    def _load_from_string(self, bytes):
 
2373
    def _load_from_string(self, str_or_unicode):
2827
2374
        """Create a config store from a string.
2828
2375
 
2829
 
        :param bytes: A string representing the file content.
 
2376
        :param str_or_unicode: A string representing the file content. This will
 
2377
            be utf-8 encoded internally.
 
2378
 
 
2379
        This is for tests and should not be used in production unless a
 
2380
        convincing use case can be demonstrated :)
2830
2381
        """
2831
2382
        if self.is_loaded():
2832
2383
            raise AssertionError('Already loaded: %r' % (self._config_obj,))
2833
 
        co_input = StringIO(bytes)
 
2384
        co_input = StringIO(str_or_unicode.encode('utf-8'))
2834
2385
        try:
2835
2386
            # The config files are always stored utf8-encoded
2836
 
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
2837
 
                                         list_values=False)
 
2387
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
2838
2388
        except configobj.ConfigObjError, e:
2839
2389
            self._config_obj = None
2840
2390
            raise errors.ParseConfigError(e.errors, self.external_url())
2841
 
        except UnicodeDecodeError:
2842
 
            raise errors.ConfigContentError(self.external_url())
2843
2391
 
2844
2392
    def save(self):
2845
2393
        if not self.is_loaded():
2847
2395
            return
2848
2396
        out = StringIO()
2849
2397
        self._config_obj.write(out)
2850
 
        self._save_content(out.getvalue())
 
2398
        self.transport.put_bytes(self.file_name, out.getvalue())
2851
2399
        for hook in ConfigHooks['save']:
2852
2400
            hook(self)
2853
2401
 
 
2402
    def external_url(self):
 
2403
        # FIXME: external_url should really accepts an optional relpath
 
2404
        # parameter (bug #750169) :-/ -- vila 2011-04-04
 
2405
        # The following will do in the interim but maybe we don't want to
 
2406
        # expose a path here but rather a config ID and its associated
 
2407
        # object </hand wawe>.
 
2408
        return urlutils.join(self.transport.external_url(), self.file_name)
 
2409
 
2854
2410
    def get_sections(self):
2855
2411
        """Get the configobj section in the file order.
2856
2412
 
2857
 
        :returns: An iterable of (store, section).
 
2413
        :returns: An iterable of (name, dict).
2858
2414
        """
2859
2415
        # We need a loaded store
2860
2416
        try:
2861
2417
            self.load()
2862
 
        except (errors.NoSuchFile, errors.PermissionDenied):
2863
 
            # If the file can't be read, there is no sections
 
2418
        except errors.NoSuchFile:
 
2419
            # If the file doesn't exist, there is no sections
2864
2420
            return
2865
2421
        cobj = self._config_obj
2866
2422
        if cobj.scalars:
2867
 
            yield self, self.readonly_section_class(None, cobj)
 
2423
            yield self.readonly_section_class(None, cobj)
2868
2424
        for section_name in cobj.sections:
2869
 
            yield (self,
2870
 
                   self.readonly_section_class(section_name,
2871
 
                                               cobj[section_name]))
 
2425
            yield self.readonly_section_class(section_name, cobj[section_name])
2872
2426
 
2873
 
    def get_mutable_section(self, section_id=None):
 
2427
    def get_mutable_section(self, section_name=None):
2874
2428
        # We need a loaded store
2875
2429
        try:
2876
2430
            self.load()
2877
2431
        except errors.NoSuchFile:
2878
2432
            # The file doesn't exist, let's pretend it was empty
2879
2433
            self._load_from_string('')
2880
 
        if section_id is None:
 
2434
        if section_name is None:
2881
2435
            section = self._config_obj
2882
2436
        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)
 
2437
            section = self._config_obj.setdefault(section_name, {})
 
2438
        return self.mutable_section_class(section_name, section)
2919
2439
 
2920
2440
 
2921
2441
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2924
2444
# they may face the same issue.
2925
2445
 
2926
2446
 
2927
 
class LockableIniFileStore(TransportIniFileStore):
 
2447
class LockableIniFileStore(IniFileStore):
2928
2448
    """A ConfigObjStore using locks on save to ensure store integrity."""
2929
2449
 
2930
2450
    def __init__(self, transport, file_name, lock_dir_name=None):
2977
2497
class GlobalStore(LockableIniFileStore):
2978
2498
 
2979
2499
    def __init__(self, possible_transports=None):
2980
 
        t = transport.get_transport_from_path(
2981
 
            config_dir(), possible_transports=possible_transports)
 
2500
        t = transport.get_transport(config_dir(),
 
2501
                                    possible_transports=possible_transports)
2982
2502
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
2983
 
        self.id = 'bazaar'
2984
2503
 
2985
2504
 
2986
2505
class LocationStore(LockableIniFileStore):
2987
2506
 
2988
2507
    def __init__(self, possible_transports=None):
2989
 
        t = transport.get_transport_from_path(
2990
 
            config_dir(), possible_transports=possible_transports)
 
2508
        t = transport.get_transport(config_dir(),
 
2509
                                    possible_transports=possible_transports)
2991
2510
        super(LocationStore, self).__init__(t, 'locations.conf')
2992
 
        self.id = 'locations'
2993
 
 
2994
 
 
2995
 
class BranchStore(TransportIniFileStore):
 
2511
 
 
2512
 
 
2513
class BranchStore(IniFileStore):
2996
2514
 
2997
2515
    def __init__(self, branch):
2998
2516
        super(BranchStore, self).__init__(branch.control_transport,
2999
2517
                                          'branch.conf')
3000
2518
        self.branch = branch
3001
 
        self.id = 'branch'
3002
2519
 
3003
2520
    def lock_write(self, token=None):
3004
2521
        return self.branch.lock_write(token)
3015
2532
        super(BranchStore, self).save()
3016
2533
 
3017
2534
 
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
2535
class SectionMatcher(object):
3027
2536
    """Select sections into a given Store.
3028
2537
 
3029
 
    This is intended to be used to postpone getting an iterable of sections
3030
 
    from a store.
 
2538
    This intended to be used to postpone getting an iterable of sections from a
 
2539
    store.
3031
2540
    """
3032
2541
 
3033
2542
    def __init__(self, store):
3038
2547
        # sections.
3039
2548
        sections = self.store.get_sections()
3040
2549
        # Walk the revisions in the order provided
3041
 
        for store, s in sections:
 
2550
        for s in sections:
3042
2551
            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
 
        """
 
2552
                yield s
 
2553
 
 
2554
    def match(self, secion):
3052
2555
        raise NotImplementedError(self.match)
3053
2556
 
3054
2557
 
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
2558
class LocationSection(Section):
3066
2559
 
3067
2560
    def __init__(self, section, length, extra_path):
3068
2561
        super(LocationSection, self).__init__(section.id, section.options)
3069
2562
        self.length = length
3070
2563
        self.extra_path = extra_path
3071
 
        self.locals = {'relpath': extra_path,
3072
 
                       'basename': urlutils.basename(extra_path)}
3073
2564
 
3074
 
    def get(self, name, default=None, expand=True):
 
2565
    def get(self, name, default=None):
3075
2566
        value = super(LocationSection, self).get(name, default)
3076
 
        if value is not None and expand:
 
2567
        if value is not None:
3077
2568
            policy_name = self.get(name + ':policy', None)
3078
2569
            policy = _policy_value.get(policy_name, POLICY_NONE)
3079
2570
            if policy == POLICY_APPENDPATH:
3080
2571
                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
2572
        return value
3095
2573
 
3096
2574
 
3107
2585
        # We slightly diverge from LocalConfig here by allowing the no-name
3108
2586
        # section as the most generic one and the lower priority.
3109
2587
        no_name_section = None
3110
 
        all_sections = []
 
2588
        sections = []
3111
2589
        # Filter out the no_name_section so _iter_for_location_by_parts can be
3112
2590
        # used (it assumes all sections have a name).
3113
 
        for _, section in self.store.get_sections():
 
2591
        for section in self.store.get_sections():
3114
2592
            if section.id is None:
3115
2593
                no_name_section = section
3116
2594
            else:
3117
 
                all_sections.append(section)
 
2595
                sections.append(section)
3118
2596
        # Unfortunately _iter_for_location_by_parts deals with section names so
3119
2597
        # we have to resync.
3120
2598
        filtered_sections = _iter_for_location_by_parts(
3121
 
            [s.id for s in all_sections], self.location)
3122
 
        iter_all_sections = iter(all_sections)
 
2599
            [s.id for s in sections], self.location)
 
2600
        iter_sections = iter(sections)
3123
2601
        matching_sections = []
3124
2602
        if no_name_section is not None:
3125
2603
            matching_sections.append(
3126
2604
                LocationSection(no_name_section, 0, self.location))
3127
2605
        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
 
2606
            # a section id is unique for a given store so it's safe to iterate
 
2607
            # again
 
2608
            section = iter_sections.next()
 
2609
            if section_id == section.id:
 
2610
                matching_sections.append(
 
2611
                    LocationSection(section, length, extra_path))
3138
2612
        return matching_sections
3139
2613
 
3140
2614
    def get_sections(self):
3153
2627
            if ignore:
3154
2628
                break
3155
2629
            # 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
 
2630
            yield section
3174
2631
 
3175
2632
 
3176
2633
class Stack(object):
3177
2634
    """A stack of configurations where an option can be defined"""
3178
2635
 
3179
 
    def __init__(self, sections_def, store=None, mutable_section_id=None):
 
2636
    def __init__(self, sections_def, store=None, mutable_section_name=None):
3180
2637
        """Creates a stack of sections with an optional store for changes.
3181
2638
 
3182
2639
        :param sections_def: A list of Section or callables that returns an
3186
2643
        :param store: The optional Store where modifications will be
3187
2644
            recorded. If none is specified, no modifications can be done.
3188
2645
 
3189
 
        :param mutable_section_id: The id of the MutableSection where changes
3190
 
            are recorded. This requires the ``store`` parameter to be
 
2646
        :param mutable_section_name: The name of the MutableSection where
 
2647
            changes are recorded. This requires the ``store`` parameter to be
3191
2648
            specified.
3192
2649
        """
3193
2650
        self.sections_def = sections_def
3194
2651
        self.store = store
3195
 
        self.mutable_section_id = mutable_section_id
 
2652
        self.mutable_section_name = mutable_section_name
3196
2653
 
3197
 
    def get(self, name, expand=None):
 
2654
    def get(self, name):
3198
2655
        """Return the *first* option value found in the sections.
3199
2656
 
3200
2657
        This is where we guarantee that sections coming from Store are loaded
3202
2659
        option exists or get its value, which in turn may require to discover
3203
2660
        in which sections it can be defined. Both of these (section and option
3204
2661
        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
2662
        """
3212
2663
        # FIXME: No caching of options nor sections yet -- vila 20110503
3213
 
        if expand is None:
3214
 
            expand = _get_expand_default_value()
3215
2664
        value = None
3216
2665
        # Ensuring lazy loading is achieved by delaying section matching (which
3217
2666
        # implies querying the persistent storage) until it can't be avoided
3218
2667
        # anymore by using callables to describe (possibly empty) section
3219
2668
        # lists.
3220
 
        for sections in self.sections_def:
3221
 
            for store, section in sections():
 
2669
        for section_or_callable in self.sections_def:
 
2670
            # Each section can expand to multiple ones when a callable is used
 
2671
            if callable(section_or_callable):
 
2672
                sections = section_or_callable()
 
2673
            else:
 
2674
                sections = [section_or_callable]
 
2675
            for section in sections:
3222
2676
                value = section.get(name)
3223
2677
                if value is not None:
3224
2678
                    break
3225
2679
            if value is not None:
3226
2680
                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:
 
2681
        if value is None:
3250
2682
            # If the option is registered, it may provide a default value
3251
 
            value = opt.get_default()
3252
 
            value = expand_and_convert(value)
 
2683
            try:
 
2684
                opt = option_registry.get(name)
 
2685
            except KeyError:
 
2686
                # Not registered
 
2687
                opt = None
 
2688
            if opt is not None:
 
2689
                value = opt.get_default()
3253
2690
        for hook in ConfigHooks['get']:
3254
2691
            hook(self, name, value)
3255
2692
        return value
3256
2693
 
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
2694
    def _get_mutable_section(self):
3323
2695
        """Get the MutableSection for the Stack.
3324
2696
 
3325
2697
        This is where we guarantee that the mutable section is lazily loaded:
3326
2698
        this means we won't load the corresponding store before setting a value
3327
2699
        or deleting an option. In practice the store will often be loaded but
3328
 
        this helps catching some programming errors.
 
2700
        this allows helps catching some programming errors.
3329
2701
        """
3330
 
        section = self.store.get_mutable_section(self.mutable_section_id)
 
2702
        section = self.store.get_mutable_section(self.mutable_section_name)
3331
2703
        return section
3332
2704
 
3333
2705
    def set(self, name, value):
3348
2720
        # Mostly for debugging use
3349
2721
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3350
2722
 
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
2723
 
3358
2724
class _CompatibleStack(Stack):
3359
2725
    """Place holder for compatibility with previous design.
3364
2730
    One assumption made here is that the daughter classes will all use Stores
3365
2731
    derived from LockableIniFileStore).
3366
2732
 
3367
 
    It implements set() and remove () by re-loading the store before applying
3368
 
    the modification and saving it.
 
2733
    It implements set() by re-loading the store before applying the
 
2734
    modification and saving it.
3369
2735
 
3370
2736
    The long term plan being to implement a single write by store to save
3371
2737
    all modifications, this class should not be used in the interim.
3378
2744
        # Force a write to persistent storage
3379
2745
        self.store.save()
3380
2746
 
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
2747
 
3389
2748
class GlobalStack(_CompatibleStack):
3390
 
    """Global options only stack."""
3391
2749
 
3392
2750
    def __init__(self):
3393
2751
        # Get a GlobalStore
3394
2752
        gstore = GlobalStore()
3395
 
        super(GlobalStack, self).__init__(
3396
 
            [self._get_overrides, NameMatcher(gstore, 'DEFAULT').get_sections],
3397
 
            gstore, mutable_section_id='DEFAULT')
 
2753
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3398
2754
 
3399
2755
 
3400
2756
class LocationStack(_CompatibleStack):
3401
 
    """Per-location options falling back to global options stack."""
3402
2757
 
3403
2758
    def __init__(self, location):
3404
 
        """Make a new stack for a location and global configuration.
3405
 
        
3406
 
        :param location: A URL prefix to """
3407
2759
        lstore = LocationStore()
3408
 
        if location.startswith('file://'):
3409
 
            location = urlutils.local_path_from_url(location)
3410
2760
        matcher = LocationMatcher(lstore, location)
3411
2761
        gstore = GlobalStore()
3412
2762
        super(LocationStack, self).__init__(
3413
 
            [self._get_overrides,
3414
 
             matcher.get_sections, NameMatcher(gstore, 'DEFAULT').get_sections],
3415
 
            lstore, mutable_section_id=location)
3416
 
 
 
2763
            [matcher.get_sections, gstore.get_sections], lstore)
3417
2764
 
3418
2765
class BranchStack(_CompatibleStack):
3419
 
    """Per-location options falling back to branch then global options stack."""
3420
2766
 
3421
2767
    def __init__(self, branch):
3422
 
        bstore = branch._get_config_store()
 
2768
        bstore = BranchStore(branch)
3423
2769
        lstore = LocationStore()
3424
2770
        matcher = LocationMatcher(lstore, branch.base)
3425
2771
        gstore = GlobalStore()
3426
2772
        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)
 
2773
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
 
2774
            bstore)
 
2775
        self.branch = branch
 
2776
 
3467
2777
 
3468
2778
class cmd_config(commands.Command):
3469
2779
    __doc__ = """Display, set or remove a configuration option.
3486
2796
    takes_options = [
3487
2797
        'directory',
3488
2798
        # 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
 
2799
        # their own config files (or not) -- vila 20101002
3491
2800
        commands.Option('scope', help='Reduce the scope to the specified'
3492
 
                        ' configuration file.',
 
2801
                        ' configuration file',
3493
2802
                        type=unicode),
3494
2803
        commands.Option('all',
3495
2804
            help='Display all the defined values for the matching options.',
3496
2805
            ),
3497
2806
        commands.Option('remove', help='Remove the option from'
3498
 
                        ' the configuration file.'),
 
2807
                        ' the configuration file'),
3499
2808
        ]
3500
2809
 
3501
2810
    _see_also = ['configuration']
3531
2840
                # Set the option value
3532
2841
                self._set_config_option(name, value, directory, scope)
3533
2842
 
3534
 
    def _get_stack(self, directory, scope=None):
3535
 
        """Get the configuration stack specified by ``directory`` and ``scope``.
 
2843
    def _get_configs(self, directory, scope=None):
 
2844
        """Iterate the configurations specified by ``directory`` and ``scope``.
3536
2845
 
3537
2846
        :param directory: Where the configurations are derived from.
3538
2847
 
3539
2848
        :param scope: A specific config to start from.
3540
2849
        """
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
2850
        if scope is not None:
3545
2851
            if scope == 'bazaar':
3546
 
                return GlobalStack()
 
2852
                yield GlobalConfig()
3547
2853
            elif scope == 'locations':
3548
 
                return LocationStack(directory)
 
2854
                yield LocationConfig(directory)
3549
2855
            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)
 
2856
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2857
                    directory)
 
2858
                yield br.get_config()
3555
2859
        else:
3556
2860
            try:
3557
 
                (_, br, _) = (
3558
 
                    controldir.ControlDir.open_containing_tree_or_branch(
3559
 
                        directory))
3560
 
                return br.get_config_stack()
 
2861
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2862
                    directory)
 
2863
                yield br.get_config()
3561
2864
            except errors.NotBranchError:
3562
 
                return LocationStack(directory)
 
2865
                yield LocationConfig(directory)
 
2866
                yield GlobalConfig()
3563
2867
 
3564
2868
    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:
 
2869
        displayed = False
 
2870
        for c in self._get_configs(directory, scope):
 
2871
            if displayed:
 
2872
                break
 
2873
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2874
                if name == oname:
 
2875
                    # Display only the first value and exit
 
2876
 
 
2877
                    # FIXME: We need to use get_user_option to take policies
 
2878
                    # into account and we need to make sure the option exists
 
2879
                    # too (hence the two for loops), this needs a better API
 
2880
                    # -- vila 20101117
 
2881
                    value = c.get_user_option(name)
 
2882
                    # Quote the value appropriately
 
2883
                    value = parser._quote(value)
 
2884
                    self.outf.write('%s\n' % (value,))
 
2885
                    displayed = True
 
2886
                    break
 
2887
        if not displayed:
3572
2888
            raise errors.NoSuchConfigOption(name)
3573
2889
 
3574
2890
    def _show_matching_options(self, name, directory, scope):
3575
 
        name = lazy_regex.lazy_compile(name)
 
2891
        name = re.compile(name)
3576
2892
        # We want any error in the regexp to be raised *now* so we need to
3577
 
        # avoid the delay introduced by the lazy regexp.  But, we still do
3578
 
        # want the nicer errors raised by lazy_regex.
 
2893
        # avoid the delay introduced by the lazy regexp.
3579
2894
        name._compile_and_collapse()
3580
 
        cur_store_id = None
 
2895
        cur_conf_id = None
3581
2896
        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))
 
2897
        for c in self._get_configs(directory, scope):
 
2898
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2899
                if name.search(oname):
 
2900
                    if cur_conf_id != conf_id:
 
2901
                        # Explain where the options are defined
 
2902
                        self.outf.write('%s:\n' % (conf_id,))
 
2903
                        cur_conf_id = conf_id
 
2904
                        cur_section = None
 
2905
                    if (section not in (None, 'DEFAULT')
 
2906
                        and cur_section != section):
 
2907
                        # Display the section if it's not the default (or only)
 
2908
                        # one.
 
2909
                        self.outf.write('  [%s]\n' % (section,))
 
2910
                        cur_section = section
 
2911
                    self.outf.write('  %s = %s\n' % (oname, value))
3601
2912
 
3602
2913
    def _set_config_option(self, name, value, directory, scope):
3603
 
        conf = self._get_stack(directory, scope)
3604
 
        conf.set(name, value)
 
2914
        for conf in self._get_configs(directory, scope):
 
2915
            conf.set_user_option(name, value)
 
2916
            break
 
2917
        else:
 
2918
            raise errors.NoSuchConfig(scope)
3605
2919
 
3606
2920
    def _remove_config_option(self, name, directory, scope):
3607
2921
        if name is None:
3608
2922
            raise errors.BzrCommandError(
3609
2923
                '--remove expects an option to remove.')
3610
 
        conf = self._get_stack(directory, scope)
3611
 
        try:
3612
 
            conf.remove(name)
3613
 
        except KeyError:
 
2924
        removed = False
 
2925
        for conf in self._get_configs(directory, scope):
 
2926
            for (section_name, section, conf_id) in conf._get_sections():
 
2927
                if scope is not None and conf_id != scope:
 
2928
                    # Not the right configuration file
 
2929
                    continue
 
2930
                if name in section:
 
2931
                    if conf_id != conf.config_id():
 
2932
                        conf = self._get_configs(directory, conf_id).next()
 
2933
                    # We use the first section in the first config where the
 
2934
                    # option is defined to remove it
 
2935
                    conf.remove_user_option(name, section_name)
 
2936
                    removed = True
 
2937
                    break
 
2938
            break
 
2939
        else:
 
2940
            raise errors.NoSuchConfig(scope)
 
2941
        if not removed:
3614
2942
            raise errors.NoSuchConfigOption(name)
3615
2943
 
3616
 
 
3617
2944
# Test registries
3618
2945
#
3619
2946
# We need adapters that can build a Store or a Stack in a test context. Test
3622
2949
# ready-to-use store or stack.  Plugins that define new store/stacks can also
3623
2950
# register themselves here to be tested against the tests defined in
3624
2951
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3625
 
# for the same test.
 
2952
# for the same tests.
3626
2953
 
3627
2954
# The registered object should be a callable receiving a test instance
3628
2955
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store