~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

Add bzrlib.tests.per_repository_vf.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005-2011 Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#            and others
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 
 
19
"""Configuration that affects the behaviour of Bazaar.
 
20
 
 
21
Currently this configuration resides in ~/.bazaar/bazaar.conf
 
22
and ~/.bazaar/locations.conf, which is written to by bzr.
 
23
 
 
24
In bazaar.conf the following options may be set:
 
25
[DEFAULT]
 
26
editor=name-of-program
 
27
email=Your Name <your@email.address>
 
28
check_signatures=require|ignore|check-available(default)
 
29
create_signatures=always|never|when-required(default)
 
30
gpg_signing_command=name-of-program
 
31
log_format=name-of-format
 
32
 
 
33
in locations.conf, you specify the url of a branch and options for it.
 
34
Wildcards may be used - * and ? as normal in shell completion. Options
 
35
set in both bazaar.conf and locations.conf are overridden by the locations.conf
 
36
setting.
 
37
[/home/robertc/source]
 
38
recurse=False|True(default)
 
39
email= as above
 
40
check_signatures= as above
 
41
create_signatures= as above.
 
42
 
 
43
explanation of options
 
44
----------------------
 
45
editor - this option sets the pop up editor to use during commits.
 
46
email - this option sets the user id bzr will use when committing.
 
47
check_signatures - this option controls whether bzr will require good gpg
 
48
                   signatures, ignore them, or check them if they are
 
49
                   present.
 
50
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.
 
53
log_format - this option sets the default log format.  Possible values are
 
54
             long, short, line, or a plugin can register new formats.
 
55
 
 
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
 
57
 
 
58
[ALIASES]
 
59
lastlog=log --line -r-10..-1
 
60
ll=log --line -r-10..-1
 
61
h=help
 
62
up=pull
 
63
"""
 
64
 
 
65
import os
 
66
import sys
 
67
 
 
68
from bzrlib import commands
 
69
from bzrlib.decorators import needs_write_lock
 
70
from bzrlib.lazy_import import lazy_import
 
71
lazy_import(globals(), """
 
72
import errno
 
73
import fnmatch
 
74
import re
 
75
from cStringIO import StringIO
 
76
 
 
77
import bzrlib
 
78
from bzrlib import (
 
79
    atomicfile,
 
80
    bzrdir,
 
81
    debug,
 
82
    errors,
 
83
    lockdir,
 
84
    mail_client,
 
85
    mergetools,
 
86
    osutils,
 
87
    registry,
 
88
    symbol_versioning,
 
89
    trace,
 
90
    transport,
 
91
    ui,
 
92
    urlutils,
 
93
    win32utils,
 
94
    )
 
95
from bzrlib.util.configobj import configobj
 
96
""")
 
97
 
 
98
 
 
99
CHECK_IF_POSSIBLE=0
 
100
CHECK_ALWAYS=1
 
101
CHECK_NEVER=2
 
102
 
 
103
 
 
104
SIGN_WHEN_REQUIRED=0
 
105
SIGN_ALWAYS=1
 
106
SIGN_NEVER=2
 
107
 
 
108
 
 
109
POLICY_NONE = 0
 
110
POLICY_NORECURSE = 1
 
111
POLICY_APPENDPATH = 2
 
112
 
 
113
_policy_name = {
 
114
    POLICY_NONE: None,
 
115
    POLICY_NORECURSE: 'norecurse',
 
116
    POLICY_APPENDPATH: 'appendpath',
 
117
    }
 
118
_policy_value = {
 
119
    None: POLICY_NONE,
 
120
    'none': POLICY_NONE,
 
121
    'norecurse': POLICY_NORECURSE,
 
122
    'appendpath': POLICY_APPENDPATH,
 
123
    }
 
124
 
 
125
 
 
126
STORE_LOCATION = POLICY_NONE
 
127
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
 
128
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
 
129
STORE_BRANCH = 3
 
130
STORE_GLOBAL = 4
 
131
 
 
132
 
 
133
class ConfigObj(configobj.ConfigObj):
 
134
 
 
135
    def __init__(self, infile=None, **kwargs):
 
136
        # We define our own interpolation mechanism calling it option expansion
 
137
        super(ConfigObj, self).__init__(infile=infile,
 
138
                                        interpolation=False,
 
139
                                        **kwargs)
 
140
 
 
141
 
 
142
    def get_bool(self, section, key):
 
143
        return self[section].as_bool(key)
 
144
 
 
145
    def get_value(self, section, name):
 
146
        # Try [] for the old DEFAULT section.
 
147
        if section == "DEFAULT":
 
148
            try:
 
149
                return self[name]
 
150
            except KeyError:
 
151
                pass
 
152
        return self[section][name]
 
153
 
 
154
 
 
155
# FIXME: Until we can guarantee that each config file is loaded once and and
 
156
# only once for a given bzrlib session, we don't want to re-read the file every
 
157
# time we query for an option so we cache the value (bad ! watch out for tests
 
158
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
159
# yell at mgz^W vila and the RM if this is still present at that time
 
160
# -- vila 20110219
 
161
_expand_default_value = None
 
162
def _get_expand_default_value():
 
163
    global _expand_default_value
 
164
    if _expand_default_value is not None:
 
165
        return _expand_default_value
 
166
    conf = GlobalConfig()
 
167
    # Note that we must not use None for the expand value below or we'll run
 
168
    # into infinite recursion. Using False really would be quite silly ;)
 
169
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
 
170
    if expand is None:
 
171
        # This is an opt-in feature, you *really* need to clearly say you want
 
172
        # to activate it !
 
173
        expand = False
 
174
    _expand_default_value = expand
 
175
    return expand
 
176
 
 
177
 
 
178
class Config(object):
 
179
    """A configuration policy - what username, editor, gpg needs etc."""
 
180
 
 
181
    def __init__(self):
 
182
        super(Config, self).__init__()
 
183
 
 
184
    def config_id(self):
 
185
        """Returns a unique ID for the config."""
 
186
        raise NotImplementedError(self.config_id)
 
187
 
 
188
    def get_editor(self):
 
189
        """Get the users pop up editor."""
 
190
        raise NotImplementedError
 
191
 
 
192
    def get_change_editor(self, old_tree, new_tree):
 
193
        from bzrlib import diff
 
194
        cmd = self._get_change_editor()
 
195
        if cmd is None:
 
196
            return None
 
197
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
 
198
                                             sys.stdout)
 
199
 
 
200
 
 
201
    def get_mail_client(self):
 
202
        """Get a mail client to use"""
 
203
        selected_client = self.get_user_option('mail_client')
 
204
        _registry = mail_client.mail_client_registry
 
205
        try:
 
206
            mail_client_class = _registry.get(selected_client)
 
207
        except KeyError:
 
208
            raise errors.UnknownMailClient(selected_client)
 
209
        return mail_client_class(self)
 
210
 
 
211
    def _get_signature_checking(self):
 
212
        """Template method to override signature checking policy."""
 
213
 
 
214
    def _get_signing_policy(self):
 
215
        """Template method to override signature creation policy."""
 
216
 
 
217
    option_ref_re = None
 
218
 
 
219
    def expand_options(self, string, env=None):
 
220
        """Expand option references in the string in the configuration context.
 
221
 
 
222
        :param string: The string containing option to expand.
 
223
 
 
224
        :param env: An option dict defining additional configuration options or
 
225
            overriding existing ones.
 
226
 
 
227
        :returns: The expanded string.
 
228
        """
 
229
        return self._expand_options_in_string(string, env)
 
230
 
 
231
    def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
 
232
        """Expand options in  a list of strings in the configuration context.
 
233
 
 
234
        :param slist: A list of strings.
 
235
 
 
236
        :param env: An option dict defining additional configuration options or
 
237
            overriding existing ones.
 
238
 
 
239
        :param _ref_stack: Private list containing the options being
 
240
            expanded to detect loops.
 
241
 
 
242
        :returns: The flatten list of expanded strings.
 
243
        """
 
244
        # expand options in each value separately flattening lists
 
245
        result = []
 
246
        for s in slist:
 
247
            value = self._expand_options_in_string(s, env, _ref_stack)
 
248
            if isinstance(value, list):
 
249
                result.extend(value)
 
250
            else:
 
251
                result.append(value)
 
252
        return result
 
253
 
 
254
    def _expand_options_in_string(self, string, env=None, _ref_stack=None):
 
255
        """Expand options in the string in the configuration context.
 
256
 
 
257
        :param string: The string to be expanded.
 
258
 
 
259
        :param env: An option dict defining additional configuration options or
 
260
            overriding existing ones.
 
261
 
 
262
        :param _ref_stack: Private list containing the options being
 
263
            expanded to detect loops.
 
264
 
 
265
        :returns: The expanded string.
 
266
        """
 
267
        if string is None:
 
268
            # Not much to expand there
 
269
            return None
 
270
        if _ref_stack is None:
 
271
            # What references are currently resolved (to detect loops)
 
272
            _ref_stack = []
 
273
        if self.option_ref_re is None:
 
274
            # We want to match the most embedded reference first (i.e. for
 
275
            # '{{foo}}' we will get '{foo}',
 
276
            # for '{bar{baz}}' we will get '{baz}'
 
277
            self.option_ref_re = re.compile('({[^{}]+})')
 
278
        result = string
 
279
        # We need to iterate until no more refs appear ({{foo}} will need two
 
280
        # iterations for example).
 
281
        while True:
 
282
            try:
 
283
                raw_chunks = self.option_ref_re.split(result)
 
284
            except TypeError:
 
285
                import pdb; pdb.set_trace()
 
286
            if len(raw_chunks) == 1:
 
287
                # Shorcut the trivial case: no refs
 
288
                return result
 
289
            chunks = []
 
290
            list_value = False
 
291
            # Split will isolate refs so that every other chunk is a ref
 
292
            chunk_is_ref = False
 
293
            for chunk in raw_chunks:
 
294
                if not chunk_is_ref:
 
295
                    if chunk:
 
296
                        # Keep only non-empty strings (or we get bogus empty
 
297
                        # slots when a list value is involved).
 
298
                        chunks.append(chunk)
 
299
                    chunk_is_ref = True
 
300
                else:
 
301
                    name = chunk[1:-1]
 
302
                    if name in _ref_stack:
 
303
                        raise errors.OptionExpansionLoop(string, _ref_stack)
 
304
                    _ref_stack.append(name)
 
305
                    value = self._expand_option(name, env, _ref_stack)
 
306
                    if value is None:
 
307
                        raise errors.ExpandingUnknownOption(name, string)
 
308
                    if isinstance(value, list):
 
309
                        list_value = True
 
310
                        chunks.extend(value)
 
311
                    else:
 
312
                        chunks.append(value)
 
313
                    _ref_stack.pop()
 
314
                    chunk_is_ref = False
 
315
            if list_value:
 
316
                # Once a list appears as the result of an expansion, all
 
317
                # callers will get a list result. This allows a consistent
 
318
                # behavior even when some options in the expansion chain
 
319
                # defined as strings (no comma in their value) but their
 
320
                # expanded value is a list.
 
321
                return self._expand_options_in_list(chunks, env, _ref_stack)
 
322
            else:
 
323
                result = ''.join(chunks)
 
324
        return result
 
325
 
 
326
    def _expand_option(self, name, env, _ref_stack):
 
327
        if env is not None and name in env:
 
328
            # Special case, values provided in env takes precedence over
 
329
            # anything else
 
330
            value = env[name]
 
331
        else:
 
332
            # FIXME: This is a limited implementation, what we really need is a
 
333
            # way to query the bzr config for the value of an option,
 
334
            # respecting the scope rules (That is, once we implement fallback
 
335
            # configs, getting the option value should restart from the top
 
336
            # config, not the current one) -- vila 20101222
 
337
            value = self.get_user_option(name, expand=False)
 
338
            if isinstance(value, list):
 
339
                value = self._expand_options_in_list(value, env, _ref_stack)
 
340
            else:
 
341
                value = self._expand_options_in_string(value, env, _ref_stack)
 
342
        return value
 
343
 
 
344
    def _get_user_option(self, option_name):
 
345
        """Template method to provide a user option."""
 
346
        return None
 
347
 
 
348
    def get_user_option(self, option_name, expand=None):
 
349
        """Get a generic option - no special process, no default.
 
350
 
 
351
        :param option_name: The queried option.
 
352
 
 
353
        :param expand: Whether options references should be expanded.
 
354
 
 
355
        :returns: The value of the option.
 
356
        """
 
357
        if expand is None:
 
358
            expand = _get_expand_default_value()
 
359
        value = self._get_user_option(option_name)
 
360
        if expand:
 
361
            if isinstance(value, list):
 
362
                value = self._expand_options_in_list(value)
 
363
            elif isinstance(value, dict):
 
364
                trace.warning('Cannot expand "%s":'
 
365
                              ' Dicts do not support option expansion'
 
366
                              % (option_name,))
 
367
            else:
 
368
                value = self._expand_options_in_string(value)
 
369
        return value
 
370
 
 
371
    def get_user_option_as_bool(self, option_name, expand=None):
 
372
        """Get a generic option as a boolean - no special process, no default.
 
373
 
 
374
        :return None if the option doesn't exist or its value can't be
 
375
            interpreted as a boolean. Returns True or False otherwise.
 
376
        """
 
377
        s = self.get_user_option(option_name, expand=expand)
 
378
        if s is None:
 
379
            # The option doesn't exist
 
380
            return None
 
381
        val = ui.bool_from_string(s)
 
382
        if val is None:
 
383
            # The value can't be interpreted as a boolean
 
384
            trace.warning('Value "%s" is not a boolean for "%s"',
 
385
                          s, option_name)
 
386
        return val
 
387
 
 
388
    def get_user_option_as_list(self, option_name, expand=None):
 
389
        """Get a generic option as a list - no special process, no default.
 
390
 
 
391
        :return None if the option doesn't exist. Returns the value as a list
 
392
            otherwise.
 
393
        """
 
394
        l = self.get_user_option(option_name, expand=expand)
 
395
        if isinstance(l, (str, unicode)):
 
396
            # A single value, most probably the user forgot (or didn't care to
 
397
            # add) the final ','
 
398
            l = [l]
 
399
        return l
 
400
 
 
401
    def gpg_signing_command(self):
 
402
        """What program should be used to sign signatures?"""
 
403
        result = self._gpg_signing_command()
 
404
        if result is None:
 
405
            result = "gpg"
 
406
        return result
 
407
 
 
408
    def _gpg_signing_command(self):
 
409
        """See gpg_signing_command()."""
 
410
        return None
 
411
 
 
412
    def log_format(self):
 
413
        """What log format should be used"""
 
414
        result = self._log_format()
 
415
        if result is None:
 
416
            result = "long"
 
417
        return result
 
418
 
 
419
    def _log_format(self):
 
420
        """See log_format()."""
 
421
        return None
 
422
 
 
423
    def post_commit(self):
 
424
        """An ordered list of python functions to call.
 
425
 
 
426
        Each function takes branch, rev_id as parameters.
 
427
        """
 
428
        return self._post_commit()
 
429
 
 
430
    def _post_commit(self):
 
431
        """See Config.post_commit."""
 
432
        return None
 
433
 
 
434
    def user_email(self):
 
435
        """Return just the email component of a username."""
 
436
        return extract_email_address(self.username())
 
437
 
 
438
    def username(self):
 
439
        """Return email-style username.
 
440
 
 
441
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
 
442
 
 
443
        $BZR_EMAIL can be set to override this, then
 
444
        the concrete policy type is checked, and finally
 
445
        $EMAIL is examined.
 
446
        If no username can be found, errors.NoWhoami exception is raised.
 
447
 
 
448
        TODO: Check it's reasonably well-formed.
 
449
        """
 
450
        v = os.environ.get('BZR_EMAIL')
 
451
        if v:
 
452
            return v.decode(osutils.get_user_encoding())
 
453
 
 
454
        v = self._get_user_id()
 
455
        if v:
 
456
            return v
 
457
 
 
458
        v = os.environ.get('EMAIL')
 
459
        if v:
 
460
            return v.decode(osutils.get_user_encoding())
 
461
 
 
462
        raise errors.NoWhoami()
 
463
 
 
464
    def ensure_username(self):
 
465
        """Raise errors.NoWhoami if username is not set.
 
466
 
 
467
        This method relies on the username() function raising the error.
 
468
        """
 
469
        self.username()
 
470
 
 
471
    def signature_checking(self):
 
472
        """What is the current policy for signature checking?."""
 
473
        policy = self._get_signature_checking()
 
474
        if policy is not None:
 
475
            return policy
 
476
        return CHECK_IF_POSSIBLE
 
477
 
 
478
    def signing_policy(self):
 
479
        """What is the current policy for signature checking?."""
 
480
        policy = self._get_signing_policy()
 
481
        if policy is not None:
 
482
            return policy
 
483
        return SIGN_WHEN_REQUIRED
 
484
 
 
485
    def signature_needed(self):
 
486
        """Is a signature needed when committing ?."""
 
487
        policy = self._get_signing_policy()
 
488
        if policy is None:
 
489
            policy = self._get_signature_checking()
 
490
            if policy is not None:
 
491
                trace.warning("Please use create_signatures,"
 
492
                              " not check_signatures to set signing policy.")
 
493
            if policy == CHECK_ALWAYS:
 
494
                return True
 
495
        elif policy == SIGN_ALWAYS:
 
496
            return True
 
497
        return False
 
498
 
 
499
    def get_alias(self, value):
 
500
        return self._get_alias(value)
 
501
 
 
502
    def _get_alias(self, value):
 
503
        pass
 
504
 
 
505
    def get_nickname(self):
 
506
        return self._get_nickname()
 
507
 
 
508
    def _get_nickname(self):
 
509
        return None
 
510
 
 
511
    def get_bzr_remote_path(self):
 
512
        try:
 
513
            return os.environ['BZR_REMOTE_PATH']
 
514
        except KeyError:
 
515
            path = self.get_user_option("bzr_remote_path")
 
516
            if path is None:
 
517
                path = 'bzr'
 
518
            return path
 
519
 
 
520
    def suppress_warning(self, warning):
 
521
        """Should the warning be suppressed or emitted.
 
522
 
 
523
        :param warning: The name of the warning being tested.
 
524
 
 
525
        :returns: True if the warning should be suppressed, False otherwise.
 
526
        """
 
527
        warnings = self.get_user_option_as_list('suppress_warnings')
 
528
        if warnings is None or warning not in warnings:
 
529
            return False
 
530
        else:
 
531
            return True
 
532
 
 
533
    def get_merge_tools(self):
 
534
        tools = {}
 
535
        for (oname, value, section, conf_id, parser) in self._get_options():
 
536
            if oname.startswith('bzr.mergetool.'):
 
537
                tool_name = oname[len('bzr.mergetool.'):]
 
538
                tools[tool_name] = value
 
539
        trace.mutter('loaded merge tools: %r' % tools)
 
540
        return tools
 
541
 
 
542
    def find_merge_tool(self, name):
 
543
        # We fake a defaults mechanism here by checking if the given name can 
 
544
        # be found in the known_merge_tools if it's not found in the config.
 
545
        # This should be done through the proposed config defaults mechanism
 
546
        # when it becomes available in the future.
 
547
        command_line = (self.get_user_option('bzr.mergetool.%s' % name,
 
548
                                             expand=False)
 
549
                        or mergetools.known_merge_tools.get(name, None))
 
550
        return command_line
 
551
 
 
552
 
 
553
class IniBasedConfig(Config):
 
554
    """A configuration policy that draws from ini files."""
 
555
 
 
556
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
 
557
                 file_name=None):
 
558
        """Base class for configuration files using an ini-like syntax.
 
559
 
 
560
        :param file_name: The configuration file path.
 
561
        """
 
562
        super(IniBasedConfig, self).__init__()
 
563
        self.file_name = file_name
 
564
        if symbol_versioning.deprecated_passed(get_filename):
 
565
            symbol_versioning.warn(
 
566
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
567
                ' Use file_name instead.',
 
568
                DeprecationWarning,
 
569
                stacklevel=2)
 
570
            if get_filename is not None:
 
571
                self.file_name = get_filename()
 
572
        else:
 
573
            self.file_name = file_name
 
574
        self._content = None
 
575
        self._parser = None
 
576
 
 
577
    @classmethod
 
578
    def from_string(cls, str_or_unicode, file_name=None, save=False):
 
579
        """Create a config object from a string.
 
580
 
 
581
        :param str_or_unicode: A string representing the file content. This will
 
582
            be utf-8 encoded.
 
583
 
 
584
        :param file_name: The configuration file path.
 
585
 
 
586
        :param _save: Whether the file should be saved upon creation.
 
587
        """
 
588
        conf = cls(file_name=file_name)
 
589
        conf._create_from_string(str_or_unicode, save)
 
590
        return conf
 
591
 
 
592
    def _create_from_string(self, str_or_unicode, save):
 
593
        self._content = StringIO(str_or_unicode.encode('utf-8'))
 
594
        # Some tests use in-memory configs, some other always need the config
 
595
        # file to exist on disk.
 
596
        if save:
 
597
            self._write_config_file()
 
598
 
 
599
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
 
600
        if self._parser is not None:
 
601
            return self._parser
 
602
        if symbol_versioning.deprecated_passed(file):
 
603
            symbol_versioning.warn(
 
604
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
605
                ' Use IniBasedConfig(_content=xxx) instead.',
 
606
                DeprecationWarning,
 
607
                stacklevel=2)
 
608
        if self._content is not None:
 
609
            co_input = self._content
 
610
        elif self.file_name is None:
 
611
            raise AssertionError('We have no content to create the config')
 
612
        else:
 
613
            co_input = self.file_name
 
614
        try:
 
615
            self._parser = ConfigObj(co_input, encoding='utf-8')
 
616
        except configobj.ConfigObjError, e:
 
617
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
618
        # Make sure self.reload() will use the right file name
 
619
        self._parser.filename = self.file_name
 
620
        return self._parser
 
621
 
 
622
    def reload(self):
 
623
        """Reload the config file from disk."""
 
624
        if self.file_name is None:
 
625
            raise AssertionError('We need a file name to reload the config')
 
626
        if self._parser is not None:
 
627
            self._parser.reload()
 
628
 
 
629
    def _get_matching_sections(self):
 
630
        """Return an ordered list of (section_name, extra_path) pairs.
 
631
 
 
632
        If the section contains inherited configuration, extra_path is
 
633
        a string containing the additional path components.
 
634
        """
 
635
        section = self._get_section()
 
636
        if section is not None:
 
637
            return [(section, '')]
 
638
        else:
 
639
            return []
 
640
 
 
641
    def _get_section(self):
 
642
        """Override this to define the section used by the config."""
 
643
        return "DEFAULT"
 
644
 
 
645
    def _get_sections(self, name=None):
 
646
        """Returns an iterator of the sections specified by ``name``.
 
647
 
 
648
        :param name: The section name. If None is supplied, the default
 
649
            configurations are yielded.
 
650
 
 
651
        :return: A tuple (name, section, config_id) for all sections that will
 
652
            be walked by user_get_option() in the 'right' order. The first one
 
653
            is where set_user_option() will update the value.
 
654
        """
 
655
        parser = self._get_parser()
 
656
        if name is not None:
 
657
            yield (name, parser[name], self.config_id())
 
658
        else:
 
659
            # No section name has been given so we fallback to the configobj
 
660
            # itself which holds the variables defined outside of any section.
 
661
            yield (None, parser, self.config_id())
 
662
 
 
663
    def _get_options(self, sections=None):
 
664
        """Return an ordered list of (name, value, section, config_id) tuples.
 
665
 
 
666
        All options are returned with their associated value and the section
 
667
        they appeared in. ``config_id`` is a unique identifier for the
 
668
        configuration file the option is defined in.
 
669
 
 
670
        :param sections: Default to ``_get_matching_sections`` if not
 
671
            specified. This gives a better control to daughter classes about
 
672
            which sections should be searched. This is a list of (name,
 
673
            configobj) tuples.
 
674
        """
 
675
        opts = []
 
676
        if sections is None:
 
677
            parser = self._get_parser()
 
678
            sections = []
 
679
            for (section_name, _) in self._get_matching_sections():
 
680
                try:
 
681
                    section = parser[section_name]
 
682
                except KeyError:
 
683
                    # This could happen for an empty file for which we define a
 
684
                    # DEFAULT section. FIXME: Force callers to provide sections
 
685
                    # instead ? -- vila 20100930
 
686
                    continue
 
687
                sections.append((section_name, section))
 
688
        config_id = self.config_id()
 
689
        for (section_name, section) in sections:
 
690
            for (name, value) in section.iteritems():
 
691
                yield (name, parser._quote(value), section_name,
 
692
                       config_id, parser)
 
693
 
 
694
    def _get_option_policy(self, section, option_name):
 
695
        """Return the policy for the given (section, option_name) pair."""
 
696
        return POLICY_NONE
 
697
 
 
698
    def _get_change_editor(self):
 
699
        return self.get_user_option('change_editor')
 
700
 
 
701
    def _get_signature_checking(self):
 
702
        """See Config._get_signature_checking."""
 
703
        policy = self._get_user_option('check_signatures')
 
704
        if policy:
 
705
            return self._string_to_signature_policy(policy)
 
706
 
 
707
    def _get_signing_policy(self):
 
708
        """See Config._get_signing_policy"""
 
709
        policy = self._get_user_option('create_signatures')
 
710
        if policy:
 
711
            return self._string_to_signing_policy(policy)
 
712
 
 
713
    def _get_user_id(self):
 
714
        """Get the user id from the 'email' key in the current section."""
 
715
        return self._get_user_option('email')
 
716
 
 
717
    def _get_user_option(self, option_name):
 
718
        """See Config._get_user_option."""
 
719
        for (section, extra_path) in self._get_matching_sections():
 
720
            try:
 
721
                value = self._get_parser().get_value(section, option_name)
 
722
            except KeyError:
 
723
                continue
 
724
            policy = self._get_option_policy(section, option_name)
 
725
            if policy == POLICY_NONE:
 
726
                return value
 
727
            elif policy == POLICY_NORECURSE:
 
728
                # norecurse items only apply to the exact path
 
729
                if extra_path:
 
730
                    continue
 
731
                else:
 
732
                    return value
 
733
            elif policy == POLICY_APPENDPATH:
 
734
                if extra_path:
 
735
                    value = urlutils.join(value, extra_path)
 
736
                return value
 
737
            else:
 
738
                raise AssertionError('Unexpected config policy %r' % policy)
 
739
        else:
 
740
            return None
 
741
 
 
742
    def _gpg_signing_command(self):
 
743
        """See Config.gpg_signing_command."""
 
744
        return self._get_user_option('gpg_signing_command')
 
745
 
 
746
    def _log_format(self):
 
747
        """See Config.log_format."""
 
748
        return self._get_user_option('log_format')
 
749
 
 
750
    def _post_commit(self):
 
751
        """See Config.post_commit."""
 
752
        return self._get_user_option('post_commit')
 
753
 
 
754
    def _string_to_signature_policy(self, signature_string):
 
755
        """Convert a string to a signing policy."""
 
756
        if signature_string.lower() == 'check-available':
 
757
            return CHECK_IF_POSSIBLE
 
758
        if signature_string.lower() == 'ignore':
 
759
            return CHECK_NEVER
 
760
        if signature_string.lower() == 'require':
 
761
            return CHECK_ALWAYS
 
762
        raise errors.BzrError("Invalid signatures policy '%s'"
 
763
                              % signature_string)
 
764
 
 
765
    def _string_to_signing_policy(self, signature_string):
 
766
        """Convert a string to a signing policy."""
 
767
        if signature_string.lower() == 'when-required':
 
768
            return SIGN_WHEN_REQUIRED
 
769
        if signature_string.lower() == 'never':
 
770
            return SIGN_NEVER
 
771
        if signature_string.lower() == 'always':
 
772
            return SIGN_ALWAYS
 
773
        raise errors.BzrError("Invalid signing policy '%s'"
 
774
                              % signature_string)
 
775
 
 
776
    def _get_alias(self, value):
 
777
        try:
 
778
            return self._get_parser().get_value("ALIASES",
 
779
                                                value)
 
780
        except KeyError:
 
781
            pass
 
782
 
 
783
    def _get_nickname(self):
 
784
        return self.get_user_option('nickname')
 
785
 
 
786
    def remove_user_option(self, option_name, section_name=None):
 
787
        """Remove a user option and save the configuration file.
 
788
 
 
789
        :param option_name: The option to be removed.
 
790
 
 
791
        :param section_name: The section the option is defined in, default to
 
792
            the default section.
 
793
        """
 
794
        self.reload()
 
795
        parser = self._get_parser()
 
796
        if section_name is None:
 
797
            section = parser
 
798
        else:
 
799
            section = parser[section_name]
 
800
        try:
 
801
            del section[option_name]
 
802
        except KeyError:
 
803
            raise errors.NoSuchConfigOption(option_name)
 
804
        self._write_config_file()
 
805
 
 
806
    def _write_config_file(self):
 
807
        if self.file_name is None:
 
808
            raise AssertionError('We cannot save, self.file_name is None')
 
809
        conf_dir = os.path.dirname(self.file_name)
 
810
        ensure_config_dir_exists(conf_dir)
 
811
        atomic_file = atomicfile.AtomicFile(self.file_name)
 
812
        self._get_parser().write(atomic_file)
 
813
        atomic_file.commit()
 
814
        atomic_file.close()
 
815
        osutils.copy_ownership_from_path(self.file_name)
 
816
 
 
817
 
 
818
class LockableConfig(IniBasedConfig):
 
819
    """A configuration needing explicit locking for access.
 
820
 
 
821
    If several processes try to write the config file, the accesses need to be
 
822
    serialized.
 
823
 
 
824
    Daughter classes should decorate all methods that update a config with the
 
825
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
 
826
    ``_write_config_file()`` method. These methods (typically ``set_option()``
 
827
    and variants must reload the config file from disk before calling
 
828
    ``_write_config_file()``), this can be achieved by calling the
 
829
    ``self.reload()`` method. Note that the lock scope should cover both the
 
830
    reading and the writing of the config file which is why the decorator can't
 
831
    be applied to ``_write_config_file()`` only.
 
832
 
 
833
    This should be enough to implement the following logic:
 
834
    - lock for exclusive write access,
 
835
    - reload the config file from disk,
 
836
    - set the new value
 
837
    - unlock
 
838
 
 
839
    This logic guarantees that a writer can update a value without erasing an
 
840
    update made by another writer.
 
841
    """
 
842
 
 
843
    lock_name = 'lock'
 
844
 
 
845
    def __init__(self, file_name):
 
846
        super(LockableConfig, self).__init__(file_name=file_name)
 
847
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
 
848
        # FIXME: It doesn't matter that we don't provide possible_transports
 
849
        # below since this is currently used only for local config files ;
 
850
        # local transports are not shared. But if/when we start using
 
851
        # LockableConfig for other kind of transports, we will need to reuse
 
852
        # whatever connection is already established -- vila 20100929
 
853
        self.transport = transport.get_transport(self.dir)
 
854
        self._lock = lockdir.LockDir(self.transport, 'lock')
 
855
 
 
856
    def _create_from_string(self, unicode_bytes, save):
 
857
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
 
858
        if save:
 
859
            # We need to handle the saving here (as opposed to IniBasedConfig)
 
860
            # to be able to lock
 
861
            self.lock_write()
 
862
            self._write_config_file()
 
863
            self.unlock()
 
864
 
 
865
    def lock_write(self, token=None):
 
866
        """Takes a write lock in the directory containing the config file.
 
867
 
 
868
        If the directory doesn't exist it is created.
 
869
        """
 
870
        ensure_config_dir_exists(self.dir)
 
871
        return self._lock.lock_write(token)
 
872
 
 
873
    def unlock(self):
 
874
        self._lock.unlock()
 
875
 
 
876
    def break_lock(self):
 
877
        self._lock.break_lock()
 
878
 
 
879
    @needs_write_lock
 
880
    def remove_user_option(self, option_name, section_name=None):
 
881
        super(LockableConfig, self).remove_user_option(option_name,
 
882
                                                       section_name)
 
883
 
 
884
    def _write_config_file(self):
 
885
        if self._lock is None or not self._lock.is_held:
 
886
            # NB: if the following exception is raised it probably means a
 
887
            # missing @needs_write_lock decorator on one of the callers.
 
888
            raise errors.ObjectNotLocked(self)
 
889
        super(LockableConfig, self)._write_config_file()
 
890
 
 
891
 
 
892
class GlobalConfig(LockableConfig):
 
893
    """The configuration that should be used for a specific location."""
 
894
 
 
895
    def __init__(self):
 
896
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
897
 
 
898
    def config_id(self):
 
899
        return 'bazaar'
 
900
 
 
901
    @classmethod
 
902
    def from_string(cls, str_or_unicode, save=False):
 
903
        """Create a config object from a string.
 
904
 
 
905
        :param str_or_unicode: A string representing the file content. This
 
906
            will be utf-8 encoded.
 
907
 
 
908
        :param save: Whether the file should be saved upon creation.
 
909
        """
 
910
        conf = cls()
 
911
        conf._create_from_string(str_or_unicode, save)
 
912
        return conf
 
913
 
 
914
    def get_editor(self):
 
915
        return self._get_user_option('editor')
 
916
 
 
917
    @needs_write_lock
 
918
    def set_user_option(self, option, value):
 
919
        """Save option and its value in the configuration."""
 
920
        self._set_option(option, value, 'DEFAULT')
 
921
 
 
922
    def get_aliases(self):
 
923
        """Return the aliases section."""
 
924
        if 'ALIASES' in self._get_parser():
 
925
            return self._get_parser()['ALIASES']
 
926
        else:
 
927
            return {}
 
928
 
 
929
    @needs_write_lock
 
930
    def set_alias(self, alias_name, alias_command):
 
931
        """Save the alias in the configuration."""
 
932
        self._set_option(alias_name, alias_command, 'ALIASES')
 
933
 
 
934
    @needs_write_lock
 
935
    def unset_alias(self, alias_name):
 
936
        """Unset an existing alias."""
 
937
        self.reload()
 
938
        aliases = self._get_parser().get('ALIASES')
 
939
        if not aliases or alias_name not in aliases:
 
940
            raise errors.NoSuchAlias(alias_name)
 
941
        del aliases[alias_name]
 
942
        self._write_config_file()
 
943
 
 
944
    def _set_option(self, option, value, section):
 
945
        self.reload()
 
946
        self._get_parser().setdefault(section, {})[option] = value
 
947
        self._write_config_file()
 
948
 
 
949
 
 
950
    def _get_sections(self, name=None):
 
951
        """See IniBasedConfig._get_sections()."""
 
952
        parser = self._get_parser()
 
953
        # We don't give access to options defined outside of any section, we
 
954
        # used the DEFAULT section by... default.
 
955
        if name in (None, 'DEFAULT'):
 
956
            # This could happen for an empty file where the DEFAULT section
 
957
            # doesn't exist yet. So we force DEFAULT when yielding
 
958
            name = 'DEFAULT'
 
959
            if 'DEFAULT' not in parser:
 
960
               parser['DEFAULT']= {}
 
961
        yield (name, parser[name], self.config_id())
 
962
 
 
963
    @needs_write_lock
 
964
    def remove_user_option(self, option_name, section_name=None):
 
965
        if section_name is None:
 
966
            # We need to force the default section.
 
967
            section_name = 'DEFAULT'
 
968
        # We need to avoid the LockableConfig implementation or we'll lock
 
969
        # twice
 
970
        super(LockableConfig, self).remove_user_option(option_name,
 
971
                                                       section_name)
 
972
 
 
973
 
 
974
class LocationConfig(LockableConfig):
 
975
    """A configuration object that gives the policy for a location."""
 
976
 
 
977
    def __init__(self, location):
 
978
        super(LocationConfig, self).__init__(
 
979
            file_name=locations_config_filename())
 
980
        # local file locations are looked up by local path, rather than
 
981
        # by file url. This is because the config file is a user
 
982
        # file, and we would rather not expose the user to file urls.
 
983
        if location.startswith('file://'):
 
984
            location = urlutils.local_path_from_url(location)
 
985
        self.location = location
 
986
 
 
987
    def config_id(self):
 
988
        return 'locations'
 
989
 
 
990
    @classmethod
 
991
    def from_string(cls, str_or_unicode, location, save=False):
 
992
        """Create a config object from a string.
 
993
 
 
994
        :param str_or_unicode: A string representing the file content. This will
 
995
            be utf-8 encoded.
 
996
 
 
997
        :param location: The location url to filter the configuration.
 
998
 
 
999
        :param save: Whether the file should be saved upon creation.
 
1000
        """
 
1001
        conf = cls(location)
 
1002
        conf._create_from_string(str_or_unicode, save)
 
1003
        return conf
 
1004
 
 
1005
    def _get_matching_sections(self):
 
1006
        """Return an ordered list of section names matching this location."""
 
1007
        sections = self._get_parser()
 
1008
        location_names = self.location.split('/')
 
1009
        if self.location.endswith('/'):
 
1010
            del location_names[-1]
 
1011
        matches=[]
 
1012
        for section in sections:
 
1013
            # location is a local path if possible, so we need
 
1014
            # to convert 'file://' urls to local paths if necessary.
 
1015
            # This also avoids having file:///path be a more exact
 
1016
            # match than '/path'.
 
1017
            if section.startswith('file://'):
 
1018
                section_path = urlutils.local_path_from_url(section)
 
1019
            else:
 
1020
                section_path = section
 
1021
            section_names = section_path.split('/')
 
1022
            if section.endswith('/'):
 
1023
                del section_names[-1]
 
1024
            names = zip(location_names, section_names)
 
1025
            matched = True
 
1026
            for name in names:
 
1027
                if not fnmatch.fnmatch(name[0], name[1]):
 
1028
                    matched = False
 
1029
                    break
 
1030
            if not matched:
 
1031
                continue
 
1032
            # so, for the common prefix they matched.
 
1033
            # if section is longer, no match.
 
1034
            if len(section_names) > len(location_names):
 
1035
                continue
 
1036
            matches.append((len(section_names), section,
 
1037
                            '/'.join(location_names[len(section_names):])))
 
1038
        # put the longest (aka more specific) locations first
 
1039
        matches.sort(reverse=True)
 
1040
        sections = []
 
1041
        for (length, section, extra_path) in matches:
 
1042
            sections.append((section, extra_path))
 
1043
            # should we stop looking for parent configs here?
 
1044
            try:
 
1045
                if self._get_parser()[section].as_bool('ignore_parents'):
 
1046
                    break
 
1047
            except KeyError:
 
1048
                pass
 
1049
        return sections
 
1050
 
 
1051
    def _get_sections(self, name=None):
 
1052
        """See IniBasedConfig._get_sections()."""
 
1053
        # We ignore the name here as the only sections handled are named with
 
1054
        # the location path and we don't expose embedded sections either.
 
1055
        parser = self._get_parser()
 
1056
        for name, extra_path in self._get_matching_sections():
 
1057
            yield (name, parser[name], self.config_id())
 
1058
 
 
1059
    def _get_option_policy(self, section, option_name):
 
1060
        """Return the policy for the given (section, option_name) pair."""
 
1061
        # check for the old 'recurse=False' flag
 
1062
        try:
 
1063
            recurse = self._get_parser()[section].as_bool('recurse')
 
1064
        except KeyError:
 
1065
            recurse = True
 
1066
        if not recurse:
 
1067
            return POLICY_NORECURSE
 
1068
 
 
1069
        policy_key = option_name + ':policy'
 
1070
        try:
 
1071
            policy_name = self._get_parser()[section][policy_key]
 
1072
        except KeyError:
 
1073
            policy_name = None
 
1074
 
 
1075
        return _policy_value[policy_name]
 
1076
 
 
1077
    def _set_option_policy(self, section, option_name, option_policy):
 
1078
        """Set the policy for the given option name in the given section."""
 
1079
        # The old recurse=False option affects all options in the
 
1080
        # section.  To handle multiple policies in the section, we
 
1081
        # need to convert it to a policy_norecurse key.
 
1082
        try:
 
1083
            recurse = self._get_parser()[section].as_bool('recurse')
 
1084
        except KeyError:
 
1085
            pass
 
1086
        else:
 
1087
            symbol_versioning.warn(
 
1088
                'The recurse option is deprecated as of 0.14.  '
 
1089
                'The section "%s" has been converted to use policies.'
 
1090
                % section,
 
1091
                DeprecationWarning)
 
1092
            del self._get_parser()[section]['recurse']
 
1093
            if not recurse:
 
1094
                for key in self._get_parser()[section].keys():
 
1095
                    if not key.endswith(':policy'):
 
1096
                        self._get_parser()[section][key +
 
1097
                                                    ':policy'] = 'norecurse'
 
1098
 
 
1099
        policy_key = option_name + ':policy'
 
1100
        policy_name = _policy_name[option_policy]
 
1101
        if policy_name is not None:
 
1102
            self._get_parser()[section][policy_key] = policy_name
 
1103
        else:
 
1104
            if policy_key in self._get_parser()[section]:
 
1105
                del self._get_parser()[section][policy_key]
 
1106
 
 
1107
    @needs_write_lock
 
1108
    def set_user_option(self, option, value, store=STORE_LOCATION):
 
1109
        """Save option and its value in the configuration."""
 
1110
        if store not in [STORE_LOCATION,
 
1111
                         STORE_LOCATION_NORECURSE,
 
1112
                         STORE_LOCATION_APPENDPATH]:
 
1113
            raise ValueError('bad storage policy %r for %r' %
 
1114
                (store, option))
 
1115
        self.reload()
 
1116
        location = self.location
 
1117
        if location.endswith('/'):
 
1118
            location = location[:-1]
 
1119
        parser = self._get_parser()
 
1120
        if not location in parser and not location + '/' in parser:
 
1121
            parser[location] = {}
 
1122
        elif location + '/' in parser:
 
1123
            location = location + '/'
 
1124
        parser[location][option]=value
 
1125
        # the allowed values of store match the config policies
 
1126
        self._set_option_policy(location, option, store)
 
1127
        self._write_config_file()
 
1128
 
 
1129
 
 
1130
class BranchConfig(Config):
 
1131
    """A configuration object giving the policy for a branch."""
 
1132
 
 
1133
    def __init__(self, branch):
 
1134
        super(BranchConfig, self).__init__()
 
1135
        self._location_config = None
 
1136
        self._branch_data_config = None
 
1137
        self._global_config = None
 
1138
        self.branch = branch
 
1139
        self.option_sources = (self._get_location_config,
 
1140
                               self._get_branch_data_config,
 
1141
                               self._get_global_config)
 
1142
 
 
1143
    def config_id(self):
 
1144
        return 'branch'
 
1145
 
 
1146
    def _get_branch_data_config(self):
 
1147
        if self._branch_data_config is None:
 
1148
            self._branch_data_config = TreeConfig(self.branch)
 
1149
            self._branch_data_config.config_id = self.config_id
 
1150
        return self._branch_data_config
 
1151
 
 
1152
    def _get_location_config(self):
 
1153
        if self._location_config is None:
 
1154
            self._location_config = LocationConfig(self.branch.base)
 
1155
        return self._location_config
 
1156
 
 
1157
    def _get_global_config(self):
 
1158
        if self._global_config is None:
 
1159
            self._global_config = GlobalConfig()
 
1160
        return self._global_config
 
1161
 
 
1162
    def _get_best_value(self, option_name):
 
1163
        """This returns a user option from local, tree or global config.
 
1164
 
 
1165
        They are tried in that order.  Use get_safe_value if trusted values
 
1166
        are necessary.
 
1167
        """
 
1168
        for source in self.option_sources:
 
1169
            value = getattr(source(), option_name)()
 
1170
            if value is not None:
 
1171
                return value
 
1172
        return None
 
1173
 
 
1174
    def _get_safe_value(self, option_name):
 
1175
        """This variant of get_best_value never returns untrusted values.
 
1176
 
 
1177
        It does not return values from the branch data, because the branch may
 
1178
        not be controlled by the user.
 
1179
 
 
1180
        We may wish to allow locations.conf to control whether branches are
 
1181
        trusted in the future.
 
1182
        """
 
1183
        for source in (self._get_location_config, self._get_global_config):
 
1184
            value = getattr(source(), option_name)()
 
1185
            if value is not None:
 
1186
                return value
 
1187
        return None
 
1188
 
 
1189
    def _get_user_id(self):
 
1190
        """Return the full user id for the branch.
 
1191
 
 
1192
        e.g. "John Hacker <jhacker@example.com>"
 
1193
        This is looked up in the email controlfile for the branch.
 
1194
        """
 
1195
        try:
 
1196
            return (self.branch._transport.get_bytes("email")
 
1197
                    .decode(osutils.get_user_encoding())
 
1198
                    .rstrip("\r\n"))
 
1199
        except errors.NoSuchFile, e:
 
1200
            pass
 
1201
 
 
1202
        return self._get_best_value('_get_user_id')
 
1203
 
 
1204
    def _get_change_editor(self):
 
1205
        return self._get_best_value('_get_change_editor')
 
1206
 
 
1207
    def _get_signature_checking(self):
 
1208
        """See Config._get_signature_checking."""
 
1209
        return self._get_best_value('_get_signature_checking')
 
1210
 
 
1211
    def _get_signing_policy(self):
 
1212
        """See Config._get_signing_policy."""
 
1213
        return self._get_best_value('_get_signing_policy')
 
1214
 
 
1215
    def _get_user_option(self, option_name):
 
1216
        """See Config._get_user_option."""
 
1217
        for source in self.option_sources:
 
1218
            value = source()._get_user_option(option_name)
 
1219
            if value is not None:
 
1220
                return value
 
1221
        return None
 
1222
 
 
1223
    def _get_sections(self, name=None):
 
1224
        """See IniBasedConfig.get_sections()."""
 
1225
        for source in self.option_sources:
 
1226
            for section in source()._get_sections(name):
 
1227
                yield section
 
1228
 
 
1229
    def _get_options(self, sections=None):
 
1230
        opts = []
 
1231
        # First the locations options
 
1232
        for option in self._get_location_config()._get_options():
 
1233
            yield option
 
1234
        # Then the branch options
 
1235
        branch_config = self._get_branch_data_config()
 
1236
        if sections is None:
 
1237
            sections = [('DEFAULT', branch_config._get_parser())]
 
1238
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
 
1239
        # Config itself has no notion of sections :( -- vila 20101001
 
1240
        config_id = self.config_id()
 
1241
        for (section_name, section) in sections:
 
1242
            for (name, value) in section.iteritems():
 
1243
                yield (name, value, section_name,
 
1244
                       config_id, branch_config._get_parser())
 
1245
        # Then the global options
 
1246
        for option in self._get_global_config()._get_options():
 
1247
            yield option
 
1248
 
 
1249
    def set_user_option(self, name, value, store=STORE_BRANCH,
 
1250
        warn_masked=False):
 
1251
        if store == STORE_BRANCH:
 
1252
            self._get_branch_data_config().set_option(value, name)
 
1253
        elif store == STORE_GLOBAL:
 
1254
            self._get_global_config().set_user_option(name, value)
 
1255
        else:
 
1256
            self._get_location_config().set_user_option(name, value, store)
 
1257
        if not warn_masked:
 
1258
            return
 
1259
        if store in (STORE_GLOBAL, STORE_BRANCH):
 
1260
            mask_value = self._get_location_config().get_user_option(name)
 
1261
            if mask_value is not None:
 
1262
                trace.warning('Value "%s" is masked by "%s" from'
 
1263
                              ' locations.conf', value, mask_value)
 
1264
            else:
 
1265
                if store == STORE_GLOBAL:
 
1266
                    branch_config = self._get_branch_data_config()
 
1267
                    mask_value = branch_config.get_user_option(name)
 
1268
                    if mask_value is not None:
 
1269
                        trace.warning('Value "%s" is masked by "%s" from'
 
1270
                                      ' branch.conf', value, mask_value)
 
1271
 
 
1272
    def remove_user_option(self, option_name, section_name=None):
 
1273
        self._get_branch_data_config().remove_option(option_name, section_name)
 
1274
 
 
1275
    def _gpg_signing_command(self):
 
1276
        """See Config.gpg_signing_command."""
 
1277
        return self._get_safe_value('_gpg_signing_command')
 
1278
 
 
1279
    def _post_commit(self):
 
1280
        """See Config.post_commit."""
 
1281
        return self._get_safe_value('_post_commit')
 
1282
 
 
1283
    def _get_nickname(self):
 
1284
        value = self._get_explicit_nickname()
 
1285
        if value is not None:
 
1286
            return value
 
1287
        return urlutils.unescape(self.branch.base.split('/')[-2])
 
1288
 
 
1289
    def has_explicit_nickname(self):
 
1290
        """Return true if a nickname has been explicitly assigned."""
 
1291
        return self._get_explicit_nickname() is not None
 
1292
 
 
1293
    def _get_explicit_nickname(self):
 
1294
        return self._get_best_value('_get_nickname')
 
1295
 
 
1296
    def _log_format(self):
 
1297
        """See Config.log_format."""
 
1298
        return self._get_best_value('_log_format')
 
1299
 
 
1300
 
 
1301
def ensure_config_dir_exists(path=None):
 
1302
    """Make sure a configuration directory exists.
 
1303
    This makes sure that the directory exists.
 
1304
    On windows, since configuration directories are 2 levels deep,
 
1305
    it makes sure both the directory and the parent directory exists.
 
1306
    """
 
1307
    if path is None:
 
1308
        path = config_dir()
 
1309
    if not os.path.isdir(path):
 
1310
        if sys.platform == 'win32':
 
1311
            parent_dir = os.path.dirname(path)
 
1312
            if not os.path.isdir(parent_dir):
 
1313
                trace.mutter('creating config parent directory: %r', parent_dir)
 
1314
                os.mkdir(parent_dir)
 
1315
        trace.mutter('creating config directory: %r', path)
 
1316
        os.mkdir(path)
 
1317
        osutils.copy_ownership_from_path(path)
 
1318
 
 
1319
 
 
1320
def config_dir():
 
1321
    """Return per-user configuration directory.
 
1322
 
 
1323
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
 
1324
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1325
    that will be used instead.
 
1326
 
 
1327
    TODO: Global option --config-dir to override this.
 
1328
    """
 
1329
    base = os.environ.get('BZR_HOME', None)
 
1330
    if sys.platform == 'win32':
 
1331
        # environ variables on Windows are in user encoding/mbcs. So decode
 
1332
        # before using one
 
1333
        if base is not None:
 
1334
            base = base.decode('mbcs')
 
1335
        if base is None:
 
1336
            base = win32utils.get_appdata_location_unicode()
 
1337
        if base is None:
 
1338
            base = os.environ.get('HOME', None)
 
1339
            if base is not None:
 
1340
                base = base.decode('mbcs')
 
1341
        if base is None:
 
1342
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
 
1343
                                  ' or HOME set')
 
1344
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
1345
    elif sys.platform == 'darwin':
 
1346
        if base is None:
 
1347
            # this takes into account $HOME
 
1348
            base = os.path.expanduser("~")
 
1349
        return osutils.pathjoin(base, '.bazaar')
 
1350
    else:
 
1351
        if base is None:
 
1352
 
 
1353
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1354
            if xdg_dir is None:
 
1355
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1356
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1357
            if osutils.isdir(xdg_dir):
 
1358
                trace.mutter(
 
1359
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1360
                return xdg_dir
 
1361
 
 
1362
            base = os.path.expanduser("~")
 
1363
        return osutils.pathjoin(base, ".bazaar")
 
1364
 
 
1365
 
 
1366
def config_filename():
 
1367
    """Return per-user configuration ini file filename."""
 
1368
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
 
1369
 
 
1370
 
 
1371
def locations_config_filename():
 
1372
    """Return per-user configuration ini file filename."""
 
1373
    return osutils.pathjoin(config_dir(), 'locations.conf')
 
1374
 
 
1375
 
 
1376
def authentication_config_filename():
 
1377
    """Return per-user authentication ini file filename."""
 
1378
    return osutils.pathjoin(config_dir(), 'authentication.conf')
 
1379
 
 
1380
 
 
1381
def user_ignore_config_filename():
 
1382
    """Return the user default ignore filename"""
 
1383
    return osutils.pathjoin(config_dir(), 'ignore')
 
1384
 
 
1385
 
 
1386
def crash_dir():
 
1387
    """Return the directory name to store crash files.
 
1388
 
 
1389
    This doesn't implicitly create it.
 
1390
 
 
1391
    On Windows it's in the config directory; elsewhere it's /var/crash
 
1392
    which may be monitored by apport.  It can be overridden by
 
1393
    $APPORT_CRASH_DIR.
 
1394
    """
 
1395
    if sys.platform == 'win32':
 
1396
        return osutils.pathjoin(config_dir(), 'Crash')
 
1397
    else:
 
1398
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
 
1399
        # 2010-01-31
 
1400
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
 
1401
 
 
1402
 
 
1403
def xdg_cache_dir():
 
1404
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
 
1405
    # Possibly this should be different on Windows?
 
1406
    e = os.environ.get('XDG_CACHE_DIR', None)
 
1407
    if e:
 
1408
        return e
 
1409
    else:
 
1410
        return os.path.expanduser('~/.cache')
 
1411
 
 
1412
 
 
1413
def parse_username(username):
 
1414
    """Parse e-mail username and return a (name, address) tuple."""
 
1415
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
 
1416
    if match is None:
 
1417
        return (username, '')
 
1418
    else:
 
1419
        return (match.group(1), match.group(2))
 
1420
 
 
1421
 
 
1422
def extract_email_address(e):
 
1423
    """Return just the address part of an email string.
 
1424
 
 
1425
    That is just the user@domain part, nothing else.
 
1426
    This part is required to contain only ascii characters.
 
1427
    If it can't be extracted, raises an error.
 
1428
 
 
1429
    >>> extract_email_address('Jane Tester <jane@test.com>')
 
1430
    "jane@test.com"
 
1431
    """
 
1432
    name, email = parse_username(e)
 
1433
    if not email:
 
1434
        raise errors.NoEmailInUsername(e)
 
1435
    return email
 
1436
 
 
1437
 
 
1438
class TreeConfig(IniBasedConfig):
 
1439
    """Branch configuration data associated with its contents, not location"""
 
1440
 
 
1441
    # XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
 
1442
 
 
1443
    def __init__(self, branch):
 
1444
        self._config = branch._get_config()
 
1445
        self.branch = branch
 
1446
 
 
1447
    def _get_parser(self, file=None):
 
1448
        if file is not None:
 
1449
            return IniBasedConfig._get_parser(file)
 
1450
        return self._config._get_configobj()
 
1451
 
 
1452
    def get_option(self, name, section=None, default=None):
 
1453
        self.branch.lock_read()
 
1454
        try:
 
1455
            return self._config.get_option(name, section, default)
 
1456
        finally:
 
1457
            self.branch.unlock()
 
1458
 
 
1459
    def set_option(self, value, name, section=None):
 
1460
        """Set a per-branch configuration option"""
 
1461
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1462
        # higher levels providing the right lock -- vila 20101004
 
1463
        self.branch.lock_write()
 
1464
        try:
 
1465
            self._config.set_option(value, name, section)
 
1466
        finally:
 
1467
            self.branch.unlock()
 
1468
 
 
1469
    def remove_option(self, option_name, section_name=None):
 
1470
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1471
        # higher levels providing the right lock -- vila 20101004
 
1472
        self.branch.lock_write()
 
1473
        try:
 
1474
            self._config.remove_option(option_name, section_name)
 
1475
        finally:
 
1476
            self.branch.unlock()
 
1477
 
 
1478
 
 
1479
class AuthenticationConfig(object):
 
1480
    """The authentication configuration file based on a ini file.
 
1481
 
 
1482
    Implements the authentication.conf file described in
 
1483
    doc/developers/authentication-ring.txt.
 
1484
    """
 
1485
 
 
1486
    def __init__(self, _file=None):
 
1487
        self._config = None # The ConfigObj
 
1488
        if _file is None:
 
1489
            self._filename = authentication_config_filename()
 
1490
            self._input = self._filename = authentication_config_filename()
 
1491
        else:
 
1492
            # Tests can provide a string as _file
 
1493
            self._filename = None
 
1494
            self._input = _file
 
1495
 
 
1496
    def _get_config(self):
 
1497
        if self._config is not None:
 
1498
            return self._config
 
1499
        try:
 
1500
            # FIXME: Should we validate something here ? Includes: empty
 
1501
            # sections are useless, at least one of
 
1502
            # user/password/password_encoding should be defined, etc.
 
1503
 
 
1504
            # Note: the encoding below declares that the file itself is utf-8
 
1505
            # encoded, but the values in the ConfigObj are always Unicode.
 
1506
            self._config = ConfigObj(self._input, encoding='utf-8')
 
1507
        except configobj.ConfigObjError, e:
 
1508
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
1509
        return self._config
 
1510
 
 
1511
    def _save(self):
 
1512
        """Save the config file, only tests should use it for now."""
 
1513
        conf_dir = os.path.dirname(self._filename)
 
1514
        ensure_config_dir_exists(conf_dir)
 
1515
        f = file(self._filename, 'wb')
 
1516
        try:
 
1517
            self._get_config().write(f)
 
1518
        finally:
 
1519
            f.close()
 
1520
 
 
1521
    def _set_option(self, section_name, option_name, value):
 
1522
        """Set an authentication configuration option"""
 
1523
        conf = self._get_config()
 
1524
        section = conf.get(section_name)
 
1525
        if section is None:
 
1526
            conf[section] = {}
 
1527
            section = conf[section]
 
1528
        section[option_name] = value
 
1529
        self._save()
 
1530
 
 
1531
    def get_credentials(self, scheme, host, port=None, user=None, path=None, 
 
1532
                        realm=None):
 
1533
        """Returns the matching credentials from authentication.conf file.
 
1534
 
 
1535
        :param scheme: protocol
 
1536
 
 
1537
        :param host: the server address
 
1538
 
 
1539
        :param port: the associated port (optional)
 
1540
 
 
1541
        :param user: login (optional)
 
1542
 
 
1543
        :param path: the absolute path on the server (optional)
 
1544
        
 
1545
        :param realm: the http authentication realm (optional)
 
1546
 
 
1547
        :return: A dict containing the matching credentials or None.
 
1548
           This includes:
 
1549
           - name: the section name of the credentials in the
 
1550
             authentication.conf file,
 
1551
           - user: can't be different from the provided user if any,
 
1552
           - scheme: the server protocol,
 
1553
           - host: the server address,
 
1554
           - port: the server port (can be None),
 
1555
           - path: the absolute server path (can be None),
 
1556
           - realm: the http specific authentication realm (can be None),
 
1557
           - password: the decoded password, could be None if the credential
 
1558
             defines only the user
 
1559
           - verify_certificates: https specific, True if the server
 
1560
             certificate should be verified, False otherwise.
 
1561
        """
 
1562
        credentials = None
 
1563
        for auth_def_name, auth_def in self._get_config().items():
 
1564
            if type(auth_def) is not configobj.Section:
 
1565
                raise ValueError("%s defined outside a section" % auth_def_name)
 
1566
 
 
1567
            a_scheme, a_host, a_user, a_path = map(
 
1568
                auth_def.get, ['scheme', 'host', 'user', 'path'])
 
1569
 
 
1570
            try:
 
1571
                a_port = auth_def.as_int('port')
 
1572
            except KeyError:
 
1573
                a_port = None
 
1574
            except ValueError:
 
1575
                raise ValueError("'port' not numeric in %s" % auth_def_name)
 
1576
            try:
 
1577
                a_verify_certificates = auth_def.as_bool('verify_certificates')
 
1578
            except KeyError:
 
1579
                a_verify_certificates = True
 
1580
            except ValueError:
 
1581
                raise ValueError(
 
1582
                    "'verify_certificates' not boolean in %s" % auth_def_name)
 
1583
 
 
1584
            # Attempt matching
 
1585
            if a_scheme is not None and scheme != a_scheme:
 
1586
                continue
 
1587
            if a_host is not None:
 
1588
                if not (host == a_host
 
1589
                        or (a_host.startswith('.') and host.endswith(a_host))):
 
1590
                    continue
 
1591
            if a_port is not None and port != a_port:
 
1592
                continue
 
1593
            if (a_path is not None and path is not None
 
1594
                and not path.startswith(a_path)):
 
1595
                continue
 
1596
            if (a_user is not None and user is not None
 
1597
                and a_user != user):
 
1598
                # Never contradict the caller about the user to be used
 
1599
                continue
 
1600
            if a_user is None:
 
1601
                # Can't find a user
 
1602
                continue
 
1603
            # Prepare a credentials dictionary with additional keys
 
1604
            # for the credential providers
 
1605
            credentials = dict(name=auth_def_name,
 
1606
                               user=a_user,
 
1607
                               scheme=a_scheme,
 
1608
                               host=host,
 
1609
                               port=port,
 
1610
                               path=path,
 
1611
                               realm=realm,
 
1612
                               password=auth_def.get('password', None),
 
1613
                               verify_certificates=a_verify_certificates)
 
1614
            # Decode the password in the credentials (or get one)
 
1615
            self.decode_password(credentials,
 
1616
                                 auth_def.get('password_encoding', None))
 
1617
            if 'auth' in debug.debug_flags:
 
1618
                trace.mutter("Using authentication section: %r", auth_def_name)
 
1619
            break
 
1620
 
 
1621
        if credentials is None:
 
1622
            # No credentials were found in authentication.conf, try the fallback
 
1623
            # credentials stores.
 
1624
            credentials = credential_store_registry.get_fallback_credentials(
 
1625
                scheme, host, port, user, path, realm)
 
1626
 
 
1627
        return credentials
 
1628
 
 
1629
    def set_credentials(self, name, host, user, scheme=None, password=None,
 
1630
                        port=None, path=None, verify_certificates=None,
 
1631
                        realm=None):
 
1632
        """Set authentication credentials for a host.
 
1633
 
 
1634
        Any existing credentials with matching scheme, host, port and path
 
1635
        will be deleted, regardless of name.
 
1636
 
 
1637
        :param name: An arbitrary name to describe this set of credentials.
 
1638
        :param host: Name of the host that accepts these credentials.
 
1639
        :param user: The username portion of these credentials.
 
1640
        :param scheme: The URL scheme (e.g. ssh, http) the credentials apply
 
1641
            to.
 
1642
        :param password: Password portion of these credentials.
 
1643
        :param port: The IP port on the host that these credentials apply to.
 
1644
        :param path: A filesystem path on the host that these credentials
 
1645
            apply to.
 
1646
        :param verify_certificates: On https, verify server certificates if
 
1647
            True.
 
1648
        :param realm: The http authentication realm (optional).
 
1649
        """
 
1650
        values = {'host': host, 'user': user}
 
1651
        if password is not None:
 
1652
            values['password'] = password
 
1653
        if scheme is not None:
 
1654
            values['scheme'] = scheme
 
1655
        if port is not None:
 
1656
            values['port'] = '%d' % port
 
1657
        if path is not None:
 
1658
            values['path'] = path
 
1659
        if verify_certificates is not None:
 
1660
            values['verify_certificates'] = str(verify_certificates)
 
1661
        if realm is not None:
 
1662
            values['realm'] = realm
 
1663
        config = self._get_config()
 
1664
        for_deletion = []
 
1665
        for section, existing_values in config.items():
 
1666
            for key in ('scheme', 'host', 'port', 'path', 'realm'):
 
1667
                if existing_values.get(key) != values.get(key):
 
1668
                    break
 
1669
            else:
 
1670
                del config[section]
 
1671
        config.update({name: values})
 
1672
        self._save()
 
1673
 
 
1674
    def get_user(self, scheme, host, port=None, realm=None, path=None,
 
1675
                 prompt=None, ask=False, default=None):
 
1676
        """Get a user from authentication file.
 
1677
 
 
1678
        :param scheme: protocol
 
1679
 
 
1680
        :param host: the server address
 
1681
 
 
1682
        :param port: the associated port (optional)
 
1683
 
 
1684
        :param realm: the realm sent by the server (optional)
 
1685
 
 
1686
        :param path: the absolute path on the server (optional)
 
1687
 
 
1688
        :param ask: Ask the user if there is no explicitly configured username 
 
1689
                    (optional)
 
1690
 
 
1691
        :param default: The username returned if none is defined (optional).
 
1692
 
 
1693
        :return: The found user.
 
1694
        """
 
1695
        credentials = self.get_credentials(scheme, host, port, user=None,
 
1696
                                           path=path, realm=realm)
 
1697
        if credentials is not None:
 
1698
            user = credentials['user']
 
1699
        else:
 
1700
            user = None
 
1701
        if user is None:
 
1702
            if ask:
 
1703
                if prompt is None:
 
1704
                    # Create a default prompt suitable for most cases
 
1705
                    prompt = scheme.upper() + ' %(host)s username'
 
1706
                # Special handling for optional fields in the prompt
 
1707
                if port is not None:
 
1708
                    prompt_host = '%s:%d' % (host, port)
 
1709
                else:
 
1710
                    prompt_host = host
 
1711
                user = ui.ui_factory.get_username(prompt, host=prompt_host)
 
1712
            else:
 
1713
                user = default
 
1714
        return user
 
1715
 
 
1716
    def get_password(self, scheme, host, user, port=None,
 
1717
                     realm=None, path=None, prompt=None):
 
1718
        """Get a password from authentication file or prompt the user for one.
 
1719
 
 
1720
        :param scheme: protocol
 
1721
 
 
1722
        :param host: the server address
 
1723
 
 
1724
        :param port: the associated port (optional)
 
1725
 
 
1726
        :param user: login
 
1727
 
 
1728
        :param realm: the realm sent by the server (optional)
 
1729
 
 
1730
        :param path: the absolute path on the server (optional)
 
1731
 
 
1732
        :return: The found password or the one entered by the user.
 
1733
        """
 
1734
        credentials = self.get_credentials(scheme, host, port, user, path,
 
1735
                                           realm)
 
1736
        if credentials is not None:
 
1737
            password = credentials['password']
 
1738
            if password is not None and scheme is 'ssh':
 
1739
                trace.warning('password ignored in section [%s],'
 
1740
                              ' use an ssh agent instead'
 
1741
                              % credentials['name'])
 
1742
                password = None
 
1743
        else:
 
1744
            password = None
 
1745
        # Prompt user only if we could't find a password
 
1746
        if password is None:
 
1747
            if prompt is None:
 
1748
                # Create a default prompt suitable for most cases
 
1749
                prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
 
1750
            # Special handling for optional fields in the prompt
 
1751
            if port is not None:
 
1752
                prompt_host = '%s:%d' % (host, port)
 
1753
            else:
 
1754
                prompt_host = host
 
1755
            password = ui.ui_factory.get_password(prompt,
 
1756
                                                  host=prompt_host, user=user)
 
1757
        return password
 
1758
 
 
1759
    def decode_password(self, credentials, encoding):
 
1760
        try:
 
1761
            cs = credential_store_registry.get_credential_store(encoding)
 
1762
        except KeyError:
 
1763
            raise ValueError('%r is not a known password_encoding' % encoding)
 
1764
        credentials['password'] = cs.decode_password(credentials)
 
1765
        return credentials
 
1766
 
 
1767
 
 
1768
class CredentialStoreRegistry(registry.Registry):
 
1769
    """A class that registers credential stores.
 
1770
 
 
1771
    A credential store provides access to credentials via the password_encoding
 
1772
    field in authentication.conf sections.
 
1773
 
 
1774
    Except for stores provided by bzr itself, most stores are expected to be
 
1775
    provided by plugins that will therefore use
 
1776
    register_lazy(password_encoding, module_name, member_name, help=help,
 
1777
    fallback=fallback) to install themselves.
 
1778
 
 
1779
    A fallback credential store is one that is queried if no credentials can be
 
1780
    found via authentication.conf.
 
1781
    """
 
1782
 
 
1783
    def get_credential_store(self, encoding=None):
 
1784
        cs = self.get(encoding)
 
1785
        if callable(cs):
 
1786
            cs = cs()
 
1787
        return cs
 
1788
 
 
1789
    def is_fallback(self, name):
 
1790
        """Check if the named credentials store should be used as fallback."""
 
1791
        return self.get_info(name)
 
1792
 
 
1793
    def get_fallback_credentials(self, scheme, host, port=None, user=None,
 
1794
                                 path=None, realm=None):
 
1795
        """Request credentials from all fallback credentials stores.
 
1796
 
 
1797
        The first credentials store that can provide credentials wins.
 
1798
        """
 
1799
        credentials = None
 
1800
        for name in self.keys():
 
1801
            if not self.is_fallback(name):
 
1802
                continue
 
1803
            cs = self.get_credential_store(name)
 
1804
            credentials = cs.get_credentials(scheme, host, port, user,
 
1805
                                             path, realm)
 
1806
            if credentials is not None:
 
1807
                # We found some credentials
 
1808
                break
 
1809
        return credentials
 
1810
 
 
1811
    def register(self, key, obj, help=None, override_existing=False,
 
1812
                 fallback=False):
 
1813
        """Register a new object to a name.
 
1814
 
 
1815
        :param key: This is the key to use to request the object later.
 
1816
        :param obj: The object to register.
 
1817
        :param help: Help text for this entry. This may be a string or
 
1818
                a callable. If it is a callable, it should take two
 
1819
                parameters (registry, key): this registry and the key that
 
1820
                the help was registered under.
 
1821
        :param override_existing: Raise KeyErorr if False and something has
 
1822
                already been registered for that key. If True, ignore if there
 
1823
                is an existing key (always register the new value).
 
1824
        :param fallback: Whether this credential store should be 
 
1825
                used as fallback.
 
1826
        """
 
1827
        return super(CredentialStoreRegistry,
 
1828
                     self).register(key, obj, help, info=fallback,
 
1829
                                    override_existing=override_existing)
 
1830
 
 
1831
    def register_lazy(self, key, module_name, member_name,
 
1832
                      help=None, override_existing=False,
 
1833
                      fallback=False):
 
1834
        """Register a new credential store to be loaded on request.
 
1835
 
 
1836
        :param module_name: The python path to the module. Such as 'os.path'.
 
1837
        :param member_name: The member of the module to return.  If empty or
 
1838
                None, get() will return the module itself.
 
1839
        :param help: Help text for this entry. This may be a string or
 
1840
                a callable.
 
1841
        :param override_existing: If True, replace the existing object
 
1842
                with the new one. If False, if there is already something
 
1843
                registered with the same key, raise a KeyError
 
1844
        :param fallback: Whether this credential store should be 
 
1845
                used as fallback.
 
1846
        """
 
1847
        return super(CredentialStoreRegistry, self).register_lazy(
 
1848
            key, module_name, member_name, help,
 
1849
            info=fallback, override_existing=override_existing)
 
1850
 
 
1851
 
 
1852
credential_store_registry = CredentialStoreRegistry()
 
1853
 
 
1854
 
 
1855
class CredentialStore(object):
 
1856
    """An abstract class to implement storage for credentials"""
 
1857
 
 
1858
    def decode_password(self, credentials):
 
1859
        """Returns a clear text password for the provided credentials."""
 
1860
        raise NotImplementedError(self.decode_password)
 
1861
 
 
1862
    def get_credentials(self, scheme, host, port=None, user=None, path=None,
 
1863
                        realm=None):
 
1864
        """Return the matching credentials from this credential store.
 
1865
 
 
1866
        This method is only called on fallback credential stores.
 
1867
        """
 
1868
        raise NotImplementedError(self.get_credentials)
 
1869
 
 
1870
 
 
1871
 
 
1872
class PlainTextCredentialStore(CredentialStore):
 
1873
    __doc__ = """Plain text credential store for the authentication.conf file"""
 
1874
 
 
1875
    def decode_password(self, credentials):
 
1876
        """See CredentialStore.decode_password."""
 
1877
        return credentials['password']
 
1878
 
 
1879
 
 
1880
credential_store_registry.register('plain', PlainTextCredentialStore,
 
1881
                                   help=PlainTextCredentialStore.__doc__)
 
1882
credential_store_registry.default_key = 'plain'
 
1883
 
 
1884
 
 
1885
class BzrDirConfig(object):
 
1886
 
 
1887
    def __init__(self, bzrdir):
 
1888
        self._bzrdir = bzrdir
 
1889
        self._config = bzrdir._get_config()
 
1890
 
 
1891
    def set_default_stack_on(self, value):
 
1892
        """Set the default stacking location.
 
1893
 
 
1894
        It may be set to a location, or None.
 
1895
 
 
1896
        This policy affects all branches contained by this bzrdir, except for
 
1897
        those under repositories.
 
1898
        """
 
1899
        if self._config is None:
 
1900
            raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
 
1901
        if value is None:
 
1902
            self._config.set_option('', 'default_stack_on')
 
1903
        else:
 
1904
            self._config.set_option(value, 'default_stack_on')
 
1905
 
 
1906
    def get_default_stack_on(self):
 
1907
        """Return the default stacking location.
 
1908
 
 
1909
        This will either be a location, or None.
 
1910
 
 
1911
        This policy affects all branches contained by this bzrdir, except for
 
1912
        those under repositories.
 
1913
        """
 
1914
        if self._config is None:
 
1915
            return None
 
1916
        value = self._config.get_option('default_stack_on')
 
1917
        if value == '':
 
1918
            value = None
 
1919
        return value
 
1920
 
 
1921
 
 
1922
class TransportConfig(object):
 
1923
    """A Config that reads/writes a config file on a Transport.
 
1924
 
 
1925
    It is a low-level object that considers config data to be name/value pairs
 
1926
    that may be associated with a section.  Assigning meaning to these values
 
1927
    is done at higher levels like TreeConfig.
 
1928
    """
 
1929
 
 
1930
    def __init__(self, transport, filename):
 
1931
        self._transport = transport
 
1932
        self._filename = filename
 
1933
 
 
1934
    def get_option(self, name, section=None, default=None):
 
1935
        """Return the value associated with a named option.
 
1936
 
 
1937
        :param name: The name of the value
 
1938
        :param section: The section the option is in (if any)
 
1939
        :param default: The value to return if the value is not set
 
1940
        :return: The value or default value
 
1941
        """
 
1942
        configobj = self._get_configobj()
 
1943
        if section is None:
 
1944
            section_obj = configobj
 
1945
        else:
 
1946
            try:
 
1947
                section_obj = configobj[section]
 
1948
            except KeyError:
 
1949
                return default
 
1950
        return section_obj.get(name, default)
 
1951
 
 
1952
    def set_option(self, value, name, section=None):
 
1953
        """Set the value associated with a named option.
 
1954
 
 
1955
        :param value: The value to set
 
1956
        :param name: The name of the value to set
 
1957
        :param section: The section the option is in (if any)
 
1958
        """
 
1959
        configobj = self._get_configobj()
 
1960
        if section is None:
 
1961
            configobj[name] = value
 
1962
        else:
 
1963
            configobj.setdefault(section, {})[name] = value
 
1964
        self._set_configobj(configobj)
 
1965
 
 
1966
    def remove_option(self, option_name, section_name=None):
 
1967
        configobj = self._get_configobj()
 
1968
        if section_name is None:
 
1969
            del configobj[option_name]
 
1970
        else:
 
1971
            del configobj[section_name][option_name]
 
1972
        self._set_configobj(configobj)
 
1973
 
 
1974
    def _get_config_file(self):
 
1975
        try:
 
1976
            return StringIO(self._transport.get_bytes(self._filename))
 
1977
        except errors.NoSuchFile:
 
1978
            return StringIO()
 
1979
 
 
1980
    def _get_configobj(self):
 
1981
        f = self._get_config_file()
 
1982
        try:
 
1983
            return ConfigObj(f, encoding='utf-8')
 
1984
        finally:
 
1985
            f.close()
 
1986
 
 
1987
    def _set_configobj(self, configobj):
 
1988
        out_file = StringIO()
 
1989
        configobj.write(out_file)
 
1990
        out_file.seek(0)
 
1991
        self._transport.put_file(self._filename, out_file)
 
1992
 
 
1993
 
 
1994
class cmd_config(commands.Command):
 
1995
    __doc__ = """Display, set or remove a configuration option.
 
1996
 
 
1997
    Display the active value for a given option.
 
1998
 
 
1999
    If --all is specified, NAME is interpreted as a regular expression and all
 
2000
    matching options are displayed mentioning their scope. The active value
 
2001
    that bzr will take into account is the first one displayed for each option.
 
2002
 
 
2003
    If no NAME is given, --all .* is implied.
 
2004
 
 
2005
    Setting a value is achieved by using name=value without spaces. The value
 
2006
    is set in the most relevant scope and can be checked by displaying the
 
2007
    option again.
 
2008
    """
 
2009
 
 
2010
    takes_args = ['name?']
 
2011
 
 
2012
    takes_options = [
 
2013
        'directory',
 
2014
        # FIXME: This should be a registry option so that plugins can register
 
2015
        # their own config files (or not) -- vila 20101002
 
2016
        commands.Option('scope', help='Reduce the scope to the specified'
 
2017
                        ' configuration file',
 
2018
                        type=unicode),
 
2019
        commands.Option('all',
 
2020
            help='Display all the defined values for the matching options.',
 
2021
            ),
 
2022
        commands.Option('remove', help='Remove the option from'
 
2023
                        ' the configuration file'),
 
2024
        ]
 
2025
 
 
2026
    @commands.display_command
 
2027
    def run(self, name=None, all=False, directory=None, scope=None,
 
2028
            remove=False):
 
2029
        if directory is None:
 
2030
            directory = '.'
 
2031
        directory = urlutils.normalize_url(directory)
 
2032
        if remove and all:
 
2033
            raise errors.BzrError(
 
2034
                '--all and --remove are mutually exclusive.')
 
2035
        elif remove:
 
2036
            # Delete the option in the given scope
 
2037
            self._remove_config_option(name, directory, scope)
 
2038
        elif name is None:
 
2039
            # Defaults to all options
 
2040
            self._show_matching_options('.*', directory, scope)
 
2041
        else:
 
2042
            try:
 
2043
                name, value = name.split('=', 1)
 
2044
            except ValueError:
 
2045
                # Display the option(s) value(s)
 
2046
                if all:
 
2047
                    self._show_matching_options(name, directory, scope)
 
2048
                else:
 
2049
                    self._show_value(name, directory, scope)
 
2050
            else:
 
2051
                if all:
 
2052
                    raise errors.BzrError(
 
2053
                        'Only one option can be set.')
 
2054
                # Set the option value
 
2055
                self._set_config_option(name, value, directory, scope)
 
2056
 
 
2057
    def _get_configs(self, directory, scope=None):
 
2058
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
2059
 
 
2060
        :param directory: Where the configurations are derived from.
 
2061
 
 
2062
        :param scope: A specific config to start from.
 
2063
        """
 
2064
        if scope is not None:
 
2065
            if scope == 'bazaar':
 
2066
                yield GlobalConfig()
 
2067
            elif scope == 'locations':
 
2068
                yield LocationConfig(directory)
 
2069
            elif scope == 'branch':
 
2070
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2071
                    directory)
 
2072
                yield br.get_config()
 
2073
        else:
 
2074
            try:
 
2075
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2076
                    directory)
 
2077
                yield br.get_config()
 
2078
            except errors.NotBranchError:
 
2079
                yield LocationConfig(directory)
 
2080
                yield GlobalConfig()
 
2081
 
 
2082
    def _show_value(self, name, directory, scope):
 
2083
        displayed = False
 
2084
        for c in self._get_configs(directory, scope):
 
2085
            if displayed:
 
2086
                break
 
2087
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2088
                if name == oname:
 
2089
                    # Display only the first value and exit
 
2090
 
 
2091
                    # FIXME: We need to use get_user_option to take policies
 
2092
                    # into account and we need to make sure the option exists
 
2093
                    # too (hence the two for loops), this needs a better API
 
2094
                    # -- vila 20101117
 
2095
                    value = c.get_user_option(name)
 
2096
                    # Quote the value appropriately
 
2097
                    value = parser._quote(value)
 
2098
                    self.outf.write('%s\n' % (value,))
 
2099
                    displayed = True
 
2100
                    break
 
2101
        if not displayed:
 
2102
            raise errors.NoSuchConfigOption(name)
 
2103
 
 
2104
    def _show_matching_options(self, name, directory, scope):
 
2105
        name = re.compile(name)
 
2106
        # We want any error in the regexp to be raised *now* so we need to
 
2107
        # avoid the delay introduced by the lazy regexp.
 
2108
        name._compile_and_collapse()
 
2109
        cur_conf_id = None
 
2110
        cur_section = None
 
2111
        for c in self._get_configs(directory, scope):
 
2112
            for (oname, value, section, conf_id, parser) in c._get_options():
 
2113
                if name.search(oname):
 
2114
                    if cur_conf_id != conf_id:
 
2115
                        # Explain where the options are defined
 
2116
                        self.outf.write('%s:\n' % (conf_id,))
 
2117
                        cur_conf_id = conf_id
 
2118
                        cur_section = None
 
2119
                    if (section not in (None, 'DEFAULT')
 
2120
                        and cur_section != section):
 
2121
                        # Display the section if it's not the default (or only)
 
2122
                        # one.
 
2123
                        self.outf.write('  [%s]\n' % (section,))
 
2124
                        cur_section = section
 
2125
                    self.outf.write('  %s = %s\n' % (oname, value))
 
2126
 
 
2127
    def _set_config_option(self, name, value, directory, scope):
 
2128
        for conf in self._get_configs(directory, scope):
 
2129
            conf.set_user_option(name, value)
 
2130
            break
 
2131
        else:
 
2132
            raise errors.NoSuchConfig(scope)
 
2133
 
 
2134
    def _remove_config_option(self, name, directory, scope):
 
2135
        if name is None:
 
2136
            raise errors.BzrCommandError(
 
2137
                '--remove expects an option to remove.')
 
2138
        removed = False
 
2139
        for conf in self._get_configs(directory, scope):
 
2140
            for (section_name, section, conf_id) in conf._get_sections():
 
2141
                if scope is not None and conf_id != scope:
 
2142
                    # Not the right configuration file
 
2143
                    continue
 
2144
                if name in section:
 
2145
                    if conf_id != conf.config_id():
 
2146
                        conf = self._get_configs(directory, conf_id).next()
 
2147
                    # We use the first section in the first config where the
 
2148
                    # option is defined to remove it
 
2149
                    conf.remove_user_option(name, section_name)
 
2150
                    removed = True
 
2151
                    break
 
2152
            break
 
2153
        else:
 
2154
            raise errors.NoSuchConfig(scope)
 
2155
        if not removed:
 
2156
            raise errors.NoSuchConfigOption(name)