~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

MergeĀ lp:~gz/bzr/path_from_environ_832028

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
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
32
35
 
33
36
in locations.conf, you specify the url of a branch and options for it.
34
37
Wildcards may be used - * and ? as normal in shell completion. Options
39
42
email= as above
40
43
check_signatures= as above
41
44
create_signatures= as above.
 
45
validate_signatures_in_log=as above
 
46
acceptable_keys=as above
42
47
 
43
48
explanation of options
44
49
----------------------
45
50
editor - this option sets the pop up editor to use during commits.
46
51
email - this option sets the user id bzr will use when committing.
47
 
check_signatures - this option controls whether bzr will require good gpg
 
52
check_signatures - this option will control whether bzr will require good gpg
48
53
                   signatures, ignore them, or check them if they are
49
 
                   present.
 
54
                   present.  Currently it is unused except that check_signatures
 
55
                   turns on create_signatures.
50
56
create_signatures - this option controls whether bzr will always create
51
 
                    gpg signatures, never create them, or create them if the
52
 
                    branch is configured to require them.
 
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.
53
60
log_format - this option sets the default log format.  Possible values are
54
61
             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
55
65
 
56
66
In bazaar.conf you can also define aliases in the ALIASES sections, example
57
67
 
63
73
"""
64
74
 
65
75
import os
 
76
import string
66
77
import sys
67
78
 
 
79
 
 
80
import bzrlib
68
81
from bzrlib.decorators import needs_write_lock
69
82
from bzrlib.lazy_import import lazy_import
70
83
lazy_import(globals(), """
71
 
import errno
72
 
from fnmatch import fnmatch
 
84
import fnmatch
73
85
import re
74
86
from cStringIO import StringIO
75
87
 
76
 
import bzrlib
77
88
from bzrlib import (
78
89
    atomicfile,
 
90
    controldir,
79
91
    debug,
80
92
    errors,
 
93
    lazy_regex,
 
94
    library_state,
81
95
    lockdir,
82
96
    mail_client,
 
97
    mergetools,
83
98
    osutils,
84
 
    registry,
85
99
    symbol_versioning,
86
100
    trace,
87
101
    transport,
89
103
    urlutils,
90
104
    win32utils,
91
105
    )
 
106
from bzrlib.i18n import gettext
92
107
from bzrlib.util.configobj import configobj
93
108
""")
 
109
from bzrlib import (
 
110
    commands,
 
111
    hooks,
 
112
    lazy_regex,
 
113
    registry,
 
114
    )
 
115
from bzrlib.symbol_versioning import (
 
116
    deprecated_in,
 
117
    deprecated_method,
 
118
    )
94
119
 
95
120
 
96
121
CHECK_IF_POSSIBLE=0
126
151
STORE_BRANCH = 3
127
152
STORE_GLOBAL = 4
128
153
 
129
 
_ConfigObj = None
130
 
def ConfigObj(*args, **kwargs):
131
 
    global _ConfigObj
132
 
    if _ConfigObj is None:
133
 
        class ConfigObj(configobj.ConfigObj):
134
 
 
135
 
            def get_bool(self, section, key):
136
 
                return self[section].as_bool(key)
137
 
 
138
 
            def get_value(self, section, name):
139
 
                # Try [] for the old DEFAULT section.
140
 
                if section == "DEFAULT":
141
 
                    try:
142
 
                        return self[name]
143
 
                    except KeyError:
144
 
                        pass
145
 
                return self[section][name]
146
 
        _ConfigObj = ConfigObj
147
 
    return _ConfigObj(*args, **kwargs)
 
154
 
 
155
def signature_policy_from_unicode(signature_string):
 
156
    """Convert a string to a signing policy."""
 
157
    if signature_string.lower() == 'check-available':
 
158
        return CHECK_IF_POSSIBLE
 
159
    if signature_string.lower() == 'ignore':
 
160
        return CHECK_NEVER
 
161
    if signature_string.lower() == 'require':
 
162
        return CHECK_ALWAYS
 
163
    raise ValueError("Invalid signatures policy '%s'"
 
164
                     % signature_string)
 
165
 
 
166
 
 
167
def signing_policy_from_unicode(signature_string):
 
168
    """Convert a string to a signing policy."""
 
169
    if signature_string.lower() == 'when-required':
 
170
        return SIGN_WHEN_REQUIRED
 
171
    if signature_string.lower() == 'never':
 
172
        return SIGN_NEVER
 
173
    if signature_string.lower() == 'always':
 
174
        return SIGN_ALWAYS
 
175
    raise ValueError("Invalid signing policy '%s'"
 
176
                     % signature_string)
 
177
 
 
178
 
 
179
class ConfigObj(configobj.ConfigObj):
 
180
 
 
181
    def __init__(self, infile=None, **kwargs):
 
182
        # We define our own interpolation mechanism calling it option expansion
 
183
        super(ConfigObj, self).__init__(infile=infile,
 
184
                                        interpolation=False,
 
185
                                        **kwargs)
 
186
 
 
187
    def get_bool(self, section, key):
 
188
        return self[section].as_bool(key)
 
189
 
 
190
    def get_value(self, section, name):
 
191
        # Try [] for the old DEFAULT section.
 
192
        if section == "DEFAULT":
 
193
            try:
 
194
                return self[name]
 
195
            except KeyError:
 
196
                pass
 
197
        return self[section][name]
 
198
 
 
199
 
 
200
# FIXME: Until we can guarantee that each config file is loaded once and
 
201
# only once for a given bzrlib session, we don't want to re-read the file every
 
202
# time we query for an option so we cache the value (bad ! watch out for tests
 
203
# needing to restore the proper value). -- vila 20110219
 
204
_expand_default_value = None
 
205
def _get_expand_default_value():
 
206
    global _expand_default_value
 
207
    if _expand_default_value is not None:
 
208
        return _expand_default_value
 
209
    conf = GlobalConfig()
 
210
    # Note that we must not use None for the expand value below or we'll run
 
211
    # into infinite recursion. Using False really would be quite silly ;)
 
212
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
 
213
    if expand is None:
 
214
        # This is an opt-in feature, you *really* need to clearly say you want
 
215
        # to activate it !
 
216
        expand = False
 
217
    _expand_default_value = expand
 
218
    return expand
148
219
 
149
220
 
150
221
class Config(object):
153
224
    def __init__(self):
154
225
        super(Config, self).__init__()
155
226
 
 
227
    def config_id(self):
 
228
        """Returns a unique ID for the config."""
 
229
        raise NotImplementedError(self.config_id)
 
230
 
 
231
    @deprecated_method(deprecated_in((2, 4, 0)))
156
232
    def get_editor(self):
157
233
        """Get the users pop up editor."""
158
234
        raise NotImplementedError
165
241
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
166
242
                                             sys.stdout)
167
243
 
168
 
 
169
244
    def get_mail_client(self):
170
245
        """Get a mail client to use"""
171
246
        selected_client = self.get_user_option('mail_client')
182
257
    def _get_signing_policy(self):
183
258
        """Template method to override signature creation policy."""
184
259
 
 
260
    option_ref_re = None
 
261
 
 
262
    def expand_options(self, string, env=None):
 
263
        """Expand option references in the string in the configuration context.
 
264
 
 
265
        :param string: The string containing option to expand.
 
266
 
 
267
        :param env: An option dict defining additional configuration options or
 
268
            overriding existing ones.
 
269
 
 
270
        :returns: The expanded string.
 
271
        """
 
272
        return self._expand_options_in_string(string, env)
 
273
 
 
274
    def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
 
275
        """Expand options in  a list of strings in the configuration context.
 
276
 
 
277
        :param slist: A list of strings.
 
278
 
 
279
        :param env: An option dict defining additional configuration options or
 
280
            overriding existing ones.
 
281
 
 
282
        :param _ref_stack: Private list containing the options being
 
283
            expanded to detect loops.
 
284
 
 
285
        :returns: The flatten list of expanded strings.
 
286
        """
 
287
        # expand options in each value separately flattening lists
 
288
        result = []
 
289
        for s in slist:
 
290
            value = self._expand_options_in_string(s, env, _ref_stack)
 
291
            if isinstance(value, list):
 
292
                result.extend(value)
 
293
            else:
 
294
                result.append(value)
 
295
        return result
 
296
 
 
297
    def _expand_options_in_string(self, string, env=None, _ref_stack=None):
 
298
        """Expand options in the string in the configuration context.
 
299
 
 
300
        :param string: The string to be expanded.
 
301
 
 
302
        :param env: An option dict defining additional configuration options or
 
303
            overriding existing ones.
 
304
 
 
305
        :param _ref_stack: Private list containing the options being
 
306
            expanded to detect loops.
 
307
 
 
308
        :returns: The expanded string.
 
309
        """
 
310
        if string is None:
 
311
            # Not much to expand there
 
312
            return None
 
313
        if _ref_stack is None:
 
314
            # What references are currently resolved (to detect loops)
 
315
            _ref_stack = []
 
316
        if self.option_ref_re is None:
 
317
            # We want to match the most embedded reference first (i.e. for
 
318
            # '{{foo}}' we will get '{foo}',
 
319
            # for '{bar{baz}}' we will get '{baz}'
 
320
            self.option_ref_re = re.compile('({[^{}]+})')
 
321
        result = string
 
322
        # We need to iterate until no more refs appear ({{foo}} will need two
 
323
        # iterations for example).
 
324
        while True:
 
325
            raw_chunks = self.option_ref_re.split(result)
 
326
            if len(raw_chunks) == 1:
 
327
                # Shorcut the trivial case: no refs
 
328
                return result
 
329
            chunks = []
 
330
            list_value = False
 
331
            # Split will isolate refs so that every other chunk is a ref
 
332
            chunk_is_ref = False
 
333
            for chunk in raw_chunks:
 
334
                if not chunk_is_ref:
 
335
                    if chunk:
 
336
                        # Keep only non-empty strings (or we get bogus empty
 
337
                        # slots when a list value is involved).
 
338
                        chunks.append(chunk)
 
339
                    chunk_is_ref = True
 
340
                else:
 
341
                    name = chunk[1:-1]
 
342
                    if name in _ref_stack:
 
343
                        raise errors.OptionExpansionLoop(string, _ref_stack)
 
344
                    _ref_stack.append(name)
 
345
                    value = self._expand_option(name, env, _ref_stack)
 
346
                    if value is None:
 
347
                        raise errors.ExpandingUnknownOption(name, string)
 
348
                    if isinstance(value, list):
 
349
                        list_value = True
 
350
                        chunks.extend(value)
 
351
                    else:
 
352
                        chunks.append(value)
 
353
                    _ref_stack.pop()
 
354
                    chunk_is_ref = False
 
355
            if list_value:
 
356
                # Once a list appears as the result of an expansion, all
 
357
                # callers will get a list result. This allows a consistent
 
358
                # behavior even when some options in the expansion chain
 
359
                # defined as strings (no comma in their value) but their
 
360
                # expanded value is a list.
 
361
                return self._expand_options_in_list(chunks, env, _ref_stack)
 
362
            else:
 
363
                result = ''.join(chunks)
 
364
        return result
 
365
 
 
366
    def _expand_option(self, name, env, _ref_stack):
 
367
        if env is not None and name in env:
 
368
            # Special case, values provided in env takes precedence over
 
369
            # anything else
 
370
            value = env[name]
 
371
        else:
 
372
            # FIXME: This is a limited implementation, what we really need is a
 
373
            # way to query the bzr config for the value of an option,
 
374
            # respecting the scope rules (That is, once we implement fallback
 
375
            # configs, getting the option value should restart from the top
 
376
            # config, not the current one) -- vila 20101222
 
377
            value = self.get_user_option(name, expand=False)
 
378
            if isinstance(value, list):
 
379
                value = self._expand_options_in_list(value, env, _ref_stack)
 
380
            else:
 
381
                value = self._expand_options_in_string(value, env, _ref_stack)
 
382
        return value
 
383
 
185
384
    def _get_user_option(self, option_name):
186
385
        """Template method to provide a user option."""
187
386
        return None
188
387
 
189
 
    def get_user_option(self, option_name):
190
 
        """Get a generic option - no special process, no default."""
191
 
        return self._get_user_option(option_name)
192
 
 
193
 
    def get_user_option_as_bool(self, option_name):
194
 
        """Get a generic option as a boolean - no special process, no default.
195
 
 
 
388
    def get_user_option(self, option_name, expand=None):
 
389
        """Get a generic option - no special process, no default.
 
390
 
 
391
        :param option_name: The queried option.
 
392
 
 
393
        :param expand: Whether options references should be expanded.
 
394
 
 
395
        :returns: The value of the option.
 
396
        """
 
397
        if expand is None:
 
398
            expand = _get_expand_default_value()
 
399
        value = self._get_user_option(option_name)
 
400
        if expand:
 
401
            if isinstance(value, list):
 
402
                value = self._expand_options_in_list(value)
 
403
            elif isinstance(value, dict):
 
404
                trace.warning('Cannot expand "%s":'
 
405
                              ' Dicts do not support option expansion'
 
406
                              % (option_name,))
 
407
            else:
 
408
                value = self._expand_options_in_string(value)
 
409
        for hook in OldConfigHooks['get']:
 
410
            hook(self, option_name, value)
 
411
        return value
 
412
 
 
413
    def get_user_option_as_bool(self, option_name, expand=None, default=None):
 
414
        """Get a generic option as a boolean.
 
415
 
 
416
        :param expand: Allow expanding references to other config values.
 
417
        :param default: Default value if nothing is configured
196
418
        :return None if the option doesn't exist or its value can't be
197
419
            interpreted as a boolean. Returns True or False otherwise.
198
420
        """
199
 
        s = self._get_user_option(option_name)
 
421
        s = self.get_user_option(option_name, expand=expand)
200
422
        if s is None:
201
423
            # The option doesn't exist
202
 
            return None
 
424
            return default
203
425
        val = ui.bool_from_string(s)
204
426
        if val is None:
205
427
            # The value can't be interpreted as a boolean
207
429
                          s, option_name)
208
430
        return val
209
431
 
210
 
    def get_user_option_as_list(self, option_name):
 
432
    def get_user_option_as_list(self, option_name, expand=None):
211
433
        """Get a generic option as a list - no special process, no default.
212
434
 
213
435
        :return None if the option doesn't exist. Returns the value as a list
214
436
            otherwise.
215
437
        """
216
 
        l = self._get_user_option(option_name)
 
438
        l = self.get_user_option(option_name, expand=expand)
217
439
        if isinstance(l, (str, unicode)):
218
 
            # A single value, most probably the user forgot the final ','
 
440
            # A single value, most probably the user forgot (or didn't care to
 
441
            # add) the final ','
219
442
            l = [l]
220
443
        return l
 
444
        
 
445
    def get_user_option_as_int_from_SI(self, option_name, default=None):
 
446
        """Get a generic option from a human readable size in SI units, e.g 10MB
 
447
        
 
448
        Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
449
        by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
450
        pedantic.
 
451
        
 
452
        :return Integer, expanded to its base-10 value if a proper SI unit is 
 
453
            found. If the option doesn't exist, or isn't a value in 
 
454
            SI units, return default (which defaults to None)
 
455
        """
 
456
        val = self.get_user_option(option_name)
 
457
        if isinstance(val, list):
 
458
            val = val[0]
 
459
        if val is None:
 
460
            val = default
 
461
        else:
 
462
            p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
 
463
            try:
 
464
                m = p.match(val)
 
465
                if m is not None:
 
466
                    val = int(m.group(1))
 
467
                    if m.group(2) is not None:
 
468
                        if m.group(2).lower() == 'k':
 
469
                            val *= 10**3
 
470
                        elif m.group(2).lower() == 'm':
 
471
                            val *= 10**6
 
472
                        elif m.group(2).lower() == 'g':
 
473
                            val *= 10**9
 
474
                else:
 
475
                    ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
 
476
                                               ' value {1!r} is not an SI unit.').format(
 
477
                                                option_name, val))
 
478
                    val = default
 
479
            except TypeError:
 
480
                val = default
 
481
        return val
 
482
        
221
483
 
 
484
    @deprecated_method(deprecated_in((2, 5, 0)))
222
485
    def gpg_signing_command(self):
223
486
        """What program should be used to sign signatures?"""
224
487
        result = self._gpg_signing_command()
241
504
        """See log_format()."""
242
505
        return None
243
506
 
 
507
    def validate_signatures_in_log(self):
 
508
        """Show GPG signature validity in log"""
 
509
        result = self._validate_signatures_in_log()
 
510
        if result == "true":
 
511
            result = True
 
512
        else:
 
513
            result = False
 
514
        return result
 
515
 
 
516
    def _validate_signatures_in_log(self):
 
517
        """See validate_signatures_in_log()."""
 
518
        return None
 
519
 
 
520
    @deprecated_method(deprecated_in((2, 5, 0)))
 
521
    def acceptable_keys(self):
 
522
        """Comma separated list of key patterns acceptable to 
 
523
        verify-signatures command"""
 
524
        result = self._acceptable_keys()
 
525
        return result
 
526
 
 
527
    def _acceptable_keys(self):
 
528
        """See acceptable_keys()."""
 
529
        return None
 
530
 
244
531
    def post_commit(self):
245
532
        """An ordered list of python functions to call.
246
533
 
265
552
        the concrete policy type is checked, and finally
266
553
        $EMAIL is examined.
267
554
        If no username can be found, errors.NoWhoami exception is raised.
268
 
 
269
 
        TODO: Check it's reasonably well-formed.
270
555
        """
271
556
        v = os.environ.get('BZR_EMAIL')
272
557
        if v:
273
558
            return v.decode(osutils.get_user_encoding())
274
 
 
275
559
        v = self._get_user_id()
276
560
        if v:
277
561
            return v
278
 
 
279
562
        v = os.environ.get('EMAIL')
280
563
        if v:
281
564
            return v.decode(osutils.get_user_encoding())
282
 
 
 
565
        name, email = _auto_user_id()
 
566
        if name and email:
 
567
            return '%s <%s>' % (name, email)
 
568
        elif email:
 
569
            return email
283
570
        raise errors.NoWhoami()
284
571
 
285
572
    def ensure_username(self):
289
576
        """
290
577
        self.username()
291
578
 
 
579
    @deprecated_method(deprecated_in((2, 5, 0)))
292
580
    def signature_checking(self):
293
581
        """What is the current policy for signature checking?."""
294
582
        policy = self._get_signature_checking()
296
584
            return policy
297
585
        return CHECK_IF_POSSIBLE
298
586
 
 
587
    @deprecated_method(deprecated_in((2, 5, 0)))
299
588
    def signing_policy(self):
300
589
        """What is the current policy for signature checking?."""
301
590
        policy = self._get_signing_policy()
303
592
            return policy
304
593
        return SIGN_WHEN_REQUIRED
305
594
 
 
595
    @deprecated_method(deprecated_in((2, 5, 0)))
306
596
    def signature_needed(self):
307
597
        """Is a signature needed when committing ?."""
308
598
        policy = self._get_signing_policy()
309
599
        if policy is None:
310
600
            policy = self._get_signature_checking()
311
601
            if policy is not None:
 
602
                #this warning should go away once check_signatures is
 
603
                #implemented (if not before)
312
604
                trace.warning("Please use create_signatures,"
313
605
                              " not check_signatures to set signing policy.")
314
 
            if policy == CHECK_ALWAYS:
315
 
                return True
316
606
        elif policy == SIGN_ALWAYS:
317
607
            return True
318
608
        return False
319
609
 
 
610
    @deprecated_method(deprecated_in((2, 5, 0)))
 
611
    def gpg_signing_key(self):
 
612
        """GPG user-id to sign commits"""
 
613
        key = self.get_user_option('gpg_signing_key')
 
614
        if key == "default" or key == None:
 
615
            return self.user_email()
 
616
        else:
 
617
            return key
 
618
 
320
619
    def get_alias(self, value):
321
620
        return self._get_alias(value)
322
621
 
351
650
        else:
352
651
            return True
353
652
 
 
653
    def get_merge_tools(self):
 
654
        tools = {}
 
655
        for (oname, value, section, conf_id, parser) in self._get_options():
 
656
            if oname.startswith('bzr.mergetool.'):
 
657
                tool_name = oname[len('bzr.mergetool.'):]
 
658
                tools[tool_name] = self.get_user_option(oname)
 
659
        trace.mutter('loaded merge tools: %r' % tools)
 
660
        return tools
 
661
 
 
662
    def find_merge_tool(self, name):
 
663
        # We fake a defaults mechanism here by checking if the given name can
 
664
        # be found in the known_merge_tools if it's not found in the config.
 
665
        # This should be done through the proposed config defaults mechanism
 
666
        # when it becomes available in the future.
 
667
        command_line = (self.get_user_option('bzr.mergetool.%s' % name,
 
668
                                             expand=False)
 
669
                        or mergetools.known_merge_tools.get(name, None))
 
670
        return command_line
 
671
 
 
672
 
 
673
class _ConfigHooks(hooks.Hooks):
 
674
    """A dict mapping hook names and a list of callables for configs.
 
675
    """
 
676
 
 
677
    def __init__(self):
 
678
        """Create the default hooks.
 
679
 
 
680
        These are all empty initially, because by default nothing should get
 
681
        notified.
 
682
        """
 
683
        super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
 
684
        self.add_hook('load',
 
685
                      'Invoked when a config store is loaded.'
 
686
                      ' The signature is (store).',
 
687
                      (2, 4))
 
688
        self.add_hook('save',
 
689
                      'Invoked when a config store is saved.'
 
690
                      ' The signature is (store).',
 
691
                      (2, 4))
 
692
        # The hooks for config options
 
693
        self.add_hook('get',
 
694
                      'Invoked when a config option is read.'
 
695
                      ' The signature is (stack, name, value).',
 
696
                      (2, 4))
 
697
        self.add_hook('set',
 
698
                      'Invoked when a config option is set.'
 
699
                      ' The signature is (stack, name, value).',
 
700
                      (2, 4))
 
701
        self.add_hook('remove',
 
702
                      'Invoked when a config option is removed.'
 
703
                      ' The signature is (stack, name).',
 
704
                      (2, 4))
 
705
ConfigHooks = _ConfigHooks()
 
706
 
 
707
 
 
708
class _OldConfigHooks(hooks.Hooks):
 
709
    """A dict mapping hook names and a list of callables for configs.
 
710
    """
 
711
 
 
712
    def __init__(self):
 
713
        """Create the default hooks.
 
714
 
 
715
        These are all empty initially, because by default nothing should get
 
716
        notified.
 
717
        """
 
718
        super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
 
719
        self.add_hook('load',
 
720
                      'Invoked when a config store is loaded.'
 
721
                      ' The signature is (config).',
 
722
                      (2, 4))
 
723
        self.add_hook('save',
 
724
                      'Invoked when a config store is saved.'
 
725
                      ' The signature is (config).',
 
726
                      (2, 4))
 
727
        # The hooks for config options
 
728
        self.add_hook('get',
 
729
                      'Invoked when a config option is read.'
 
730
                      ' The signature is (config, name, value).',
 
731
                      (2, 4))
 
732
        self.add_hook('set',
 
733
                      'Invoked when a config option is set.'
 
734
                      ' The signature is (config, name, value).',
 
735
                      (2, 4))
 
736
        self.add_hook('remove',
 
737
                      'Invoked when a config option is removed.'
 
738
                      ' The signature is (config, name).',
 
739
                      (2, 4))
 
740
OldConfigHooks = _OldConfigHooks()
 
741
 
354
742
 
355
743
class IniBasedConfig(Config):
356
744
    """A configuration policy that draws from ini files."""
417
805
            self._parser = ConfigObj(co_input, encoding='utf-8')
418
806
        except configobj.ConfigObjError, e:
419
807
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
808
        except UnicodeDecodeError:
 
809
            raise errors.ConfigContentError(self.file_name)
420
810
        # Make sure self.reload() will use the right file name
421
811
        self._parser.filename = self.file_name
 
812
        for hook in OldConfigHooks['load']:
 
813
            hook(self)
422
814
        return self._parser
423
815
 
424
816
    def reload(self):
427
819
            raise AssertionError('We need a file name to reload the config')
428
820
        if self._parser is not None:
429
821
            self._parser.reload()
 
822
        for hook in ConfigHooks['load']:
 
823
            hook(self)
430
824
 
431
825
    def _get_matching_sections(self):
432
826
        """Return an ordered list of (section_name, extra_path) pairs.
444
838
        """Override this to define the section used by the config."""
445
839
        return "DEFAULT"
446
840
 
 
841
    def _get_sections(self, name=None):
 
842
        """Returns an iterator of the sections specified by ``name``.
 
843
 
 
844
        :param name: The section name. If None is supplied, the default
 
845
            configurations are yielded.
 
846
 
 
847
        :return: A tuple (name, section, config_id) for all sections that will
 
848
            be walked by user_get_option() in the 'right' order. The first one
 
849
            is where set_user_option() will update the value.
 
850
        """
 
851
        parser = self._get_parser()
 
852
        if name is not None:
 
853
            yield (name, parser[name], self.config_id())
 
854
        else:
 
855
            # No section name has been given so we fallback to the configobj
 
856
            # itself which holds the variables defined outside of any section.
 
857
            yield (None, parser, self.config_id())
 
858
 
 
859
    def _get_options(self, sections=None):
 
860
        """Return an ordered list of (name, value, section, config_id) tuples.
 
861
 
 
862
        All options are returned with their associated value and the section
 
863
        they appeared in. ``config_id`` is a unique identifier for the
 
864
        configuration file the option is defined in.
 
865
 
 
866
        :param sections: Default to ``_get_matching_sections`` if not
 
867
            specified. This gives a better control to daughter classes about
 
868
            which sections should be searched. This is a list of (name,
 
869
            configobj) tuples.
 
870
        """
 
871
        opts = []
 
872
        if sections is None:
 
873
            parser = self._get_parser()
 
874
            sections = []
 
875
            for (section_name, _) in self._get_matching_sections():
 
876
                try:
 
877
                    section = parser[section_name]
 
878
                except KeyError:
 
879
                    # This could happen for an empty file for which we define a
 
880
                    # DEFAULT section. FIXME: Force callers to provide sections
 
881
                    # instead ? -- vila 20100930
 
882
                    continue
 
883
                sections.append((section_name, section))
 
884
        config_id = self.config_id()
 
885
        for (section_name, section) in sections:
 
886
            for (name, value) in section.iteritems():
 
887
                yield (name, parser._quote(value), section_name,
 
888
                       config_id, parser)
 
889
 
447
890
    def _get_option_policy(self, section, option_name):
448
891
        """Return the policy for the given (section, option_name) pair."""
449
892
        return POLICY_NONE
455
898
        """See Config._get_signature_checking."""
456
899
        policy = self._get_user_option('check_signatures')
457
900
        if policy:
458
 
            return self._string_to_signature_policy(policy)
 
901
            return signature_policy_from_unicode(policy)
459
902
 
460
903
    def _get_signing_policy(self):
461
904
        """See Config._get_signing_policy"""
462
905
        policy = self._get_user_option('create_signatures')
463
906
        if policy:
464
 
            return self._string_to_signing_policy(policy)
 
907
            return signing_policy_from_unicode(policy)
465
908
 
466
909
    def _get_user_id(self):
467
910
        """Get the user id from the 'email' key in the current section."""
500
943
        """See Config.log_format."""
501
944
        return self._get_user_option('log_format')
502
945
 
 
946
    def _validate_signatures_in_log(self):
 
947
        """See Config.validate_signatures_in_log."""
 
948
        return self._get_user_option('validate_signatures_in_log')
 
949
 
 
950
    def _acceptable_keys(self):
 
951
        """See Config.acceptable_keys."""
 
952
        return self._get_user_option('acceptable_keys')
 
953
 
503
954
    def _post_commit(self):
504
955
        """See Config.post_commit."""
505
956
        return self._get_user_option('post_commit')
506
957
 
507
 
    def _string_to_signature_policy(self, signature_string):
508
 
        """Convert a string to a signing policy."""
509
 
        if signature_string.lower() == 'check-available':
510
 
            return CHECK_IF_POSSIBLE
511
 
        if signature_string.lower() == 'ignore':
512
 
            return CHECK_NEVER
513
 
        if signature_string.lower() == 'require':
514
 
            return CHECK_ALWAYS
515
 
        raise errors.BzrError("Invalid signatures policy '%s'"
516
 
                              % signature_string)
517
 
 
518
 
    def _string_to_signing_policy(self, signature_string):
519
 
        """Convert a string to a signing policy."""
520
 
        if signature_string.lower() == 'when-required':
521
 
            return SIGN_WHEN_REQUIRED
522
 
        if signature_string.lower() == 'never':
523
 
            return SIGN_NEVER
524
 
        if signature_string.lower() == 'always':
525
 
            return SIGN_ALWAYS
526
 
        raise errors.BzrError("Invalid signing policy '%s'"
527
 
                              % signature_string)
528
 
 
529
958
    def _get_alias(self, value):
530
959
        try:
531
960
            return self._get_parser().get_value("ALIASES",
536
965
    def _get_nickname(self):
537
966
        return self.get_user_option('nickname')
538
967
 
 
968
    def remove_user_option(self, option_name, section_name=None):
 
969
        """Remove a user option and save the configuration file.
 
970
 
 
971
        :param option_name: The option to be removed.
 
972
 
 
973
        :param section_name: The section the option is defined in, default to
 
974
            the default section.
 
975
        """
 
976
        self.reload()
 
977
        parser = self._get_parser()
 
978
        if section_name is None:
 
979
            section = parser
 
980
        else:
 
981
            section = parser[section_name]
 
982
        try:
 
983
            del section[option_name]
 
984
        except KeyError:
 
985
            raise errors.NoSuchConfigOption(option_name)
 
986
        self._write_config_file()
 
987
        for hook in OldConfigHooks['remove']:
 
988
            hook(self, option_name)
 
989
 
539
990
    def _write_config_file(self):
540
991
        if self.file_name is None:
541
992
            raise AssertionError('We cannot save, self.file_name is None')
546
997
        atomic_file.commit()
547
998
        atomic_file.close()
548
999
        osutils.copy_ownership_from_path(self.file_name)
 
1000
        for hook in OldConfigHooks['save']:
 
1001
            hook(self)
549
1002
 
550
1003
 
551
1004
class LockableConfig(IniBasedConfig):
578
1031
    def __init__(self, file_name):
579
1032
        super(LockableConfig, self).__init__(file_name=file_name)
580
1033
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
581
 
        self.transport = transport.get_transport(self.dir)
582
 
        self._lock = lockdir.LockDir(self.transport, 'lock')
 
1034
        # FIXME: It doesn't matter that we don't provide possible_transports
 
1035
        # below since this is currently used only for local config files ;
 
1036
        # local transports are not shared. But if/when we start using
 
1037
        # LockableConfig for other kind of transports, we will need to reuse
 
1038
        # whatever connection is already established -- vila 20100929
 
1039
        self.transport = transport.get_transport_from_path(self.dir)
 
1040
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
583
1041
 
584
1042
    def _create_from_string(self, unicode_bytes, save):
585
1043
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
604
1062
    def break_lock(self):
605
1063
        self._lock.break_lock()
606
1064
 
 
1065
    @needs_write_lock
 
1066
    def remove_user_option(self, option_name, section_name=None):
 
1067
        super(LockableConfig, self).remove_user_option(option_name,
 
1068
                                                       section_name)
 
1069
 
607
1070
    def _write_config_file(self):
608
1071
        if self._lock is None or not self._lock.is_held:
609
1072
            # NB: if the following exception is raised it probably means a
618
1081
    def __init__(self):
619
1082
        super(GlobalConfig, self).__init__(file_name=config_filename())
620
1083
 
 
1084
    def config_id(self):
 
1085
        return 'bazaar'
 
1086
 
621
1087
    @classmethod
622
1088
    def from_string(cls, str_or_unicode, save=False):
623
1089
        """Create a config object from a string.
631
1097
        conf._create_from_string(str_or_unicode, save)
632
1098
        return conf
633
1099
 
 
1100
    @deprecated_method(deprecated_in((2, 4, 0)))
634
1101
    def get_editor(self):
635
1102
        return self._get_user_option('editor')
636
1103
 
665
1132
        self.reload()
666
1133
        self._get_parser().setdefault(section, {})[option] = value
667
1134
        self._write_config_file()
 
1135
        for hook in OldConfigHooks['set']:
 
1136
            hook(self, option, value)
 
1137
 
 
1138
    def _get_sections(self, name=None):
 
1139
        """See IniBasedConfig._get_sections()."""
 
1140
        parser = self._get_parser()
 
1141
        # We don't give access to options defined outside of any section, we
 
1142
        # used the DEFAULT section by... default.
 
1143
        if name in (None, 'DEFAULT'):
 
1144
            # This could happen for an empty file where the DEFAULT section
 
1145
            # doesn't exist yet. So we force DEFAULT when yielding
 
1146
            name = 'DEFAULT'
 
1147
            if 'DEFAULT' not in parser:
 
1148
               parser['DEFAULT']= {}
 
1149
        yield (name, parser[name], self.config_id())
 
1150
 
 
1151
    @needs_write_lock
 
1152
    def remove_user_option(self, option_name, section_name=None):
 
1153
        if section_name is None:
 
1154
            # We need to force the default section.
 
1155
            section_name = 'DEFAULT'
 
1156
        # We need to avoid the LockableConfig implementation or we'll lock
 
1157
        # twice
 
1158
        super(LockableConfig, self).remove_user_option(option_name,
 
1159
                                                       section_name)
 
1160
 
 
1161
def _iter_for_location_by_parts(sections, location):
 
1162
    """Keep only the sessions matching the specified location.
 
1163
 
 
1164
    :param sections: An iterable of section names.
 
1165
 
 
1166
    :param location: An url or a local path to match against.
 
1167
 
 
1168
    :returns: An iterator of (section, extra_path, nb_parts) where nb is the
 
1169
        number of path components in the section name, section is the section
 
1170
        name and extra_path is the difference between location and the section
 
1171
        name.
 
1172
 
 
1173
    ``location`` will always be a local path and never a 'file://' url but the
 
1174
    section names themselves can be in either form.
 
1175
    """
 
1176
    location_parts = location.rstrip('/').split('/')
 
1177
 
 
1178
    for section in sections:
 
1179
        # location is a local path if possible, so we need to convert 'file://'
 
1180
        # urls in section names to local paths if necessary.
 
1181
 
 
1182
        # This also avoids having file:///path be a more exact
 
1183
        # match than '/path'.
 
1184
 
 
1185
        # FIXME: This still raises an issue if a user defines both file:///path
 
1186
        # *and* /path. Should we raise an error in this case -- vila 20110505
 
1187
 
 
1188
        if section.startswith('file://'):
 
1189
            section_path = urlutils.local_path_from_url(section)
 
1190
        else:
 
1191
            section_path = section
 
1192
        section_parts = section_path.rstrip('/').split('/')
 
1193
 
 
1194
        matched = True
 
1195
        if len(section_parts) > len(location_parts):
 
1196
            # More path components in the section, they can't match
 
1197
            matched = False
 
1198
        else:
 
1199
            # Rely on zip truncating in length to the length of the shortest
 
1200
            # argument sequence.
 
1201
            names = zip(location_parts, section_parts)
 
1202
            for name in names:
 
1203
                if not fnmatch.fnmatch(name[0], name[1]):
 
1204
                    matched = False
 
1205
                    break
 
1206
        if not matched:
 
1207
            continue
 
1208
        # build the path difference between the section and the location
 
1209
        extra_path = '/'.join(location_parts[len(section_parts):])
 
1210
        yield section, extra_path, len(section_parts)
668
1211
 
669
1212
 
670
1213
class LocationConfig(LockableConfig):
680
1223
            location = urlutils.local_path_from_url(location)
681
1224
        self.location = location
682
1225
 
 
1226
    def config_id(self):
 
1227
        return 'locations'
 
1228
 
683
1229
    @classmethod
684
1230
    def from_string(cls, str_or_unicode, location, save=False):
685
1231
        """Create a config object from a string.
697
1243
 
698
1244
    def _get_matching_sections(self):
699
1245
        """Return an ordered list of section names matching this location."""
700
 
        sections = self._get_parser()
701
 
        location_names = self.location.split('/')
702
 
        if self.location.endswith('/'):
703
 
            del location_names[-1]
704
 
        matches=[]
705
 
        for section in sections:
706
 
            # location is a local path if possible, so we need
707
 
            # to convert 'file://' urls to local paths if necessary.
708
 
            # This also avoids having file:///path be a more exact
709
 
            # match than '/path'.
710
 
            if section.startswith('file://'):
711
 
                section_path = urlutils.local_path_from_url(section)
712
 
            else:
713
 
                section_path = section
714
 
            section_names = section_path.split('/')
715
 
            if section.endswith('/'):
716
 
                del section_names[-1]
717
 
            names = zip(location_names, section_names)
718
 
            matched = True
719
 
            for name in names:
720
 
                if not fnmatch(name[0], name[1]):
721
 
                    matched = False
722
 
                    break
723
 
            if not matched:
724
 
                continue
725
 
            # so, for the common prefix they matched.
726
 
            # if section is longer, no match.
727
 
            if len(section_names) > len(location_names):
728
 
                continue
729
 
            matches.append((len(section_names), section,
730
 
                            '/'.join(location_names[len(section_names):])))
731
 
        matches.sort(reverse=True)
732
 
        sections = []
733
 
        for (length, section, extra_path) in matches:
734
 
            sections.append((section, extra_path))
 
1246
        matches = list(_iter_for_location_by_parts(self._get_parser(),
 
1247
                                                   self.location))
 
1248
        # put the longest (aka more specific) locations first
 
1249
        matches.sort(
 
1250
            key=lambda (section, extra_path, length): (length, section),
 
1251
            reverse=True)
 
1252
        for (section, extra_path, length) in matches:
 
1253
            yield section, extra_path
735
1254
            # should we stop looking for parent configs here?
736
1255
            try:
737
1256
                if self._get_parser()[section].as_bool('ignore_parents'):
738
1257
                    break
739
1258
            except KeyError:
740
1259
                pass
741
 
        return sections
 
1260
 
 
1261
    def _get_sections(self, name=None):
 
1262
        """See IniBasedConfig._get_sections()."""
 
1263
        # We ignore the name here as the only sections handled are named with
 
1264
        # the location path and we don't expose embedded sections either.
 
1265
        parser = self._get_parser()
 
1266
        for name, extra_path in self._get_matching_sections():
 
1267
            yield (name, parser[name], self.config_id())
742
1268
 
743
1269
    def _get_option_policy(self, section, option_name):
744
1270
        """Return the policy for the given (section, option_name) pair."""
809
1335
        # the allowed values of store match the config policies
810
1336
        self._set_option_policy(location, option, store)
811
1337
        self._write_config_file()
 
1338
        for hook in OldConfigHooks['set']:
 
1339
            hook(self, option, value)
812
1340
 
813
1341
 
814
1342
class BranchConfig(Config):
824
1352
                               self._get_branch_data_config,
825
1353
                               self._get_global_config)
826
1354
 
 
1355
    def config_id(self):
 
1356
        return 'branch'
 
1357
 
827
1358
    def _get_branch_data_config(self):
828
1359
        if self._branch_data_config is None:
829
1360
            self._branch_data_config = TreeConfig(self.branch)
 
1361
            self._branch_data_config.config_id = self.config_id
830
1362
        return self._branch_data_config
831
1363
 
832
1364
    def _get_location_config(self):
872
1404
        e.g. "John Hacker <jhacker@example.com>"
873
1405
        This is looked up in the email controlfile for the branch.
874
1406
        """
875
 
        try:
876
 
            return (self.branch._transport.get_bytes("email")
877
 
                    .decode(osutils.get_user_encoding())
878
 
                    .rstrip("\r\n"))
879
 
        except errors.NoSuchFile, e:
880
 
            pass
881
 
 
882
1407
        return self._get_best_value('_get_user_id')
883
1408
 
884
1409
    def _get_change_editor(self):
900
1425
                return value
901
1426
        return None
902
1427
 
 
1428
    def _get_sections(self, name=None):
 
1429
        """See IniBasedConfig.get_sections()."""
 
1430
        for source in self.option_sources:
 
1431
            for section in source()._get_sections(name):
 
1432
                yield section
 
1433
 
 
1434
    def _get_options(self, sections=None):
 
1435
        opts = []
 
1436
        # First the locations options
 
1437
        for option in self._get_location_config()._get_options():
 
1438
            yield option
 
1439
        # Then the branch options
 
1440
        branch_config = self._get_branch_data_config()
 
1441
        if sections is None:
 
1442
            sections = [('DEFAULT', branch_config._get_parser())]
 
1443
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
 
1444
        # Config itself has no notion of sections :( -- vila 20101001
 
1445
        config_id = self.config_id()
 
1446
        for (section_name, section) in sections:
 
1447
            for (name, value) in section.iteritems():
 
1448
                yield (name, value, section_name,
 
1449
                       config_id, branch_config._get_parser())
 
1450
        # Then the global options
 
1451
        for option in self._get_global_config()._get_options():
 
1452
            yield option
 
1453
 
903
1454
    def set_user_option(self, name, value, store=STORE_BRANCH,
904
1455
        warn_masked=False):
905
1456
        if store == STORE_BRANCH:
923
1474
                        trace.warning('Value "%s" is masked by "%s" from'
924
1475
                                      ' branch.conf', value, mask_value)
925
1476
 
 
1477
    def remove_user_option(self, option_name, section_name=None):
 
1478
        self._get_branch_data_config().remove_option(option_name, section_name)
 
1479
 
926
1480
    def _gpg_signing_command(self):
927
1481
        """See Config.gpg_signing_command."""
928
1482
        return self._get_safe_value('_gpg_signing_command')
948
1502
        """See Config.log_format."""
949
1503
        return self._get_best_value('_log_format')
950
1504
 
 
1505
    def _validate_signatures_in_log(self):
 
1506
        """See Config.validate_signatures_in_log."""
 
1507
        return self._get_best_value('_validate_signatures_in_log')
 
1508
 
 
1509
    def _acceptable_keys(self):
 
1510
        """See Config.acceptable_keys."""
 
1511
        return self._get_best_value('_acceptable_keys')
 
1512
 
951
1513
 
952
1514
def ensure_config_dir_exists(path=None):
953
1515
    """Make sure a configuration directory exists.
962
1524
            parent_dir = os.path.dirname(path)
963
1525
            if not os.path.isdir(parent_dir):
964
1526
                trace.mutter('creating config parent directory: %r', parent_dir)
965
 
            os.mkdir(parent_dir)
 
1527
                os.mkdir(parent_dir)
966
1528
        trace.mutter('creating config directory: %r', path)
967
1529
        os.mkdir(path)
968
1530
        osutils.copy_ownership_from_path(path)
971
1533
def config_dir():
972
1534
    """Return per-user configuration directory.
973
1535
 
974
 
    By default this is ~/.bazaar/
 
1536
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
 
1537
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1538
    that will be used instead.
975
1539
 
976
1540
    TODO: Global option --config-dir to override this.
977
1541
    """
978
1542
    base = os.environ.get('BZR_HOME', None)
979
1543
    if sys.platform == 'win32':
 
1544
        # environ variables on Windows are in user encoding/mbcs. So decode
 
1545
        # before using one
 
1546
        if base is not None:
 
1547
            base = base.decode('mbcs')
980
1548
        if base is None:
981
1549
            base = win32utils.get_appdata_location_unicode()
982
1550
        if base is None:
983
1551
            base = os.environ.get('HOME', None)
 
1552
            if base is not None:
 
1553
                base = base.decode('mbcs')
984
1554
        if base is None:
985
1555
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
986
1556
                                  ' or HOME set')
987
1557
        return osutils.pathjoin(base, 'bazaar', '2.0')
988
1558
    else:
989
 
        if base is None:
 
1559
        if base is not None:
 
1560
            base = base.decode(osutils._fs_enc)
 
1561
    if sys.platform == 'darwin':
 
1562
        if base is None:
 
1563
            # this takes into account $HOME
 
1564
            base = os.path.expanduser("~")
 
1565
        return osutils.pathjoin(base, '.bazaar')
 
1566
    else:
 
1567
        if base is None:
 
1568
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1569
            if xdg_dir is None:
 
1570
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1571
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1572
            if osutils.isdir(xdg_dir):
 
1573
                trace.mutter(
 
1574
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1575
                return xdg_dir
990
1576
            base = os.path.expanduser("~")
991
1577
        return osutils.pathjoin(base, ".bazaar")
992
1578
 
1038
1624
        return os.path.expanduser('~/.cache')
1039
1625
 
1040
1626
 
 
1627
def _get_default_mail_domain():
 
1628
    """If possible, return the assumed default email domain.
 
1629
 
 
1630
    :returns: string mail domain, or None.
 
1631
    """
 
1632
    if sys.platform == 'win32':
 
1633
        # No implementation yet; patches welcome
 
1634
        return None
 
1635
    try:
 
1636
        f = open('/etc/mailname')
 
1637
    except (IOError, OSError), e:
 
1638
        return None
 
1639
    try:
 
1640
        domain = f.read().strip()
 
1641
        return domain
 
1642
    finally:
 
1643
        f.close()
 
1644
 
 
1645
 
 
1646
def _auto_user_id():
 
1647
    """Calculate automatic user identification.
 
1648
 
 
1649
    :returns: (realname, email), either of which may be None if they can't be
 
1650
    determined.
 
1651
 
 
1652
    Only used when none is set in the environment or the id file.
 
1653
 
 
1654
    This only returns an email address if we can be fairly sure the 
 
1655
    address is reasonable, ie if /etc/mailname is set on unix.
 
1656
 
 
1657
    This doesn't use the FQDN as the default domain because that may be 
 
1658
    slow, and it doesn't use the hostname alone because that's not normally 
 
1659
    a reasonable address.
 
1660
    """
 
1661
    if sys.platform == 'win32':
 
1662
        # No implementation to reliably determine Windows default mail
 
1663
        # address; please add one.
 
1664
        return None, None
 
1665
 
 
1666
    default_mail_domain = _get_default_mail_domain()
 
1667
    if not default_mail_domain:
 
1668
        return None, None
 
1669
 
 
1670
    import pwd
 
1671
    uid = os.getuid()
 
1672
    try:
 
1673
        w = pwd.getpwuid(uid)
 
1674
    except KeyError:
 
1675
        trace.mutter('no passwd entry for uid %d?' % uid)
 
1676
        return None, None
 
1677
 
 
1678
    # we try utf-8 first, because on many variants (like Linux),
 
1679
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
1680
    # false positives.  (many users will have their user encoding set to
 
1681
    # latin-1, which cannot raise UnicodeError.)
 
1682
    try:
 
1683
        gecos = w.pw_gecos.decode('utf-8')
 
1684
        encoding = 'utf-8'
 
1685
    except UnicodeError:
 
1686
        try:
 
1687
            encoding = osutils.get_user_encoding()
 
1688
            gecos = w.pw_gecos.decode(encoding)
 
1689
        except UnicodeError, e:
 
1690
            trace.mutter("cannot decode passwd entry %s" % w)
 
1691
            return None, None
 
1692
    try:
 
1693
        username = w.pw_name.decode(encoding)
 
1694
    except UnicodeError, e:
 
1695
        trace.mutter("cannot decode passwd entry %s" % w)
 
1696
        return None, None
 
1697
 
 
1698
    comma = gecos.find(',')
 
1699
    if comma == -1:
 
1700
        realname = gecos
 
1701
    else:
 
1702
        realname = gecos[:comma]
 
1703
 
 
1704
    return realname, (username + '@' + default_mail_domain)
 
1705
 
 
1706
 
1041
1707
def parse_username(username):
1042
1708
    """Parse e-mail username and return a (name, address) tuple."""
1043
1709
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1086
1752
 
1087
1753
    def set_option(self, value, name, section=None):
1088
1754
        """Set a per-branch configuration option"""
 
1755
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1756
        # higher levels providing the right lock -- vila 20101004
1089
1757
        self.branch.lock_write()
1090
1758
        try:
1091
1759
            self._config.set_option(value, name, section)
1092
1760
        finally:
1093
1761
            self.branch.unlock()
1094
1762
 
 
1763
    def remove_option(self, option_name, section_name=None):
 
1764
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1765
        # higher levels providing the right lock -- vila 20101004
 
1766
        self.branch.lock_write()
 
1767
        try:
 
1768
            self._config.remove_option(option_name, section_name)
 
1769
        finally:
 
1770
            self.branch.unlock()
 
1771
 
1095
1772
 
1096
1773
class AuthenticationConfig(object):
1097
1774
    """The authentication configuration file based on a ini file.
1123
1800
            self._config = ConfigObj(self._input, encoding='utf-8')
1124
1801
        except configobj.ConfigObjError, e:
1125
1802
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
1803
        except UnicodeError:
 
1804
            raise errors.ConfigContentError(self._filename)
1126
1805
        return self._config
1127
1806
 
1128
1807
    def _save(self):
1145
1824
        section[option_name] = value
1146
1825
        self._save()
1147
1826
 
1148
 
    def get_credentials(self, scheme, host, port=None, user=None, path=None, 
 
1827
    def get_credentials(self, scheme, host, port=None, user=None, path=None,
1149
1828
                        realm=None):
1150
1829
        """Returns the matching credentials from authentication.conf file.
1151
1830
 
1319
1998
            if ask:
1320
1999
                if prompt is None:
1321
2000
                    # Create a default prompt suitable for most cases
1322
 
                    prompt = scheme.upper() + ' %(host)s username'
 
2001
                    prompt = u'%s' % (scheme.upper(),) + u' %(host)s username'
1323
2002
                # Special handling for optional fields in the prompt
1324
2003
                if port is not None:
1325
2004
                    prompt_host = '%s:%d' % (host, port)
1363
2042
        if password is None:
1364
2043
            if prompt is None:
1365
2044
                # Create a default prompt suitable for most cases
1366
 
                prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
 
2045
                prompt = u'%s' % scheme.upper() + u' %(user)s@%(host)s password'
1367
2046
            # Special handling for optional fields in the prompt
1368
2047
            if port is not None:
1369
2048
                prompt_host = '%s:%d' % (host, port)
1540
2219
    """A Config that reads/writes a config file on a Transport.
1541
2220
 
1542
2221
    It is a low-level object that considers config data to be name/value pairs
1543
 
    that may be associated with a section.  Assigning meaning to the these
1544
 
    values is done at higher levels like TreeConfig.
 
2222
    that may be associated with a section.  Assigning meaning to these values
 
2223
    is done at higher levels like TreeConfig.
1545
2224
    """
1546
2225
 
1547
2226
    def __init__(self, transport, filename):
1564
2243
                section_obj = configobj[section]
1565
2244
            except KeyError:
1566
2245
                return default
1567
 
        return section_obj.get(name, default)
 
2246
        value = section_obj.get(name, default)
 
2247
        for hook in OldConfigHooks['get']:
 
2248
            hook(self, name, value)
 
2249
        return value
1568
2250
 
1569
2251
    def set_option(self, value, name, section=None):
1570
2252
        """Set the value associated with a named option.
1578
2260
            configobj[name] = value
1579
2261
        else:
1580
2262
            configobj.setdefault(section, {})[name] = value
 
2263
        for hook in OldConfigHooks['set']:
 
2264
            hook(self, name, value)
 
2265
        self._set_configobj(configobj)
 
2266
 
 
2267
    def remove_option(self, option_name, section_name=None):
 
2268
        configobj = self._get_configobj()
 
2269
        if section_name is None:
 
2270
            del configobj[option_name]
 
2271
        else:
 
2272
            del configobj[section_name][option_name]
 
2273
        for hook in OldConfigHooks['remove']:
 
2274
            hook(self, option_name)
1581
2275
        self._set_configobj(configobj)
1582
2276
 
1583
2277
    def _get_config_file(self):
1584
2278
        try:
1585
 
            return StringIO(self._transport.get_bytes(self._filename))
 
2279
            f = StringIO(self._transport.get_bytes(self._filename))
 
2280
            for hook in OldConfigHooks['load']:
 
2281
                hook(self)
 
2282
            return f
1586
2283
        except errors.NoSuchFile:
1587
2284
            return StringIO()
 
2285
        except errors.PermissionDenied, e:
 
2286
            trace.warning("Permission denied while trying to open "
 
2287
                "configuration file %s.", urlutils.unescape_for_display(
 
2288
                urlutils.join(self._transport.base, self._filename), "utf-8"))
 
2289
            return StringIO()
 
2290
 
 
2291
    def _external_url(self):
 
2292
        return urlutils.join(self._transport.external_url(), self._filename)
1588
2293
 
1589
2294
    def _get_configobj(self):
1590
2295
        f = self._get_config_file()
1591
2296
        try:
1592
 
            return ConfigObj(f, encoding='utf-8')
 
2297
            try:
 
2298
                conf = ConfigObj(f, encoding='utf-8')
 
2299
            except configobj.ConfigObjError, e:
 
2300
                raise errors.ParseConfigError(e.errors, self._external_url())
 
2301
            except UnicodeDecodeError:
 
2302
                raise errors.ConfigContentError(self._external_url())
1593
2303
        finally:
1594
2304
            f.close()
 
2305
        return conf
1595
2306
 
1596
2307
    def _set_configobj(self, configobj):
1597
2308
        out_file = StringIO()
1598
2309
        configobj.write(out_file)
1599
2310
        out_file.seek(0)
1600
2311
        self._transport.put_file(self._filename, out_file)
 
2312
        for hook in OldConfigHooks['save']:
 
2313
            hook(self)
 
2314
 
 
2315
 
 
2316
class Option(object):
 
2317
    """An option definition.
 
2318
 
 
2319
    The option *values* are stored in config files and found in sections.
 
2320
 
 
2321
    Here we define various properties about the option itself, its default
 
2322
    value, how to convert it from stores, what to do when invalid values are
 
2323
    encoutered, in which config files it can be stored.
 
2324
    """
 
2325
 
 
2326
    def __init__(self, name, default=None, default_from_env=None,
 
2327
                 help=None, 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, a callable returning a unicode string so that
 
2335
            ``from_unicode`` can be used on the return value, or a python
 
2336
            object that can be stringified (so only the empty list is supported
 
2337
            for example).
 
2338
 
 
2339
        :param default_from_env: A list of environment variables which can
 
2340
           provide a default value. 'default' will be used only if none of the
 
2341
           variables specified here are set in the environment.
 
2342
 
 
2343
        :param help: a doc string to explain the option to the user.
 
2344
 
 
2345
        :param from_unicode: a callable to convert the unicode string
 
2346
            representing the option value in a store. This is not called for
 
2347
            the default value.
 
2348
 
 
2349
        :param invalid: the action to be taken when an invalid value is
 
2350
            encountered in a store. This is called only when from_unicode is
 
2351
            invoked to convert a string and returns None or raise ValueError or
 
2352
            TypeError. Accepted values are: None (ignore invalid values),
 
2353
            'warning' (emit a warning), 'error' (emit an error message and
 
2354
            terminates).
 
2355
        """
 
2356
        if default_from_env is None:
 
2357
            default_from_env = []
 
2358
        self.name = name
 
2359
        # Convert the default value to a unicode string so all values are
 
2360
        # strings internally before conversion (via from_unicode) is attempted.
 
2361
        if default is None:
 
2362
            self.default = None
 
2363
        elif isinstance(default, list):
 
2364
            # Only the empty list is supported
 
2365
            if default:
 
2366
                raise AssertionError(
 
2367
                    'Only empty lists are supported as default values')
 
2368
            self.default = u','
 
2369
        elif isinstance(default, (str, unicode, bool, int, float)):
 
2370
            # Rely on python to convert strings, booleans and integers
 
2371
            self.default = u'%s' % (default,)
 
2372
        elif callable(default):
 
2373
            self.default = default
 
2374
        else:
 
2375
            # other python objects are not expected
 
2376
            raise AssertionError('%r is not supported as a default value'
 
2377
                                 % (default,))
 
2378
        self.default_from_env = default_from_env
 
2379
        self.help = help
 
2380
        self.from_unicode = from_unicode
 
2381
        if invalid and invalid not in ('warning', 'error'):
 
2382
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
 
2383
        self.invalid = invalid
 
2384
 
 
2385
    def convert_from_unicode(self, unicode_value):
 
2386
        if self.from_unicode is None or unicode_value is None:
 
2387
            # Don't convert or nothing to convert
 
2388
            return unicode_value
 
2389
        try:
 
2390
            converted = self.from_unicode(unicode_value)
 
2391
        except (ValueError, TypeError):
 
2392
            # Invalid values are ignored
 
2393
            converted = None
 
2394
        if converted is None and self.invalid is not None:
 
2395
            # The conversion failed
 
2396
            if self.invalid == 'warning':
 
2397
                trace.warning('Value "%s" is not valid for "%s"',
 
2398
                              unicode_value, self.name)
 
2399
            elif self.invalid == 'error':
 
2400
                raise errors.ConfigOptionValueError(self.name, unicode_value)
 
2401
        return converted
 
2402
 
 
2403
    def get_default(self):
 
2404
        value = None
 
2405
        for var in self.default_from_env:
 
2406
            try:
 
2407
                # If the env variable is defined, its value is the default one
 
2408
                value = os.environ[var].decode(osutils.get_user_encoding())
 
2409
                break
 
2410
            except KeyError:
 
2411
                continue
 
2412
        if value is None:
 
2413
            # Otherwise, fallback to the value defined at registration
 
2414
            if callable(self.default):
 
2415
                value = self.default()
 
2416
                if not isinstance(value, unicode):
 
2417
                    raise AssertionError(
 
2418
                    'Callable default values should be unicode')
 
2419
            else:
 
2420
                value = self.default
 
2421
        return value
 
2422
 
 
2423
    def get_help_text(self, additional_see_also=None, plain=True):
 
2424
        result = self.help
 
2425
        from bzrlib import help_topics
 
2426
        result += help_topics._format_see_also(additional_see_also)
 
2427
        if plain:
 
2428
            result = help_topics.help_as_plain_text(result)
 
2429
        return result
 
2430
 
 
2431
 
 
2432
# Predefined converters to get proper values from store
 
2433
 
 
2434
def bool_from_store(unicode_str):
 
2435
    return ui.bool_from_string(unicode_str)
 
2436
 
 
2437
 
 
2438
def int_from_store(unicode_str):
 
2439
    return int(unicode_str)
 
2440
 
 
2441
 
 
2442
def float_from_store(unicode_str):
 
2443
    return float(unicode_str)
 
2444
 
 
2445
 
 
2446
 
 
2447
# Use a an empty dict to initialize an empty configobj avoiding all
 
2448
# parsing and encoding checks
 
2449
_list_converter_config = configobj.ConfigObj(
 
2450
    {}, encoding='utf-8', list_values=True, interpolation=False)
 
2451
 
 
2452
 
 
2453
def list_from_store(unicode_str):
 
2454
    if not isinstance(unicode_str, basestring):
 
2455
        raise TypeError
 
2456
    # Now inject our string directly as unicode. All callers got their value
 
2457
    # from configobj, so values that need to be quoted are already properly
 
2458
    # quoted.
 
2459
    _list_converter_config.reset()
 
2460
    _list_converter_config._parse([u"list=%s" % (unicode_str,)])
 
2461
    maybe_list = _list_converter_config['list']
 
2462
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
 
2463
    if isinstance(maybe_list, basestring):
 
2464
        if maybe_list:
 
2465
            # A single value, most probably the user forgot (or didn't care to
 
2466
            # add) the final ','
 
2467
            l = [maybe_list]
 
2468
        else:
 
2469
            # The empty string, convert to empty list
 
2470
            l = []
 
2471
    else:
 
2472
        # We rely on ConfigObj providing us with a list already
 
2473
        l = maybe_list
 
2474
    return l
 
2475
 
 
2476
 
 
2477
class OptionRegistry(registry.Registry):
 
2478
    """Register config options by their name.
 
2479
 
 
2480
    This overrides ``registry.Registry`` to simplify registration by acquiring
 
2481
    some information from the option object itself.
 
2482
    """
 
2483
 
 
2484
    def register(self, option):
 
2485
        """Register a new option to its name.
 
2486
 
 
2487
        :param option: The option to register. Its name is used as the key.
 
2488
        """
 
2489
        super(OptionRegistry, self).register(option.name, option,
 
2490
                                             help=option.help)
 
2491
 
 
2492
    def register_lazy(self, key, module_name, member_name):
 
2493
        """Register a new option to be loaded on request.
 
2494
 
 
2495
        :param key: the key to request the option later. Since the registration
 
2496
            is lazy, it should be provided and match the option name.
 
2497
 
 
2498
        :param module_name: the python path to the module. Such as 'os.path'.
 
2499
 
 
2500
        :param member_name: the member of the module to return.  If empty or 
 
2501
                None, get() will return the module itself.
 
2502
        """
 
2503
        super(OptionRegistry, self).register_lazy(key,
 
2504
                                                  module_name, member_name)
 
2505
 
 
2506
    def get_help(self, key=None):
 
2507
        """Get the help text associated with the given key"""
 
2508
        option = self.get(key)
 
2509
        the_help = option.help
 
2510
        if callable(the_help):
 
2511
            return the_help(self, key)
 
2512
        return the_help
 
2513
 
 
2514
 
 
2515
option_registry = OptionRegistry()
 
2516
 
 
2517
 
 
2518
# Registered options in lexicographical order
 
2519
 
 
2520
option_registry.register(
 
2521
    Option('acceptable_keys',
 
2522
           default=None, from_unicode=list_from_store,
 
2523
           help="""\
 
2524
List of GPG key patterns which are acceptable for verification.
 
2525
"""))
 
2526
option_registry.register(
 
2527
    Option('bzr.workingtree.worth_saving_limit', default=10,
 
2528
           from_unicode=int_from_store,  invalid='warning',
 
2529
           help='''\
 
2530
How many changes before saving the dirstate.
 
2531
 
 
2532
-1 means that we will never rewrite the dirstate file for only
 
2533
stat-cache changes. Regardless of this setting, we will always rewrite
 
2534
the dirstate file if a file is added/removed/renamed/etc. This flag only
 
2535
affects the behavior of updating the dirstate file after we notice that
 
2536
a file has been touched.
 
2537
'''))
 
2538
option_registry.register(
 
2539
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
 
2540
           from_unicode=signature_policy_from_unicode,
 
2541
           help='''\
 
2542
GPG checking policy.
 
2543
 
 
2544
Possible values: require, ignore, check-available (default)
 
2545
 
 
2546
this option will control whether bzr will require good gpg
 
2547
signatures, ignore them, or check them if they are
 
2548
present.
 
2549
'''))
 
2550
option_registry.register(
 
2551
    Option('create_signatures', default=SIGN_WHEN_REQUIRED,
 
2552
           from_unicode=signing_policy_from_unicode,
 
2553
           help='''\
 
2554
GPG Signing policy.
 
2555
 
 
2556
Possible values: always, never, when-required (default)
 
2557
 
 
2558
This option controls whether bzr will always create
 
2559
gpg signatures or not on commits.
 
2560
'''))
 
2561
option_registry.register(
 
2562
    Option('dirstate.fdatasync', default=True,
 
2563
           from_unicode=bool_from_store,
 
2564
           help='''\
 
2565
Flush dirstate changes onto physical disk?
 
2566
 
 
2567
If true (default), working tree metadata changes are flushed through the
 
2568
OS buffers to physical disk.  This is somewhat slower, but means data
 
2569
should not be lost if the machine crashes.  See also repository.fdatasync.
 
2570
'''))
 
2571
option_registry.register(
 
2572
    Option('debug_flags', default=[], from_unicode=list_from_store,
 
2573
           help='Debug flags to activate.'))
 
2574
option_registry.register(
 
2575
    Option('default_format', default='2a',
 
2576
           help='Format used when creating branches.'))
 
2577
option_registry.register(
 
2578
    Option('dpush_strict', default=None,
 
2579
           from_unicode=bool_from_store,
 
2580
           help='''\
 
2581
The default value for ``dpush --strict``.
 
2582
 
 
2583
If present, defines the ``--strict`` option default value for checking
 
2584
uncommitted changes before pushing into a different VCS without any
 
2585
custom bzr metadata.
 
2586
'''))
 
2587
option_registry.register(
 
2588
    Option('editor',
 
2589
           help='The command called to launch an editor to enter a message.'))
 
2590
 
 
2591
 
 
2592
def default_email():
 
2593
    name, email = _auto_user_id()
 
2594
    if name and email:
 
2595
        return u'%s <%s>' % (name, email)
 
2596
    elif email:
 
2597
        return email
 
2598
    raise errors.NoWhoami()
 
2599
 
 
2600
 
 
2601
option_registry.register(
 
2602
    Option('email', default=default_email,
 
2603
           default_from_env=['BZR_EMAIL', 'EMAIL'],
 
2604
           help='The users identity'))
 
2605
option_registry.register(
 
2606
    Option('gpg_signing_command',
 
2607
           default='gpg',
 
2608
           help="""\
 
2609
Program to use use for creating signatures.
 
2610
 
 
2611
This should support at least the -u and --clearsign options.
 
2612
"""))
 
2613
option_registry.register(
 
2614
    Option('gpg_signing_key',
 
2615
           default=None,
 
2616
           help="""\
 
2617
GPG key to use for signing.
 
2618
 
 
2619
This defaults to the first key associated with the users email.
 
2620
"""))
 
2621
option_registry.register(
 
2622
    Option('ignore_missing_extensions', default=False,
 
2623
           from_unicode=bool_from_store,
 
2624
           help='''\
 
2625
Control the missing extensions warning display.
 
2626
 
 
2627
The warning will not be emitted if set to True.
 
2628
'''))
 
2629
option_registry.register(
 
2630
    Option('language',
 
2631
           help='Language to translate messages into.'))
 
2632
option_registry.register(
 
2633
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
 
2634
           help='''\
 
2635
Steal locks that appears to be dead.
 
2636
 
 
2637
If set to True, bzr will check if a lock is supposed to be held by an
 
2638
active process from the same user on the same machine. If the user and
 
2639
machine match, but no process with the given PID is active, then bzr
 
2640
will automatically break the stale lock, and create a new lock for
 
2641
this process.
 
2642
Otherwise, bzr will prompt as normal to break the lock.
 
2643
'''))
 
2644
option_registry.register(
 
2645
    Option('log_format', default='long',
 
2646
           help= '''\
 
2647
Log format to use when displaying revisions.
 
2648
 
 
2649
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
 
2650
may be provided by plugins.
 
2651
'''))
 
2652
option_registry.register(
 
2653
    Option('output_encoding',
 
2654
           help= 'Unicode encoding for output'
 
2655
           ' (terminal encoding if not specified).'))
 
2656
option_registry.register(
 
2657
    Option('post_commit', default=None,
 
2658
           from_unicode=list_from_store,
 
2659
           help='''\
 
2660
Post commit functions.
 
2661
 
 
2662
An ordered list of python functions to call.
 
2663
 
 
2664
Each function takes branch, rev_id as parameters.
 
2665
'''))
 
2666
option_registry.register(
 
2667
    Option('push_strict', default=None,
 
2668
           from_unicode=bool_from_store,
 
2669
           help='''\
 
2670
The default value for ``push --strict``.
 
2671
 
 
2672
If present, defines the ``--strict`` option default value for checking
 
2673
uncommitted changes before sending a merge directive.
 
2674
'''))
 
2675
option_registry.register(
 
2676
    Option('repository.fdatasync', default=True,
 
2677
           from_unicode=bool_from_store,
 
2678
           help='''\
 
2679
Flush repository changes onto physical disk?
 
2680
 
 
2681
If true (default), repository changes are flushed through the OS buffers
 
2682
to physical disk.  This is somewhat slower, but means data should not be
 
2683
lost if the machine crashes.  See also dirstate.fdatasync.
 
2684
'''))
 
2685
 
 
2686
option_registry.register(
 
2687
    Option('selftest.timeout',
 
2688
        default='600',
 
2689
        from_unicode=int_from_store,
 
2690
        help='Abort selftest if one test takes longer than this many seconds',
 
2691
        ))
 
2692
 
 
2693
option_registry.register(
 
2694
    Option('send_strict', default=None,
 
2695
           from_unicode=bool_from_store,
 
2696
           help='''\
 
2697
The default value for ``send --strict``.
 
2698
 
 
2699
If present, defines the ``--strict`` option default value for checking
 
2700
uncommitted changes before pushing.
 
2701
'''))
 
2702
 
 
2703
option_registry.register(
 
2704
    Option('serve.client_timeout',
 
2705
           default=300.0, from_unicode=float_from_store,
 
2706
           help="If we wait for a new request from a client for more than"
 
2707
                " X seconds, consider the client idle, and hangup."))
 
2708
 
 
2709
 
 
2710
class Section(object):
 
2711
    """A section defines a dict of option name => value.
 
2712
 
 
2713
    This is merely a read-only dict which can add some knowledge about the
 
2714
    options. It is *not* a python dict object though and doesn't try to mimic
 
2715
    its API.
 
2716
    """
 
2717
 
 
2718
    def __init__(self, section_id, options):
 
2719
        self.id = section_id
 
2720
        # We re-use the dict-like object received
 
2721
        self.options = options
 
2722
 
 
2723
    def get(self, name, default=None, expand=True):
 
2724
        return self.options.get(name, default)
 
2725
 
 
2726
    def iter_option_names(self):
 
2727
        for k in self.options.iterkeys():
 
2728
            yield k
 
2729
 
 
2730
    def __repr__(self):
 
2731
        # Mostly for debugging use
 
2732
        return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
 
2733
 
 
2734
 
 
2735
_NewlyCreatedOption = object()
 
2736
"""Was the option created during the MutableSection lifetime"""
 
2737
 
 
2738
 
 
2739
class MutableSection(Section):
 
2740
    """A section allowing changes and keeping track of the original values."""
 
2741
 
 
2742
    def __init__(self, section_id, options):
 
2743
        super(MutableSection, self).__init__(section_id, options)
 
2744
        self.orig = {}
 
2745
 
 
2746
    def set(self, name, value):
 
2747
        if name not in self.options:
 
2748
            # This is a new option
 
2749
            self.orig[name] = _NewlyCreatedOption
 
2750
        elif name not in self.orig:
 
2751
            self.orig[name] = self.get(name, None)
 
2752
        self.options[name] = value
 
2753
 
 
2754
    def remove(self, name):
 
2755
        if name not in self.orig:
 
2756
            self.orig[name] = self.get(name, None)
 
2757
        del self.options[name]
 
2758
 
 
2759
 
 
2760
class Store(object):
 
2761
    """Abstract interface to persistent storage for configuration options."""
 
2762
 
 
2763
    readonly_section_class = Section
 
2764
    mutable_section_class = MutableSection
 
2765
 
 
2766
    def is_loaded(self):
 
2767
        """Returns True if the Store has been loaded.
 
2768
 
 
2769
        This is used to implement lazy loading and ensure the persistent
 
2770
        storage is queried only when needed.
 
2771
        """
 
2772
        raise NotImplementedError(self.is_loaded)
 
2773
 
 
2774
    def load(self):
 
2775
        """Loads the Store from persistent storage."""
 
2776
        raise NotImplementedError(self.load)
 
2777
 
 
2778
    def _load_from_string(self, bytes):
 
2779
        """Create a store from a string in configobj syntax.
 
2780
 
 
2781
        :param bytes: A string representing the file content.
 
2782
        """
 
2783
        raise NotImplementedError(self._load_from_string)
 
2784
 
 
2785
    def unload(self):
 
2786
        """Unloads the Store.
 
2787
 
 
2788
        This should make is_loaded() return False. This is used when the caller
 
2789
        knows that the persistent storage has changed or may have change since
 
2790
        the last load.
 
2791
        """
 
2792
        raise NotImplementedError(self.unload)
 
2793
 
 
2794
    def save(self):
 
2795
        """Saves the Store to persistent storage."""
 
2796
        raise NotImplementedError(self.save)
 
2797
 
 
2798
    def external_url(self):
 
2799
        raise NotImplementedError(self.external_url)
 
2800
 
 
2801
    def get_sections(self):
 
2802
        """Returns an ordered iterable of existing sections.
 
2803
 
 
2804
        :returns: An iterable of (store, section).
 
2805
        """
 
2806
        raise NotImplementedError(self.get_sections)
 
2807
 
 
2808
    def get_mutable_section(self, section_id=None):
 
2809
        """Returns the specified mutable section.
 
2810
 
 
2811
        :param section_id: The section identifier
 
2812
        """
 
2813
        raise NotImplementedError(self.get_mutable_section)
 
2814
 
 
2815
    def __repr__(self):
 
2816
        # Mostly for debugging use
 
2817
        return "<config.%s(%s)>" % (self.__class__.__name__,
 
2818
                                    self.external_url())
 
2819
 
 
2820
 
 
2821
class CommandLineStore(Store):
 
2822
    "A store to carry command line overrides for the config options."""
 
2823
 
 
2824
    def __init__(self, opts=None):
 
2825
        super(CommandLineStore, self).__init__()
 
2826
        if opts is None:
 
2827
            opts = {}
 
2828
        self.options = {}
 
2829
 
 
2830
    def _reset(self):
 
2831
        # The dict should be cleared but not replaced so it can be shared.
 
2832
        self.options.clear()
 
2833
 
 
2834
    def _from_cmdline(self, overrides):
 
2835
        # Reset before accepting new definitions
 
2836
        self._reset()
 
2837
        for over in overrides:
 
2838
            try:
 
2839
                name, value = over.split('=', 1)
 
2840
            except ValueError:
 
2841
                raise errors.BzrCommandError(
 
2842
                    gettext("Invalid '%s', should be of the form 'name=value'")
 
2843
                    % (over,))
 
2844
            self.options[name] = value
 
2845
 
 
2846
    def external_url(self):
 
2847
        # Not an url but it makes debugging easier and is never needed
 
2848
        # otherwise
 
2849
        return 'cmdline'
 
2850
 
 
2851
    def get_sections(self):
 
2852
        yield self,  self.readonly_section_class('cmdline_overrides',
 
2853
                                                 self.options)
 
2854
 
 
2855
 
 
2856
class IniFileStore(Store):
 
2857
    """A config Store using ConfigObj for storage.
 
2858
 
 
2859
    :ivar transport: The transport object where the config file is located.
 
2860
 
 
2861
    :ivar file_name: The config file basename in the transport directory.
 
2862
 
 
2863
    :ivar _config_obj: Private member to hold the ConfigObj instance used to
 
2864
        serialize/deserialize the config file.
 
2865
    """
 
2866
 
 
2867
    def __init__(self):
 
2868
        """A config Store using ConfigObj for storage.
 
2869
        """
 
2870
        super(IniFileStore, self).__init__()
 
2871
        self._config_obj = None
 
2872
 
 
2873
    def is_loaded(self):
 
2874
        return self._config_obj != None
 
2875
 
 
2876
    def unload(self):
 
2877
        self._config_obj = None
 
2878
 
 
2879
    def _load_content(self):
 
2880
        """Load the config file bytes.
 
2881
 
 
2882
        This should be provided by subclasses
 
2883
 
 
2884
        :return: Byte string
 
2885
        """
 
2886
        raise NotImplementedError(self._load_content)
 
2887
 
 
2888
    def _save_content(self, content):
 
2889
        """Save the config file bytes.
 
2890
 
 
2891
        This should be provided by subclasses
 
2892
 
 
2893
        :param content: Config file bytes to write
 
2894
        """
 
2895
        raise NotImplementedError(self._save_content)
 
2896
 
 
2897
    def load(self):
 
2898
        """Load the store from the associated file."""
 
2899
        if self.is_loaded():
 
2900
            return
 
2901
        content = self._load_content()
 
2902
        self._load_from_string(content)
 
2903
        for hook in ConfigHooks['load']:
 
2904
            hook(self)
 
2905
 
 
2906
    def _load_from_string(self, bytes):
 
2907
        """Create a config store from a string.
 
2908
 
 
2909
        :param bytes: A string representing the file content.
 
2910
        """
 
2911
        if self.is_loaded():
 
2912
            raise AssertionError('Already loaded: %r' % (self._config_obj,))
 
2913
        co_input = StringIO(bytes)
 
2914
        try:
 
2915
            # The config files are always stored utf8-encoded
 
2916
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
 
2917
                                         list_values=False)
 
2918
        except configobj.ConfigObjError, e:
 
2919
            self._config_obj = None
 
2920
            raise errors.ParseConfigError(e.errors, self.external_url())
 
2921
        except UnicodeDecodeError:
 
2922
            raise errors.ConfigContentError(self.external_url())
 
2923
 
 
2924
    def save(self):
 
2925
        if not self.is_loaded():
 
2926
            # Nothing to save
 
2927
            return
 
2928
        out = StringIO()
 
2929
        self._config_obj.write(out)
 
2930
        self._save_content(out.getvalue())
 
2931
        for hook in ConfigHooks['save']:
 
2932
            hook(self)
 
2933
 
 
2934
    def get_sections(self):
 
2935
        """Get the configobj section in the file order.
 
2936
 
 
2937
        :returns: An iterable of (store, section).
 
2938
        """
 
2939
        # We need a loaded store
 
2940
        try:
 
2941
            self.load()
 
2942
        except (errors.NoSuchFile, errors.PermissionDenied):
 
2943
            # If the file can't be read, there is no sections
 
2944
            return
 
2945
        cobj = self._config_obj
 
2946
        if cobj.scalars:
 
2947
            yield self, self.readonly_section_class(None, cobj)
 
2948
        for section_name in cobj.sections:
 
2949
            yield (self,
 
2950
                   self.readonly_section_class(section_name,
 
2951
                                               cobj[section_name]))
 
2952
 
 
2953
    def get_mutable_section(self, section_id=None):
 
2954
        # We need a loaded store
 
2955
        try:
 
2956
            self.load()
 
2957
        except errors.NoSuchFile:
 
2958
            # The file doesn't exist, let's pretend it was empty
 
2959
            self._load_from_string('')
 
2960
        if section_id is None:
 
2961
            section = self._config_obj
 
2962
        else:
 
2963
            section = self._config_obj.setdefault(section_id, {})
 
2964
        return self.mutable_section_class(section_id, section)
 
2965
 
 
2966
 
 
2967
class TransportIniFileStore(IniFileStore):
 
2968
    """IniFileStore that loads files from a transport.
 
2969
    """
 
2970
 
 
2971
    def __init__(self, transport, file_name):
 
2972
        """A Store using a ini file on a Transport
 
2973
 
 
2974
        :param transport: The transport object where the config file is located.
 
2975
        :param file_name: The config file basename in the transport directory.
 
2976
        """
 
2977
        super(TransportIniFileStore, self).__init__()
 
2978
        self.transport = transport
 
2979
        self.file_name = file_name
 
2980
 
 
2981
    def _load_content(self):
 
2982
        try:
 
2983
            return self.transport.get_bytes(self.file_name)
 
2984
        except errors.PermissionDenied:
 
2985
            trace.warning("Permission denied while trying to load "
 
2986
                          "configuration store %s.", self.external_url())
 
2987
            raise
 
2988
 
 
2989
    def _save_content(self, content):
 
2990
        self.transport.put_bytes(self.file_name, content)
 
2991
 
 
2992
    def external_url(self):
 
2993
        # FIXME: external_url should really accepts an optional relpath
 
2994
        # parameter (bug #750169) :-/ -- vila 2011-04-04
 
2995
        # The following will do in the interim but maybe we don't want to
 
2996
        # expose a path here but rather a config ID and its associated
 
2997
        # object </hand wawe>.
 
2998
        return urlutils.join(self.transport.external_url(), self.file_name)
 
2999
 
 
3000
 
 
3001
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
 
3002
# unlockable stores for use with objects that can already ensure the locking
 
3003
# (think branches). If different stores (not based on ConfigObj) are created,
 
3004
# they may face the same issue.
 
3005
 
 
3006
 
 
3007
class LockableIniFileStore(TransportIniFileStore):
 
3008
    """A ConfigObjStore using locks on save to ensure store integrity."""
 
3009
 
 
3010
    def __init__(self, transport, file_name, lock_dir_name=None):
 
3011
        """A config Store using ConfigObj for storage.
 
3012
 
 
3013
        :param transport: The transport object where the config file is located.
 
3014
 
 
3015
        :param file_name: The config file basename in the transport directory.
 
3016
        """
 
3017
        if lock_dir_name is None:
 
3018
            lock_dir_name = 'lock'
 
3019
        self.lock_dir_name = lock_dir_name
 
3020
        super(LockableIniFileStore, self).__init__(transport, file_name)
 
3021
        self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
 
3022
 
 
3023
    def lock_write(self, token=None):
 
3024
        """Takes a write lock in the directory containing the config file.
 
3025
 
 
3026
        If the directory doesn't exist it is created.
 
3027
        """
 
3028
        # FIXME: This doesn't check the ownership of the created directories as
 
3029
        # ensure_config_dir_exists does. It should if the transport is local
 
3030
        # -- vila 2011-04-06
 
3031
        self.transport.create_prefix()
 
3032
        return self._lock.lock_write(token)
 
3033
 
 
3034
    def unlock(self):
 
3035
        self._lock.unlock()
 
3036
 
 
3037
    def break_lock(self):
 
3038
        self._lock.break_lock()
 
3039
 
 
3040
    @needs_write_lock
 
3041
    def save(self):
 
3042
        # We need to be able to override the undecorated implementation
 
3043
        self.save_without_locking()
 
3044
 
 
3045
    def save_without_locking(self):
 
3046
        super(LockableIniFileStore, self).save()
 
3047
 
 
3048
 
 
3049
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
 
3050
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
 
3051
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
 
3052
 
 
3053
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
 
3054
# functions or a registry will make it easier and clearer for tests, focusing
 
3055
# on the relevant parts of the API that needs testing -- vila 20110503 (based
 
3056
# on a poolie's remark)
 
3057
class GlobalStore(LockableIniFileStore):
 
3058
 
 
3059
    def __init__(self, possible_transports=None):
 
3060
        t = transport.get_transport_from_path(
 
3061
            config_dir(), possible_transports=possible_transports)
 
3062
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
 
3063
        self.id = 'bazaar'
 
3064
 
 
3065
 
 
3066
class LocationStore(LockableIniFileStore):
 
3067
 
 
3068
    def __init__(self, possible_transports=None):
 
3069
        t = transport.get_transport_from_path(
 
3070
            config_dir(), possible_transports=possible_transports)
 
3071
        super(LocationStore, self).__init__(t, 'locations.conf')
 
3072
        self.id = 'locations'
 
3073
 
 
3074
 
 
3075
class BranchStore(TransportIniFileStore):
 
3076
 
 
3077
    def __init__(self, branch):
 
3078
        super(BranchStore, self).__init__(branch.control_transport,
 
3079
                                          'branch.conf')
 
3080
        self.branch = branch
 
3081
        self.id = 'branch'
 
3082
 
 
3083
    def lock_write(self, token=None):
 
3084
        return self.branch.lock_write(token)
 
3085
 
 
3086
    def unlock(self):
 
3087
        return self.branch.unlock()
 
3088
 
 
3089
    @needs_write_lock
 
3090
    def save(self):
 
3091
        # We need to be able to override the undecorated implementation
 
3092
        self.save_without_locking()
 
3093
 
 
3094
    def save_without_locking(self):
 
3095
        super(BranchStore, self).save()
 
3096
 
 
3097
 
 
3098
class ControlStore(LockableIniFileStore):
 
3099
 
 
3100
    def __init__(self, bzrdir):
 
3101
        super(ControlStore, self).__init__(bzrdir.transport,
 
3102
                                          'control.conf',
 
3103
                                           lock_dir_name='branch_lock')
 
3104
 
 
3105
 
 
3106
class SectionMatcher(object):
 
3107
    """Select sections into a given Store.
 
3108
 
 
3109
    This is intended to be used to postpone getting an iterable of sections
 
3110
    from a store.
 
3111
    """
 
3112
 
 
3113
    def __init__(self, store):
 
3114
        self.store = store
 
3115
 
 
3116
    def get_sections(self):
 
3117
        # This is where we require loading the store so we can see all defined
 
3118
        # sections.
 
3119
        sections = self.store.get_sections()
 
3120
        # Walk the revisions in the order provided
 
3121
        for store, s in sections:
 
3122
            if self.match(s):
 
3123
                yield store, s
 
3124
 
 
3125
    def match(self, section):
 
3126
        """Does the proposed section match.
 
3127
 
 
3128
        :param section: A Section object.
 
3129
 
 
3130
        :returns: True if the section matches, False otherwise.
 
3131
        """
 
3132
        raise NotImplementedError(self.match)
 
3133
 
 
3134
 
 
3135
class NameMatcher(SectionMatcher):
 
3136
 
 
3137
    def __init__(self, store, section_id):
 
3138
        super(NameMatcher, self).__init__(store)
 
3139
        self.section_id = section_id
 
3140
 
 
3141
    def match(self, section):
 
3142
        return section.id == self.section_id
 
3143
 
 
3144
 
 
3145
class LocationSection(Section):
 
3146
 
 
3147
    def __init__(self, section, length, extra_path):
 
3148
        super(LocationSection, self).__init__(section.id, section.options)
 
3149
        self.length = length
 
3150
        self.extra_path = extra_path
 
3151
        self.locals = {'relpath': extra_path,
 
3152
                       'basename': urlutils.basename(extra_path)}
 
3153
 
 
3154
    def get(self, name, default=None, expand=True):
 
3155
        value = super(LocationSection, self).get(name, default)
 
3156
        if value is not None and expand:
 
3157
            policy_name = self.get(name + ':policy', None)
 
3158
            policy = _policy_value.get(policy_name, POLICY_NONE)
 
3159
            if policy == POLICY_APPENDPATH:
 
3160
                value = urlutils.join(value, self.extra_path)
 
3161
            # expand section local options right now (since POLICY_APPENDPATH
 
3162
            # will never add options references, it's ok to expand after it).
 
3163
            chunks = []
 
3164
            for is_ref, chunk in iter_option_refs(value):
 
3165
                if not is_ref:
 
3166
                    chunks.append(chunk)
 
3167
                else:
 
3168
                    ref = chunk[1:-1]
 
3169
                    if ref in self.locals:
 
3170
                        chunks.append(self.locals[ref])
 
3171
                    else:
 
3172
                        chunks.append(chunk)
 
3173
            value = ''.join(chunks)
 
3174
        return value
 
3175
 
 
3176
 
 
3177
class LocationMatcher(SectionMatcher):
 
3178
 
 
3179
    def __init__(self, store, location):
 
3180
        super(LocationMatcher, self).__init__(store)
 
3181
        if location.startswith('file://'):
 
3182
            location = urlutils.local_path_from_url(location)
 
3183
        self.location = location
 
3184
 
 
3185
    def _get_matching_sections(self):
 
3186
        """Get all sections matching ``location``."""
 
3187
        # We slightly diverge from LocalConfig here by allowing the no-name
 
3188
        # section as the most generic one and the lower priority.
 
3189
        no_name_section = None
 
3190
        all_sections = []
 
3191
        # Filter out the no_name_section so _iter_for_location_by_parts can be
 
3192
        # used (it assumes all sections have a name).
 
3193
        for _, section in self.store.get_sections():
 
3194
            if section.id is None:
 
3195
                no_name_section = section
 
3196
            else:
 
3197
                all_sections.append(section)
 
3198
        # Unfortunately _iter_for_location_by_parts deals with section names so
 
3199
        # we have to resync.
 
3200
        filtered_sections = _iter_for_location_by_parts(
 
3201
            [s.id for s in all_sections], self.location)
 
3202
        iter_all_sections = iter(all_sections)
 
3203
        matching_sections = []
 
3204
        if no_name_section is not None:
 
3205
            matching_sections.append(
 
3206
                LocationSection(no_name_section, 0, self.location))
 
3207
        for section_id, extra_path, length in filtered_sections:
 
3208
            # a section id is unique for a given store so it's safe to take the
 
3209
            # first matching section while iterating. Also, all filtered
 
3210
            # sections are part of 'all_sections' and will always be found
 
3211
            # there.
 
3212
            while True:
 
3213
                section = iter_all_sections.next()
 
3214
                if section_id == section.id:
 
3215
                    matching_sections.append(
 
3216
                        LocationSection(section, length, extra_path))
 
3217
                    break
 
3218
        return matching_sections
 
3219
 
 
3220
    def get_sections(self):
 
3221
        # Override the default implementation as we want to change the order
 
3222
        matching_sections = self._get_matching_sections()
 
3223
        # We want the longest (aka more specific) locations first
 
3224
        sections = sorted(matching_sections,
 
3225
                          key=lambda section: (section.length, section.id),
 
3226
                          reverse=True)
 
3227
        # Sections mentioning 'ignore_parents' restrict the selection
 
3228
        for section in sections:
 
3229
            # FIXME: We really want to use as_bool below -- vila 2011-04-07
 
3230
            ignore = section.get('ignore_parents', None)
 
3231
            if ignore is not None:
 
3232
                ignore = ui.bool_from_string(ignore)
 
3233
            if ignore:
 
3234
                break
 
3235
            # Finally, we have a valid section
 
3236
            yield self.store, section
 
3237
 
 
3238
 
 
3239
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
 
3240
"""Describes an expandable option reference.
 
3241
 
 
3242
We want to match the most embedded reference first.
 
3243
 
 
3244
I.e. for '{{foo}}' we will get '{foo}',
 
3245
for '{bar{baz}}' we will get '{baz}'
 
3246
"""
 
3247
 
 
3248
def iter_option_refs(string):
 
3249
    # Split isolate refs so every other chunk is a ref
 
3250
    is_ref = False
 
3251
    for chunk  in _option_ref_re.split(string):
 
3252
        yield is_ref, chunk
 
3253
        is_ref = not is_ref
 
3254
 
 
3255
 
 
3256
class Stack(object):
 
3257
    """A stack of configurations where an option can be defined"""
 
3258
 
 
3259
    def __init__(self, sections_def, store=None, mutable_section_id=None):
 
3260
        """Creates a stack of sections with an optional store for changes.
 
3261
 
 
3262
        :param sections_def: A list of Section or callables that returns an
 
3263
            iterable of Section. This defines the Sections for the Stack and
 
3264
            can be called repeatedly if needed.
 
3265
 
 
3266
        :param store: The optional Store where modifications will be
 
3267
            recorded. If none is specified, no modifications can be done.
 
3268
 
 
3269
        :param mutable_section_id: The id of the MutableSection where changes
 
3270
            are recorded. This requires the ``store`` parameter to be
 
3271
            specified.
 
3272
        """
 
3273
        self.sections_def = sections_def
 
3274
        self.store = store
 
3275
        self.mutable_section_id = mutable_section_id
 
3276
 
 
3277
    def get(self, name, expand=None):
 
3278
        """Return the *first* option value found in the sections.
 
3279
 
 
3280
        This is where we guarantee that sections coming from Store are loaded
 
3281
        lazily: the loading is delayed until we need to either check that an
 
3282
        option exists or get its value, which in turn may require to discover
 
3283
        in which sections it can be defined. Both of these (section and option
 
3284
        existence) require loading the store (even partially).
 
3285
 
 
3286
        :param name: The queried option.
 
3287
 
 
3288
        :param expand: Whether options references should be expanded.
 
3289
 
 
3290
        :returns: The value of the option.
 
3291
        """
 
3292
        # FIXME: No caching of options nor sections yet -- vila 20110503
 
3293
        if expand is None:
 
3294
            expand = _get_expand_default_value()
 
3295
        value = None
 
3296
        # Ensuring lazy loading is achieved by delaying section matching (which
 
3297
        # implies querying the persistent storage) until it can't be avoided
 
3298
        # anymore by using callables to describe (possibly empty) section
 
3299
        # lists.
 
3300
        for sections in self.sections_def:
 
3301
            for store, section in sections():
 
3302
                value = section.get(name)
 
3303
                if value is not None:
 
3304
                    break
 
3305
            if value is not None:
 
3306
                break
 
3307
        # If the option is registered, it may provide additional info about
 
3308
        # value handling
 
3309
        try:
 
3310
            opt = option_registry.get(name)
 
3311
        except KeyError:
 
3312
            # Not registered
 
3313
            opt = None
 
3314
        def expand_and_convert(val):
 
3315
            # This may need to be called twice if the value is None or ends up
 
3316
            # being None during expansion or conversion.
 
3317
            if val is not None:
 
3318
                if expand:
 
3319
                    if isinstance(val, basestring):
 
3320
                        val = self._expand_options_in_string(val)
 
3321
                    else:
 
3322
                        trace.warning('Cannot expand "%s":'
 
3323
                                      ' %s does not support option expansion'
 
3324
                                      % (name, type(val)))
 
3325
                if opt is not None:
 
3326
                    val = opt.convert_from_unicode(val)
 
3327
            return val
 
3328
        value = expand_and_convert(value)
 
3329
        if opt is not None and value is None:
 
3330
            # If the option is registered, it may provide a default value
 
3331
            value = opt.get_default()
 
3332
            value = expand_and_convert(value)
 
3333
        for hook in ConfigHooks['get']:
 
3334
            hook(self, name, value)
 
3335
        return value
 
3336
 
 
3337
    def expand_options(self, string, env=None):
 
3338
        """Expand option references in the string in the configuration context.
 
3339
 
 
3340
        :param string: The string containing option(s) to expand.
 
3341
 
 
3342
        :param env: An option dict defining additional configuration options or
 
3343
            overriding existing ones.
 
3344
 
 
3345
        :returns: The expanded string.
 
3346
        """
 
3347
        return self._expand_options_in_string(string, env)
 
3348
 
 
3349
    def _expand_options_in_string(self, string, env=None, _refs=None):
 
3350
        """Expand options in the string in the configuration context.
 
3351
 
 
3352
        :param string: The string to be expanded.
 
3353
 
 
3354
        :param env: An option dict defining additional configuration options or
 
3355
            overriding existing ones.
 
3356
 
 
3357
        :param _refs: Private list (FIFO) containing the options being expanded
 
3358
            to detect loops.
 
3359
 
 
3360
        :returns: The expanded string.
 
3361
        """
 
3362
        if string is None:
 
3363
            # Not much to expand there
 
3364
            return None
 
3365
        if _refs is None:
 
3366
            # What references are currently resolved (to detect loops)
 
3367
            _refs = []
 
3368
        result = string
 
3369
        # We need to iterate until no more refs appear ({{foo}} will need two
 
3370
        # iterations for example).
 
3371
        expanded = True
 
3372
        while expanded:
 
3373
            expanded = False
 
3374
            chunks = []
 
3375
            for is_ref, chunk in iter_option_refs(result):
 
3376
                if not is_ref:
 
3377
                    chunks.append(chunk)
 
3378
                else:
 
3379
                    expanded = True
 
3380
                    name = chunk[1:-1]
 
3381
                    if name in _refs:
 
3382
                        raise errors.OptionExpansionLoop(string, _refs)
 
3383
                    _refs.append(name)
 
3384
                    value = self._expand_option(name, env, _refs)
 
3385
                    if value is None:
 
3386
                        raise errors.ExpandingUnknownOption(name, string)
 
3387
                    chunks.append(value)
 
3388
                    _refs.pop()
 
3389
            result = ''.join(chunks)
 
3390
        return result
 
3391
 
 
3392
    def _expand_option(self, name, env, _refs):
 
3393
        if env is not None and name in env:
 
3394
            # Special case, values provided in env takes precedence over
 
3395
            # anything else
 
3396
            value = env[name]
 
3397
        else:
 
3398
            value = self.get(name, expand=False)
 
3399
            value = self._expand_options_in_string(value, env, _refs)
 
3400
        return value
 
3401
 
 
3402
    def _get_mutable_section(self):
 
3403
        """Get the MutableSection for the Stack.
 
3404
 
 
3405
        This is where we guarantee that the mutable section is lazily loaded:
 
3406
        this means we won't load the corresponding store before setting a value
 
3407
        or deleting an option. In practice the store will often be loaded but
 
3408
        this helps catching some programming errors.
 
3409
        """
 
3410
        section = self.store.get_mutable_section(self.mutable_section_id)
 
3411
        return section
 
3412
 
 
3413
    def set(self, name, value):
 
3414
        """Set a new value for the option."""
 
3415
        section = self._get_mutable_section()
 
3416
        section.set(name, value)
 
3417
        for hook in ConfigHooks['set']:
 
3418
            hook(self, name, value)
 
3419
 
 
3420
    def remove(self, name):
 
3421
        """Remove an existing option."""
 
3422
        section = self._get_mutable_section()
 
3423
        section.remove(name)
 
3424
        for hook in ConfigHooks['remove']:
 
3425
            hook(self, name)
 
3426
 
 
3427
    def __repr__(self):
 
3428
        # Mostly for debugging use
 
3429
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
 
3430
 
 
3431
    def _get_overrides(self):
 
3432
        # Hack around library_state.initialize never called
 
3433
        if bzrlib.global_state is not None:
 
3434
            return bzrlib.global_state.cmdline_overrides.get_sections()
 
3435
        return []
 
3436
 
 
3437
 
 
3438
class _CompatibleStack(Stack):
 
3439
    """Place holder for compatibility with previous design.
 
3440
 
 
3441
    This is intended to ease the transition from the Config-based design to the
 
3442
    Stack-based design and should not be used nor relied upon by plugins.
 
3443
 
 
3444
    One assumption made here is that the daughter classes will all use Stores
 
3445
    derived from LockableIniFileStore).
 
3446
 
 
3447
    It implements set() and remove () by re-loading the store before applying
 
3448
    the modification and saving it.
 
3449
 
 
3450
    The long term plan being to implement a single write by store to save
 
3451
    all modifications, this class should not be used in the interim.
 
3452
    """
 
3453
 
 
3454
    def set(self, name, value):
 
3455
        # Force a reload
 
3456
        self.store.unload()
 
3457
        super(_CompatibleStack, self).set(name, value)
 
3458
        # Force a write to persistent storage
 
3459
        self.store.save()
 
3460
 
 
3461
    def remove(self, name):
 
3462
        # Force a reload
 
3463
        self.store.unload()
 
3464
        super(_CompatibleStack, self).remove(name)
 
3465
        # Force a write to persistent storage
 
3466
        self.store.save()
 
3467
 
 
3468
 
 
3469
class GlobalStack(_CompatibleStack):
 
3470
    """Global options only stack."""
 
3471
 
 
3472
    def __init__(self):
 
3473
        # Get a GlobalStore
 
3474
        gstore = GlobalStore()
 
3475
        super(GlobalStack, self).__init__(
 
3476
            [self._get_overrides, NameMatcher(gstore, 'DEFAULT').get_sections],
 
3477
            gstore, mutable_section_id='DEFAULT')
 
3478
 
 
3479
 
 
3480
class LocationStack(_CompatibleStack):
 
3481
    """Per-location options falling back to global options stack."""
 
3482
 
 
3483
    def __init__(self, location):
 
3484
        """Make a new stack for a location and global configuration.
 
3485
        
 
3486
        :param location: A URL prefix to """
 
3487
        lstore = LocationStore()
 
3488
        if location.startswith('file://'):
 
3489
            location = urlutils.local_path_from_url(location)
 
3490
        matcher = LocationMatcher(lstore, location)
 
3491
        gstore = GlobalStore()
 
3492
        super(LocationStack, self).__init__(
 
3493
            [self._get_overrides,
 
3494
             matcher.get_sections, NameMatcher(gstore, 'DEFAULT').get_sections],
 
3495
            lstore, mutable_section_id=location)
 
3496
 
 
3497
 
 
3498
class BranchStack(_CompatibleStack):
 
3499
    """Per-location options falling back to branch then global options stack."""
 
3500
 
 
3501
    def __init__(self, branch):
 
3502
        bstore = branch._get_config_store()
 
3503
        lstore = LocationStore()
 
3504
        matcher = LocationMatcher(lstore, branch.base)
 
3505
        gstore = GlobalStore()
 
3506
        super(BranchStack, self).__init__(
 
3507
            [self._get_overrides,
 
3508
             matcher.get_sections, bstore.get_sections,
 
3509
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
3510
            bstore)
 
3511
        self.branch = branch
 
3512
 
 
3513
 
 
3514
class RemoteControlStack(_CompatibleStack):
 
3515
    """Remote control-only options stack."""
 
3516
 
 
3517
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
 
3518
    # with the stack used for remote bzr dirs. RemoteControlStack only uses
 
3519
    # control.conf and is used only for stack options.
 
3520
 
 
3521
    def __init__(self, bzrdir):
 
3522
        cstore = bzrdir._get_config_store()
 
3523
        super(RemoteControlStack, self).__init__(
 
3524
            [cstore.get_sections],
 
3525
            cstore)
 
3526
        self.bzrdir = bzrdir
 
3527
 
 
3528
 
 
3529
class RemoteBranchStack(_CompatibleStack):
 
3530
    """Remote branch-only options stack."""
 
3531
 
 
3532
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
 
3533
    # with the stack used for remote branches. RemoteBranchStack only uses
 
3534
    # branch.conf and is used only for the stack options.
 
3535
 
 
3536
    def __init__(self, branch):
 
3537
        bstore = branch._get_config_store()
 
3538
        super(RemoteBranchStack, self).__init__(
 
3539
            [bstore.get_sections],
 
3540
            bstore)
 
3541
        self.branch = branch
 
3542
 
 
3543
# Use a an empty dict to initialize an empty configobj avoiding all
 
3544
# parsing and encoding checks
 
3545
_quoting_config = configobj.ConfigObj(
 
3546
    {}, encoding='utf-8', interpolation=False)
 
3547
 
 
3548
class cmd_config(commands.Command):
 
3549
    __doc__ = """Display, set or remove a configuration option.
 
3550
 
 
3551
    Display the active value for a given option.
 
3552
 
 
3553
    If --all is specified, NAME is interpreted as a regular expression and all
 
3554
    matching options are displayed mentioning their scope. The active value
 
3555
    that bzr will take into account is the first one displayed for each option.
 
3556
 
 
3557
    If no NAME is given, --all .* is implied.
 
3558
 
 
3559
    Setting a value is achieved by using name=value without spaces. The value
 
3560
    is set in the most relevant scope and can be checked by displaying the
 
3561
    option again.
 
3562
    """
 
3563
 
 
3564
    takes_args = ['name?']
 
3565
 
 
3566
    takes_options = [
 
3567
        'directory',
 
3568
        # FIXME: This should be a registry option so that plugins can register
 
3569
        # their own config files (or not) and will also address
 
3570
        # http://pad.lv/788991 -- vila 20101115
 
3571
        commands.Option('scope', help='Reduce the scope to the specified'
 
3572
                        ' configuration file.',
 
3573
                        type=unicode),
 
3574
        commands.Option('all',
 
3575
            help='Display all the defined values for the matching options.',
 
3576
            ),
 
3577
        commands.Option('remove', help='Remove the option from'
 
3578
                        ' the configuration file.'),
 
3579
        ]
 
3580
 
 
3581
    _see_also = ['configuration']
 
3582
 
 
3583
    @commands.display_command
 
3584
    def run(self, name=None, all=False, directory=None, scope=None,
 
3585
            remove=False):
 
3586
        if directory is None:
 
3587
            directory = '.'
 
3588
        directory = urlutils.normalize_url(directory)
 
3589
        if remove and all:
 
3590
            raise errors.BzrError(
 
3591
                '--all and --remove are mutually exclusive.')
 
3592
        elif remove:
 
3593
            # Delete the option in the given scope
 
3594
            self._remove_config_option(name, directory, scope)
 
3595
        elif name is None:
 
3596
            # Defaults to all options
 
3597
            self._show_matching_options('.*', directory, scope)
 
3598
        else:
 
3599
            try:
 
3600
                name, value = name.split('=', 1)
 
3601
            except ValueError:
 
3602
                # Display the option(s) value(s)
 
3603
                if all:
 
3604
                    self._show_matching_options(name, directory, scope)
 
3605
                else:
 
3606
                    self._show_value(name, directory, scope)
 
3607
            else:
 
3608
                if all:
 
3609
                    raise errors.BzrError(
 
3610
                        'Only one option can be set.')
 
3611
                # Set the option value
 
3612
                self._set_config_option(name, value, directory, scope)
 
3613
 
 
3614
    def _get_stack(self, directory, scope=None):
 
3615
        """Get the configuration stack specified by ``directory`` and ``scope``.
 
3616
 
 
3617
        :param directory: Where the configurations are derived from.
 
3618
 
 
3619
        :param scope: A specific config to start from.
 
3620
        """
 
3621
        # FIXME: scope should allow access to plugin-specific stacks (even
 
3622
        # reduced to the plugin-specific store), related to
 
3623
        # http://pad.lv/788991 -- vila 2011-11-15
 
3624
        if scope is not None:
 
3625
            if scope == 'bazaar':
 
3626
                return GlobalStack()
 
3627
            elif scope == 'locations':
 
3628
                return LocationStack(directory)
 
3629
            elif scope == 'branch':
 
3630
                (_, br, _) = (
 
3631
                    controldir.ControlDir.open_containing_tree_or_branch(
 
3632
                        directory))
 
3633
                return br.get_config_stack()
 
3634
            raise errors.NoSuchConfig(scope)
 
3635
        else:
 
3636
            try:
 
3637
                (_, br, _) = (
 
3638
                    controldir.ControlDir.open_containing_tree_or_branch(
 
3639
                        directory))
 
3640
                return br.get_config_stack()
 
3641
            except errors.NotBranchError:
 
3642
                return LocationStack(directory)
 
3643
 
 
3644
    def _show_value(self, name, directory, scope):
 
3645
        conf = self._get_stack(directory, scope)
 
3646
        value = conf.get(name, expand=True)
 
3647
        if value is not None:
 
3648
            # Quote the value appropriately
 
3649
            value = _quoting_config._quote(value)
 
3650
            self.outf.write('%s\n' % (value,))
 
3651
        else:
 
3652
            raise errors.NoSuchConfigOption(name)
 
3653
 
 
3654
    def _show_matching_options(self, name, directory, scope):
 
3655
        name = lazy_regex.lazy_compile(name)
 
3656
        # We want any error in the regexp to be raised *now* so we need to
 
3657
        # avoid the delay introduced by the lazy regexp.  But, we still do
 
3658
        # want the nicer errors raised by lazy_regex.
 
3659
        name._compile_and_collapse()
 
3660
        cur_store_id = None
 
3661
        cur_section = None
 
3662
        conf = self._get_stack(directory, scope)
 
3663
        for sections in conf.sections_def:
 
3664
            for store, section in sections():
 
3665
                for oname in section.iter_option_names():
 
3666
                    if name.search(oname):
 
3667
                        if cur_store_id != store.id:
 
3668
                            # Explain where the options are defined
 
3669
                            self.outf.write('%s:\n' % (store.id,))
 
3670
                            cur_store_id = store.id
 
3671
                            cur_section = None
 
3672
                        if (section.id not in (None, 'DEFAULT')
 
3673
                            and cur_section != section.id):
 
3674
                            # Display the section if it's not the default (or
 
3675
                            # only) one.
 
3676
                            self.outf.write('  [%s]\n' % (section.id,))
 
3677
                            cur_section = section.id
 
3678
                        value = section.get(oname, expand=False)
 
3679
                        value = _quoting_config._quote(value)
 
3680
                        self.outf.write('  %s = %s\n' % (oname, value))
 
3681
 
 
3682
    def _set_config_option(self, name, value, directory, scope):
 
3683
        conf = self._get_stack(directory, scope)
 
3684
        conf.set(name, value)
 
3685
 
 
3686
    def _remove_config_option(self, name, directory, scope):
 
3687
        if name is None:
 
3688
            raise errors.BzrCommandError(
 
3689
                '--remove expects an option to remove.')
 
3690
        conf = self._get_stack(directory, scope)
 
3691
        try:
 
3692
            conf.remove(name)
 
3693
        except KeyError:
 
3694
            raise errors.NoSuchConfigOption(name)
 
3695
 
 
3696
 
 
3697
# Test registries
 
3698
#
 
3699
# We need adapters that can build a Store or a Stack in a test context. Test
 
3700
# classes, based on TestCaseWithTransport, can use the registry to parametrize
 
3701
# themselves. The builder will receive a test instance and should return a
 
3702
# ready-to-use store or stack.  Plugins that define new store/stacks can also
 
3703
# register themselves here to be tested against the tests defined in
 
3704
# bzrlib.tests.test_config. Note that the builder can be called multiple times
 
3705
# for the same test.
 
3706
 
 
3707
# The registered object should be a callable receiving a test instance
 
3708
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
 
3709
# object.
 
3710
test_store_builder_registry = registry.Registry()
 
3711
 
 
3712
# The registered object should be a callable receiving a test instance
 
3713
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
 
3714
# object.
 
3715
test_stack_builder_registry = registry.Registry()