~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Ian Clatworthy
  • Date: 2007-12-11 02:07:30 UTC
  • mto: (3119.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 3120.
  • Revision ID: ian.clatworthy@internode.on.net-20071211020730-sdj4kj794dw0628e
make help topics more discoverable

Show diffs side-by-side

added added

removed removed

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