~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2010-12-20 11:57:14 UTC
  • mto: This revision was merged to the branch mainline in revision 5577.
  • Revision ID: jelmer@samba.org-20101220115714-2ru3hfappjweeg7q
Don't use no-plugins.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
68
70
from bzrlib.lazy_import import lazy_import
69
71
lazy_import(globals(), """
70
72
import errno
71
 
from fnmatch import fnmatch
 
73
import fnmatch
72
74
import re
73
75
from cStringIO import StringIO
74
76
 
75
77
import bzrlib
76
78
from bzrlib import (
 
79
    atomicfile,
 
80
    bzrdir,
77
81
    debug,
78
82
    errors,
 
83
    lockdir,
79
84
    mail_client,
80
85
    osutils,
 
86
    registry,
81
87
    symbol_versioning,
82
88
    trace,
 
89
    transport,
83
90
    ui,
84
91
    urlutils,
85
92
    win32utils,
121
128
STORE_BRANCH = 3
122
129
STORE_GLOBAL = 4
123
130
 
124
 
 
125
 
class ConfigObj(configobj.ConfigObj):
126
 
 
127
 
    def get_bool(self, section, key):
128
 
        return self[section].as_bool(key)
129
 
 
130
 
    def get_value(self, section, name):
131
 
        # Try [] for the old DEFAULT section.
132
 
        if section == "DEFAULT":
133
 
            try:
134
 
                return self[name]
135
 
            except KeyError:
136
 
                pass
137
 
        return self[section][name]
 
131
_ConfigObj = None
 
132
def ConfigObj(*args, **kwargs):
 
133
    global _ConfigObj
 
134
    if _ConfigObj is None:
 
135
        class ConfigObj(configobj.ConfigObj):
 
136
 
 
137
            def get_bool(self, section, key):
 
138
                return self[section].as_bool(key)
 
139
 
 
140
            def get_value(self, section, name):
 
141
                # Try [] for the old DEFAULT section.
 
142
                if section == "DEFAULT":
 
143
                    try:
 
144
                        return self[name]
 
145
                    except KeyError:
 
146
                        pass
 
147
                return self[section][name]
 
148
        _ConfigObj = ConfigObj
 
149
    return _ConfigObj(*args, **kwargs)
138
150
 
139
151
 
140
152
class Config(object):
141
153
    """A configuration policy - what username, editor, gpg needs etc."""
142
154
 
 
155
    def __init__(self):
 
156
        super(Config, self).__init__()
 
157
 
 
158
    def config_id(self):
 
159
        """Returns a unique ID for the config."""
 
160
        raise NotImplementedError(self.config_id)
 
161
 
143
162
    def get_editor(self):
144
163
        """Get the users pop up editor."""
145
164
        raise NotImplementedError
146
165
 
 
166
    def get_change_editor(self, old_tree, new_tree):
 
167
        from bzrlib import diff
 
168
        cmd = self._get_change_editor()
 
169
        if cmd is None:
 
170
            return None
 
171
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
 
172
                                             sys.stdout)
 
173
 
 
174
 
147
175
    def get_mail_client(self):
148
176
        """Get a mail client to use"""
149
177
        selected_client = self.get_user_option('mail_client')
 
178
        _registry = mail_client.mail_client_registry
150
179
        try:
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]
 
180
            mail_client_class = _registry.get(selected_client)
164
181
        except KeyError:
165
182
            raise errors.UnknownMailClient(selected_client)
166
183
        return mail_client_class(self)
179
196
        """Get a generic option - no special process, no default."""
180
197
        return self._get_user_option(option_name)
181
198
 
 
199
    def get_user_option_as_bool(self, option_name):
 
200
        """Get a generic option as a boolean - no special process, no default.
 
201
 
 
202
        :return None if the option doesn't exist or its value can't be
 
203
            interpreted as a boolean. Returns True or False otherwise.
 
204
        """
 
205
        s = self._get_user_option(option_name)
 
206
        if s is None:
 
207
            # The option doesn't exist
 
208
            return None
 
209
        val = ui.bool_from_string(s)
 
210
        if val is None:
 
211
            # The value can't be interpreted as a boolean
 
212
            trace.warning('Value "%s" is not a boolean for "%s"',
 
213
                          s, option_name)
 
214
        return val
 
215
 
 
216
    def get_user_option_as_list(self, option_name):
 
217
        """Get a generic option as a list - no special process, no default.
 
218
 
 
219
        :return None if the option doesn't exist. Returns the value as a list
 
220
            otherwise.
 
221
        """
 
222
        l = self._get_user_option(option_name)
 
223
        if isinstance(l, (str, unicode)):
 
224
            # A single value, most probably the user forgot the final ','
 
225
            l = [l]
 
226
        return l
 
227
 
182
228
    def gpg_signing_command(self):
183
229
        """What program should be used to sign signatures?"""
184
230
        result = self._gpg_signing_command()
201
247
        """See log_format()."""
202
248
        return None
203
249
 
204
 
    def __init__(self):
205
 
        super(Config, self).__init__()
206
 
 
207
250
    def post_commit(self):
208
251
        """An ordered list of python functions to call.
209
252
 
221
264
 
222
265
    def username(self):
223
266
        """Return email-style username.
224
 
    
 
267
 
225
268
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
226
 
        
227
 
        $BZR_EMAIL can be set to override this (as well as the
228
 
        deprecated $BZREMAIL), then
 
269
 
 
270
        $BZR_EMAIL can be set to override this, then
229
271
        the concrete policy type is checked, and finally
230
272
        $EMAIL is examined.
231
 
        If none is found, a reasonable default is (hopefully)
232
 
        created.
233
 
    
 
273
        If no username can be found, errors.NoWhoami exception is raised.
 
274
 
234
275
        TODO: Check it's reasonably well-formed.
235
276
        """
236
277
        v = os.environ.get('BZR_EMAIL')
237
278
        if v:
238
 
            return v.decode(bzrlib.user_encoding)
 
279
            return v.decode(osutils.get_user_encoding())
239
280
 
240
281
        v = self._get_user_id()
241
282
        if v:
243
284
 
244
285
        v = os.environ.get('EMAIL')
245
286
        if v:
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
 
287
            return v.decode(osutils.get_user_encoding())
 
288
 
 
289
        raise errors.NoWhoami()
 
290
 
 
291
    def ensure_username(self):
 
292
        """Raise errors.NoWhoami if username is not set.
 
293
 
 
294
        This method relies on the username() function raising the error.
 
295
        """
 
296
        self.username()
253
297
 
254
298
    def signature_checking(self):
255
299
        """What is the current policy for signature checking?."""
300
344
                path = 'bzr'
301
345
            return path
302
346
 
 
347
    def suppress_warning(self, warning):
 
348
        """Should the warning be suppressed or emitted.
 
349
 
 
350
        :param warning: The name of the warning being tested.
 
351
 
 
352
        :returns: True if the warning should be suppressed, False otherwise.
 
353
        """
 
354
        warnings = self.get_user_option_as_list('suppress_warnings')
 
355
        if warnings is None or warning not in warnings:
 
356
            return False
 
357
        else:
 
358
            return True
 
359
 
303
360
 
304
361
class IniBasedConfig(Config):
305
362
    """A configuration policy that draws from ini files."""
306
363
 
307
 
    def _get_parser(self, file=None):
 
364
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
 
365
                 file_name=None):
 
366
        """Base class for configuration files using an ini-like syntax.
 
367
 
 
368
        :param file_name: The configuration file path.
 
369
        """
 
370
        super(IniBasedConfig, self).__init__()
 
371
        self.file_name = file_name
 
372
        if symbol_versioning.deprecated_passed(get_filename):
 
373
            symbol_versioning.warn(
 
374
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
375
                ' Use file_name instead.',
 
376
                DeprecationWarning,
 
377
                stacklevel=2)
 
378
            if get_filename is not None:
 
379
                self.file_name = get_filename()
 
380
        else:
 
381
            self.file_name = file_name
 
382
        self._content = None
 
383
        self._parser = None
 
384
 
 
385
    @classmethod
 
386
    def from_string(cls, str_or_unicode, file_name=None, save=False):
 
387
        """Create a config object from a string.
 
388
 
 
389
        :param str_or_unicode: A string representing the file content. This will
 
390
            be utf-8 encoded.
 
391
 
 
392
        :param file_name: The configuration file path.
 
393
 
 
394
        :param _save: Whether the file should be saved upon creation.
 
395
        """
 
396
        conf = cls(file_name=file_name)
 
397
        conf._create_from_string(str_or_unicode, save)
 
398
        return conf
 
399
 
 
400
    def _create_from_string(self, str_or_unicode, save):
 
401
        self._content = StringIO(str_or_unicode.encode('utf-8'))
 
402
        # Some tests use in-memory configs, some other always need the config
 
403
        # file to exist on disk.
 
404
        if save:
 
405
            self._write_config_file()
 
406
 
 
407
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
308
408
        if self._parser is not None:
309
409
            return self._parser
310
 
        if file is None:
311
 
            input = self._get_filename()
 
410
        if symbol_versioning.deprecated_passed(file):
 
411
            symbol_versioning.warn(
 
412
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
413
                ' Use IniBasedConfig(_content=xxx) instead.',
 
414
                DeprecationWarning,
 
415
                stacklevel=2)
 
416
        if self._content is not None:
 
417
            co_input = self._content
 
418
        elif self.file_name is None:
 
419
            raise AssertionError('We have no content to create the config')
312
420
        else:
313
 
            input = file
 
421
            co_input = self.file_name
314
422
        try:
315
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
423
            self._parser = ConfigObj(co_input, encoding='utf-8')
316
424
        except configobj.ConfigObjError, e:
317
425
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
426
        # Make sure self.reload() will use the right file name
 
427
        self._parser.filename = self.file_name
318
428
        return self._parser
319
429
 
 
430
    def reload(self):
 
431
        """Reload the config file from disk."""
 
432
        if self.file_name is None:
 
433
            raise AssertionError('We need a file name to reload the config')
 
434
        if self._parser is not None:
 
435
            self._parser.reload()
 
436
 
320
437
    def _get_matching_sections(self):
321
438
        """Return an ordered list of (section_name, extra_path) pairs.
322
439
 
333
450
        """Override this to define the section used by the config."""
334
451
        return "DEFAULT"
335
452
 
 
453
    def _get_sections(self, name=None):
 
454
        """Returns an iterator of the sections specified by ``name``.
 
455
 
 
456
        :param name: The section name. If None is supplied, the default
 
457
            configurations are yielded.
 
458
 
 
459
        :return: A tuple (name, section, config_id) for all sections that will
 
460
            be walked by user_get_option() in the 'right' order. The first one
 
461
            is where set_user_option() will update the value.
 
462
        """
 
463
        parser = self._get_parser()
 
464
        if name is not None:
 
465
            yield (name, parser[name], self.config_id())
 
466
        else:
 
467
            # No section name has been given so we fallback to the configobj
 
468
            # itself which holds the variables defined outside of any section.
 
469
            yield (None, parser, self.config_id())
 
470
 
 
471
    def _get_options(self, sections=None):
 
472
        """Return an ordered list of (name, value, section, config_id) tuples.
 
473
 
 
474
        All options are returned with their associated value and the section
 
475
        they appeared in. ``config_id`` is a unique identifier for the
 
476
        configuration file the option is defined in.
 
477
 
 
478
        :param sections: Default to ``_get_matching_sections`` if not
 
479
            specified. This gives a better control to daughter classes about
 
480
            which sections should be searched. This is a list of (name,
 
481
            configobj) tuples.
 
482
        """
 
483
        opts = []
 
484
        if sections is None:
 
485
            parser = self._get_parser()
 
486
            sections = []
 
487
            for (section_name, _) in self._get_matching_sections():
 
488
                try:
 
489
                    section = parser[section_name]
 
490
                except KeyError:
 
491
                    # This could happen for an empty file for which we define a
 
492
                    # DEFAULT section. FIXME: Force callers to provide sections
 
493
                    # instead ? -- vila 20100930
 
494
                    continue
 
495
                sections.append((section_name, section))
 
496
        config_id = self.config_id()
 
497
        for (section_name, section) in sections:
 
498
            for (name, value) in section.iteritems():
 
499
                yield (name, parser._quote(value), section_name,
 
500
                       config_id, parser)
 
501
 
336
502
    def _get_option_policy(self, section, option_name):
337
503
        """Return the policy for the given (section, option_name) pair."""
338
504
        return POLICY_NONE
339
505
 
 
506
    def _get_change_editor(self):
 
507
        return self.get_user_option('change_editor')
 
508
 
340
509
    def _get_signature_checking(self):
341
510
        """See Config._get_signature_checking."""
342
511
        policy = self._get_user_option('check_signatures')
386
555
        """See Config.log_format."""
387
556
        return self._get_user_option('log_format')
388
557
 
389
 
    def __init__(self, get_filename):
390
 
        super(IniBasedConfig, self).__init__()
391
 
        self._get_filename = get_filename
392
 
        self._parser = None
393
 
        
394
558
    def _post_commit(self):
395
559
        """See Config.post_commit."""
396
560
        return self._get_user_option('post_commit')
419
583
 
420
584
    def _get_alias(self, value):
421
585
        try:
422
 
            return self._get_parser().get_value("ALIASES", 
 
586
            return self._get_parser().get_value("ALIASES",
423
587
                                                value)
424
588
        except KeyError:
425
589
            pass
427
591
    def _get_nickname(self):
428
592
        return self.get_user_option('nickname')
429
593
 
430
 
 
431
 
class GlobalConfig(IniBasedConfig):
 
594
    def remove_user_option(self, option_name, section_name=None):
 
595
        """Remove a user option and save the configuration file.
 
596
 
 
597
        :param option_name: The option to be removed.
 
598
 
 
599
        :param section_name: The section the option is defined in, default to
 
600
            the default section.
 
601
        """
 
602
        self.reload()
 
603
        parser = self._get_parser()
 
604
        if section_name is None:
 
605
            section = parser
 
606
        else:
 
607
            section = parser[section_name]
 
608
        try:
 
609
            del section[option_name]
 
610
        except KeyError:
 
611
            raise errors.NoSuchConfigOption(option_name)
 
612
        self._write_config_file()
 
613
 
 
614
    def _write_config_file(self):
 
615
        if self.file_name is None:
 
616
            raise AssertionError('We cannot save, self.file_name is None')
 
617
        conf_dir = os.path.dirname(self.file_name)
 
618
        ensure_config_dir_exists(conf_dir)
 
619
        atomic_file = atomicfile.AtomicFile(self.file_name)
 
620
        self._get_parser().write(atomic_file)
 
621
        atomic_file.commit()
 
622
        atomic_file.close()
 
623
        osutils.copy_ownership_from_path(self.file_name)
 
624
 
 
625
 
 
626
class LockableConfig(IniBasedConfig):
 
627
    """A configuration needing explicit locking for access.
 
628
 
 
629
    If several processes try to write the config file, the accesses need to be
 
630
    serialized.
 
631
 
 
632
    Daughter classes should decorate all methods that update a config with the
 
633
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
 
634
    ``_write_config_file()`` method. These methods (typically ``set_option()``
 
635
    and variants must reload the config file from disk before calling
 
636
    ``_write_config_file()``), this can be achieved by calling the
 
637
    ``self.reload()`` method. Note that the lock scope should cover both the
 
638
    reading and the writing of the config file which is why the decorator can't
 
639
    be applied to ``_write_config_file()`` only.
 
640
 
 
641
    This should be enough to implement the following logic:
 
642
    - lock for exclusive write access,
 
643
    - reload the config file from disk,
 
644
    - set the new value
 
645
    - unlock
 
646
 
 
647
    This logic guarantees that a writer can update a value without erasing an
 
648
    update made by another writer.
 
649
    """
 
650
 
 
651
    lock_name = 'lock'
 
652
 
 
653
    def __init__(self, file_name):
 
654
        super(LockableConfig, self).__init__(file_name=file_name)
 
655
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
 
656
        self.transport = transport.get_transport(self.dir)
 
657
        self._lock = lockdir.LockDir(self.transport, 'lock')
 
658
 
 
659
    def _create_from_string(self, unicode_bytes, save):
 
660
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
 
661
        if save:
 
662
            # We need to handle the saving here (as opposed to IniBasedConfig)
 
663
            # to be able to lock
 
664
            self.lock_write()
 
665
            self._write_config_file()
 
666
            self.unlock()
 
667
 
 
668
    def lock_write(self, token=None):
 
669
        """Takes a write lock in the directory containing the config file.
 
670
 
 
671
        If the directory doesn't exist it is created.
 
672
        """
 
673
        ensure_config_dir_exists(self.dir)
 
674
        return self._lock.lock_write(token)
 
675
 
 
676
    def unlock(self):
 
677
        self._lock.unlock()
 
678
 
 
679
    def break_lock(self):
 
680
        self._lock.break_lock()
 
681
 
 
682
    @needs_write_lock
 
683
    def remove_user_option(self, option_name, section_name=None):
 
684
        super(LockableConfig, self).remove_user_option(option_name,
 
685
                                                       section_name)
 
686
 
 
687
    def _write_config_file(self):
 
688
        if self._lock is None or not self._lock.is_held:
 
689
            # NB: if the following exception is raised it probably means a
 
690
            # missing @needs_write_lock decorator on one of the callers.
 
691
            raise errors.ObjectNotLocked(self)
 
692
        super(LockableConfig, self)._write_config_file()
 
693
 
 
694
 
 
695
class GlobalConfig(LockableConfig):
432
696
    """The configuration that should be used for a specific location."""
433
697
 
 
698
    def __init__(self):
 
699
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
700
 
 
701
    def config_id(self):
 
702
        return 'bazaar'
 
703
 
 
704
    @classmethod
 
705
    def from_string(cls, str_or_unicode, save=False):
 
706
        """Create a config object from a string.
 
707
 
 
708
        :param str_or_unicode: A string representing the file content. This
 
709
            will be utf-8 encoded.
 
710
 
 
711
        :param save: Whether the file should be saved upon creation.
 
712
        """
 
713
        conf = cls()
 
714
        conf._create_from_string(str_or_unicode, save)
 
715
        return conf
 
716
 
434
717
    def get_editor(self):
435
718
        return self._get_user_option('editor')
436
719
 
437
 
    def __init__(self):
438
 
        super(GlobalConfig, self).__init__(config_filename)
439
 
 
 
720
    @needs_write_lock
440
721
    def set_user_option(self, option, value):
441
722
        """Save option and its value in the configuration."""
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):
 
723
        self._set_option(option, value, 'DEFAULT')
 
724
 
 
725
    def get_aliases(self):
 
726
        """Return the aliases section."""
 
727
        if 'ALIASES' in self._get_parser():
 
728
            return self._get_parser()['ALIASES']
 
729
        else:
 
730
            return {}
 
731
 
 
732
    @needs_write_lock
 
733
    def set_alias(self, alias_name, alias_command):
 
734
        """Save the alias in the configuration."""
 
735
        self._set_option(alias_name, alias_command, 'ALIASES')
 
736
 
 
737
    @needs_write_lock
 
738
    def unset_alias(self, alias_name):
 
739
        """Unset an existing alias."""
 
740
        self.reload()
 
741
        aliases = self._get_parser().get('ALIASES')
 
742
        if not aliases or alias_name not in aliases:
 
743
            raise errors.NoSuchAlias(alias_name)
 
744
        del aliases[alias_name]
 
745
        self._write_config_file()
 
746
 
 
747
    def _set_option(self, option, value, section):
 
748
        self.reload()
 
749
        self._get_parser().setdefault(section, {})[option] = value
 
750
        self._write_config_file()
 
751
 
 
752
 
 
753
    def _get_sections(self, name=None):
 
754
        """See IniBasedConfig._get_sections()."""
 
755
        parser = self._get_parser()
 
756
        # We don't give access to options defined outside of any section, we
 
757
        # used the DEFAULT section by... default.
 
758
        if name in (None, 'DEFAULT'):
 
759
            # This could happen for an empty file where the DEFAULT section
 
760
            # doesn't exist yet. So we force DEFAULT when yielding
 
761
            name = 'DEFAULT'
 
762
            if 'DEFAULT' not in parser:
 
763
               parser['DEFAULT']= {}
 
764
        yield (name, parser[name], self.config_id())
 
765
 
 
766
    @needs_write_lock
 
767
    def remove_user_option(self, option_name, section_name=None):
 
768
        if section_name is None:
 
769
            # We need to force the default section.
 
770
            section_name = 'DEFAULT'
 
771
        # We need to avoid the LockableConfig implementation or we'll lock
 
772
        # twice
 
773
        super(LockableConfig, self).remove_user_option(option_name,
 
774
                                                       section_name)
 
775
 
 
776
 
 
777
class LocationConfig(LockableConfig):
455
778
    """A configuration object that gives the policy for a location."""
456
779
 
457
780
    def __init__(self, location):
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)
 
781
        super(LocationConfig, self).__init__(
 
782
            file_name=locations_config_filename())
470
783
        # local file locations are looked up by local path, rather than
471
784
        # by file url. This is because the config file is a user
472
785
        # file, and we would rather not expose the user to file urls.
474
787
            location = urlutils.local_path_from_url(location)
475
788
        self.location = location
476
789
 
 
790
    def config_id(self):
 
791
        return 'locations'
 
792
 
 
793
    @classmethod
 
794
    def from_string(cls, str_or_unicode, location, save=False):
 
795
        """Create a config object from a string.
 
796
 
 
797
        :param str_or_unicode: A string representing the file content. This will
 
798
            be utf-8 encoded.
 
799
 
 
800
        :param location: The location url to filter the configuration.
 
801
 
 
802
        :param save: Whether the file should be saved upon creation.
 
803
        """
 
804
        conf = cls(location)
 
805
        conf._create_from_string(str_or_unicode, save)
 
806
        return conf
 
807
 
477
808
    def _get_matching_sections(self):
478
809
        """Return an ordered list of section names matching this location."""
479
810
        sections = self._get_parser()
496
827
            names = zip(location_names, section_names)
497
828
            matched = True
498
829
            for name in names:
499
 
                if not fnmatch(name[0], name[1]):
 
830
                if not fnmatch.fnmatch(name[0], name[1]):
500
831
                    matched = False
501
832
                    break
502
833
            if not matched:
507
838
                continue
508
839
            matches.append((len(section_names), section,
509
840
                            '/'.join(location_names[len(section_names):])))
 
841
        # put the longest (aka more specific) locations first
510
842
        matches.sort(reverse=True)
511
843
        sections = []
512
844
        for (length, section, extra_path) in matches:
519
851
                pass
520
852
        return sections
521
853
 
 
854
    def _get_sections(self, name=None):
 
855
        """See IniBasedConfig._get_sections()."""
 
856
        # We ignore the name here as the only sections handled are named with
 
857
        # the location path and we don't expose embedded sections either.
 
858
        parser = self._get_parser()
 
859
        for name, extra_path in self._get_matching_sections():
 
860
            yield (name, parser[name], self.config_id())
 
861
 
522
862
    def _get_option_policy(self, section, option_name):
523
863
        """Return the policy for the given (section, option_name) pair."""
524
864
        # check for the old 'recurse=False' flag
567
907
            if policy_key in self._get_parser()[section]:
568
908
                del self._get_parser()[section][policy_key]
569
909
 
 
910
    @needs_write_lock
570
911
    def set_user_option(self, option, value, store=STORE_LOCATION):
571
912
        """Save option and its value in the configuration."""
572
 
        assert store in [STORE_LOCATION,
 
913
        if store not in [STORE_LOCATION,
573
914
                         STORE_LOCATION_NORECURSE,
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)
 
915
                         STORE_LOCATION_APPENDPATH]:
 
916
            raise ValueError('bad storage policy %r for %r' %
 
917
                (store, option))
 
918
        self.reload()
579
919
        location = self.location
580
920
        if location.endswith('/'):
581
921
            location = location[:-1]
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():
 
922
        parser = self._get_parser()
 
923
        if not location in parser and not location + '/' in parser:
 
924
            parser[location] = {}
 
925
        elif location + '/' in parser:
586
926
            location = location + '/'
587
 
        self._get_parser()[location][option]=value
 
927
        parser[location][option]=value
588
928
        # the allowed values of store match the config policies
589
929
        self._set_option_policy(location, option, store)
590
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
930
        self._write_config_file()
591
931
 
592
932
 
593
933
class BranchConfig(Config):
594
934
    """A configuration object giving the policy for a branch."""
595
935
 
 
936
    def __init__(self, branch):
 
937
        super(BranchConfig, self).__init__()
 
938
        self._location_config = None
 
939
        self._branch_data_config = None
 
940
        self._global_config = None
 
941
        self.branch = branch
 
942
        self.option_sources = (self._get_location_config,
 
943
                               self._get_branch_data_config,
 
944
                               self._get_global_config)
 
945
 
 
946
    def config_id(self):
 
947
        return 'branch'
 
948
 
596
949
    def _get_branch_data_config(self):
597
950
        if self._branch_data_config is None:
598
951
            self._branch_data_config = TreeConfig(self.branch)
 
952
            self._branch_data_config.config_id = self.config_id
599
953
        return self._branch_data_config
600
954
 
601
955
    def _get_location_config(self):
622
976
 
623
977
    def _get_safe_value(self, option_name):
624
978
        """This variant of get_best_value never returns untrusted values.
625
 
        
 
979
 
626
980
        It does not return values from the branch data, because the branch may
627
981
        not be controlled by the user.
628
982
 
637
991
 
638
992
    def _get_user_id(self):
639
993
        """Return the full user id for the branch.
640
 
    
641
 
        e.g. "John Hacker <jhacker@foo.org>"
 
994
 
 
995
        e.g. "John Hacker <jhacker@example.com>"
642
996
        This is looked up in the email controlfile for the branch.
643
997
        """
644
998
        try:
645
 
            return (self.branch.control_files.get_utf8("email") 
646
 
                    .read()
647
 
                    .decode(bzrlib.user_encoding)
 
999
            return (self.branch._transport.get_bytes("email")
 
1000
                    .decode(osutils.get_user_encoding())
648
1001
                    .rstrip("\r\n"))
649
1002
        except errors.NoSuchFile, e:
650
1003
            pass
651
 
        
 
1004
 
652
1005
        return self._get_best_value('_get_user_id')
653
1006
 
 
1007
    def _get_change_editor(self):
 
1008
        return self._get_best_value('_get_change_editor')
 
1009
 
654
1010
    def _get_signature_checking(self):
655
1011
        """See Config._get_signature_checking."""
656
1012
        return self._get_best_value('_get_signature_checking')
667
1023
                return value
668
1024
        return None
669
1025
 
 
1026
    def _get_sections(self, name=None):
 
1027
        """See IniBasedConfig.get_sections()."""
 
1028
        for source in self.option_sources:
 
1029
            for section in source()._get_sections(name):
 
1030
                yield section
 
1031
 
 
1032
    def _get_options(self, sections=None):
 
1033
        opts = []
 
1034
        # First the locations options
 
1035
        for option in self._get_location_config()._get_options():
 
1036
            yield option
 
1037
        # Then the branch options
 
1038
        branch_config = self._get_branch_data_config()
 
1039
        if sections is None:
 
1040
            sections = [('DEFAULT', branch_config._get_parser())]
 
1041
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
 
1042
        # Config itself has no notion of sections :( -- vila 20101001
 
1043
        config_id = self.config_id()
 
1044
        for (section_name, section) in sections:
 
1045
            for (name, value) in section.iteritems():
 
1046
                yield (name, value, section_name,
 
1047
                       config_id, branch_config._get_parser())
 
1048
        # Then the global options
 
1049
        for option in self._get_global_config()._get_options():
 
1050
            yield option
 
1051
 
670
1052
    def set_user_option(self, name, value, store=STORE_BRANCH,
671
1053
        warn_masked=False):
672
1054
        if store == STORE_BRANCH:
690
1072
                        trace.warning('Value "%s" is masked by "%s" from'
691
1073
                                      ' branch.conf', value, mask_value)
692
1074
 
 
1075
    def remove_user_option(self, option_name, section_name=None):
 
1076
        self._get_branch_data_config().remove_option(option_name, section_name)
693
1077
 
694
1078
    def _gpg_signing_command(self):
695
1079
        """See Config.gpg_signing_command."""
696
1080
        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)
707
1081
 
708
1082
    def _post_commit(self):
709
1083
        """See Config.post_commit."""
740
1114
            parent_dir = os.path.dirname(path)
741
1115
            if not os.path.isdir(parent_dir):
742
1116
                trace.mutter('creating config parent directory: %r', parent_dir)
743
 
            os.mkdir(parent_dir)
 
1117
                os.mkdir(parent_dir)
744
1118
        trace.mutter('creating config directory: %r', path)
745
1119
        os.mkdir(path)
 
1120
        osutils.copy_ownership_from_path(path)
746
1121
 
747
1122
 
748
1123
def config_dir():
749
1124
    """Return per-user configuration directory.
750
1125
 
751
 
    By default this is ~/.bazaar/
752
 
    
 
1126
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
 
1127
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1128
    that will be used instead.
 
1129
 
753
1130
    TODO: Global option --config-dir to override this.
754
1131
    """
755
1132
    base = os.environ.get('BZR_HOME', None)
762
1139
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
763
1140
                                  ' or HOME set')
764
1141
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
1142
    elif sys.platform == 'darwin':
 
1143
        if base is None:
 
1144
            # this takes into account $HOME
 
1145
            base = os.path.expanduser("~")
 
1146
        return osutils.pathjoin(base, '.bazaar')
765
1147
    else:
766
 
        # cygwin, linux, and darwin all have a $HOME directory
767
1148
        if base is None:
 
1149
 
 
1150
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1151
            if xdg_dir is None:
 
1152
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1153
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1154
            if osutils.isdir(xdg_dir):
 
1155
                trace.mutter(
 
1156
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1157
                return xdg_dir
 
1158
 
768
1159
            base = os.path.expanduser("~")
769
1160
        return osutils.pathjoin(base, ".bazaar")
770
1161
 
774
1165
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
775
1166
 
776
1167
 
777
 
def branches_config_filename():
778
 
    """Return per-user configuration ini file filename."""
779
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
780
 
 
781
 
 
782
1168
def locations_config_filename():
783
1169
    """Return per-user configuration ini file filename."""
784
1170
    return osutils.pathjoin(config_dir(), 'locations.conf')
794
1180
    return osutils.pathjoin(config_dir(), 'ignore')
795
1181
 
796
1182
 
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.
 
1183
def crash_dir():
 
1184
    """Return the directory name to store crash files.
 
1185
 
 
1186
    This doesn't implicitly create it.
 
1187
 
 
1188
    On Windows it's in the config directory; elsewhere it's /var/crash
 
1189
    which may be monitored by apport.  It can be overridden by
 
1190
    $APPORT_CRASH_DIR.
807
1191
    """
808
 
    import socket
809
 
 
810
1192
    if sys.platform == 'win32':
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())
 
1193
        return osutils.pathjoin(config_dir(), 'Crash')
 
1194
    else:
 
1195
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
 
1196
        # 2010-01-31
 
1197
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
 
1198
 
 
1199
 
 
1200
def xdg_cache_dir():
 
1201
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
 
1202
    # Possibly this should be different on Windows?
 
1203
    e = os.environ.get('XDG_CACHE_DIR', None)
 
1204
    if e:
 
1205
        return e
 
1206
    else:
 
1207
        return os.path.expanduser('~/.cache')
 
1208
 
 
1209
 
 
1210
def parse_username(username):
 
1211
    """Parse e-mail username and return a (name, address) tuple."""
 
1212
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
 
1213
    if match is None:
 
1214
        return (username, '')
 
1215
    else:
 
1216
        return (match.group(1), match.group(2))
863
1217
 
864
1218
 
865
1219
def extract_email_address(e):
866
1220
    """Return just the address part of an email string.
867
 
    
868
 
    That is just the user@domain part, nothing else. 
 
1221
 
 
1222
    That is just the user@domain part, nothing else.
869
1223
    This part is required to contain only ascii characters.
870
1224
    If it can't be extracted, raises an error.
871
 
    
 
1225
 
872
1226
    >>> extract_email_address('Jane Tester <jane@test.com>')
873
1227
    "jane@test.com"
874
1228
    """
875
 
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
876
 
    if not m:
 
1229
    name, email = parse_username(e)
 
1230
    if not email:
877
1231
        raise errors.NoEmailInUsername(e)
878
 
    return m.group(0)
 
1232
    return email
879
1233
 
880
1234
 
881
1235
class TreeConfig(IniBasedConfig):
882
1236
    """Branch configuration data associated with its contents, not location"""
883
1237
 
 
1238
    # XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
 
1239
 
884
1240
    def __init__(self, branch):
 
1241
        self._config = branch._get_config()
885
1242
        self.branch = branch
886
1243
 
887
1244
    def _get_parser(self, file=None):
888
1245
        if file is not None:
889
1246
            return IniBasedConfig._get_parser(file)
890
 
        return self._get_config()
891
 
 
892
 
    def _get_config(self):
893
 
        try:
894
 
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),
895
 
                            encoding='utf-8')
896
 
        except errors.NoSuchFile:
897
 
            obj = ConfigObj(encoding='utf=8')
898
 
        return obj
 
1247
        return self._config._get_configobj()
899
1248
 
900
1249
    def get_option(self, name, section=None, default=None):
901
1250
        self.branch.lock_read()
902
1251
        try:
903
 
            obj = self._get_config()
904
 
            try:
905
 
                if section is not None:
906
 
                    obj = obj[section]
907
 
                result = obj[name]
908
 
            except KeyError:
909
 
                result = default
 
1252
            return self._config.get_option(name, section, default)
910
1253
        finally:
911
1254
            self.branch.unlock()
912
 
        return result
913
1255
 
914
1256
    def set_option(self, value, name, section=None):
915
1257
        """Set a per-branch configuration option"""
916
 
        self.branch.lock_write()
917
 
        try:
918
 
            cfg_obj = self._get_config()
919
 
            if section is None:
920
 
                obj = cfg_obj
921
 
            else:
922
 
                try:
923
 
                    obj = cfg_obj[section]
924
 
                except KeyError:
925
 
                    cfg_obj[section] = {}
926
 
                    obj = cfg_obj[section]
927
 
            obj[name] = value
928
 
            out_file = StringIO()
929
 
            cfg_obj.write(out_file)
930
 
            out_file.seek(0)
931
 
            self.branch.control_files.put('branch.conf', out_file)
 
1258
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1259
        # higher levels providing the right lock -- vila 20101004
 
1260
        self.branch.lock_write()
 
1261
        try:
 
1262
            self._config.set_option(value, name, section)
 
1263
        finally:
 
1264
            self.branch.unlock()
 
1265
 
 
1266
    def remove_option(self, option_name, section_name=None):
 
1267
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1268
        # higher levels providing the right lock -- vila 20101004
 
1269
        self.branch.lock_write()
 
1270
        try:
 
1271
            self._config.remove_option(option_name, section_name)
932
1272
        finally:
933
1273
            self.branch.unlock()
934
1274
 
969
1309
        """Save the config file, only tests should use it for now."""
970
1310
        conf_dir = os.path.dirname(self._filename)
971
1311
        ensure_config_dir_exists(conf_dir)
972
 
        self._get_config().write(file(self._filename, 'wb'))
 
1312
        f = file(self._filename, 'wb')
 
1313
        try:
 
1314
            self._get_config().write(f)
 
1315
        finally:
 
1316
            f.close()
973
1317
 
974
1318
    def _set_option(self, section_name, option_name, value):
975
1319
        """Set an authentication configuration option"""
981
1325
        section[option_name] = value
982
1326
        self._save()
983
1327
 
984
 
    def get_credentials(self, scheme, host, port=None, user=None, path=None):
 
1328
    def get_credentials(self, scheme, host, port=None, user=None, path=None, 
 
1329
                        realm=None):
985
1330
        """Returns the matching credentials from authentication.conf file.
986
1331
 
987
1332
        :param scheme: protocol
993
1338
        :param user: login (optional)
994
1339
 
995
1340
        :param path: the absolute path on the server (optional)
 
1341
        
 
1342
        :param realm: the http authentication realm (optional)
996
1343
 
997
1344
        :return: A dict containing the matching credentials or None.
998
1345
           This includes:
999
1346
           - name: the section name of the credentials in the
1000
1347
             authentication.conf file,
1001
 
           - user: can't de different from the provided user if any,
 
1348
           - user: can't be different from the provided user if any,
 
1349
           - scheme: the server protocol,
 
1350
           - host: the server address,
 
1351
           - port: the server port (can be None),
 
1352
           - path: the absolute server path (can be None),
 
1353
           - realm: the http specific authentication realm (can be None),
1002
1354
           - password: the decoded password, could be None if the credential
1003
1355
             defines only the user
1004
1356
           - verify_certificates: https specific, True if the server
1006
1358
        """
1007
1359
        credentials = None
1008
1360
        for auth_def_name, auth_def in self._get_config().items():
 
1361
            if type(auth_def) is not configobj.Section:
 
1362
                raise ValueError("%s defined outside a section" % auth_def_name)
 
1363
 
1009
1364
            a_scheme, a_host, a_user, a_path = map(
1010
1365
                auth_def.get, ['scheme', 'host', 'user', 'path'])
1011
1366
 
1042
1397
            if a_user is None:
1043
1398
                # Can't find a user
1044
1399
                continue
 
1400
            # Prepare a credentials dictionary with additional keys
 
1401
            # for the credential providers
1045
1402
            credentials = dict(name=auth_def_name,
1046
 
                               user=a_user, password=auth_def['password'],
 
1403
                               user=a_user,
 
1404
                               scheme=a_scheme,
 
1405
                               host=host,
 
1406
                               port=port,
 
1407
                               path=path,
 
1408
                               realm=realm,
 
1409
                               password=auth_def.get('password', None),
1047
1410
                               verify_certificates=a_verify_certificates)
 
1411
            # Decode the password in the credentials (or get one)
1048
1412
            self.decode_password(credentials,
1049
1413
                                 auth_def.get('password_encoding', None))
1050
1414
            if 'auth' in debug.debug_flags:
1051
1415
                trace.mutter("Using authentication section: %r", auth_def_name)
1052
1416
            break
1053
1417
 
 
1418
        if credentials is None:
 
1419
            # No credentials were found in authentication.conf, try the fallback
 
1420
            # credentials stores.
 
1421
            credentials = credential_store_registry.get_fallback_credentials(
 
1422
                scheme, host, port, user, path, realm)
 
1423
 
1054
1424
        return credentials
1055
1425
 
1056
 
    def get_user(self, scheme, host, port=None,
1057
 
                 realm=None, path=None, prompt=None):
 
1426
    def set_credentials(self, name, host, user, scheme=None, password=None,
 
1427
                        port=None, path=None, verify_certificates=None,
 
1428
                        realm=None):
 
1429
        """Set authentication credentials for a host.
 
1430
 
 
1431
        Any existing credentials with matching scheme, host, port and path
 
1432
        will be deleted, regardless of name.
 
1433
 
 
1434
        :param name: An arbitrary name to describe this set of credentials.
 
1435
        :param host: Name of the host that accepts these credentials.
 
1436
        :param user: The username portion of these credentials.
 
1437
        :param scheme: The URL scheme (e.g. ssh, http) the credentials apply
 
1438
            to.
 
1439
        :param password: Password portion of these credentials.
 
1440
        :param port: The IP port on the host that these credentials apply to.
 
1441
        :param path: A filesystem path on the host that these credentials
 
1442
            apply to.
 
1443
        :param verify_certificates: On https, verify server certificates if
 
1444
            True.
 
1445
        :param realm: The http authentication realm (optional).
 
1446
        """
 
1447
        values = {'host': host, 'user': user}
 
1448
        if password is not None:
 
1449
            values['password'] = password
 
1450
        if scheme is not None:
 
1451
            values['scheme'] = scheme
 
1452
        if port is not None:
 
1453
            values['port'] = '%d' % port
 
1454
        if path is not None:
 
1455
            values['path'] = path
 
1456
        if verify_certificates is not None:
 
1457
            values['verify_certificates'] = str(verify_certificates)
 
1458
        if realm is not None:
 
1459
            values['realm'] = realm
 
1460
        config = self._get_config()
 
1461
        for_deletion = []
 
1462
        for section, existing_values in config.items():
 
1463
            for key in ('scheme', 'host', 'port', 'path', 'realm'):
 
1464
                if existing_values.get(key) != values.get(key):
 
1465
                    break
 
1466
            else:
 
1467
                del config[section]
 
1468
        config.update({name: values})
 
1469
        self._save()
 
1470
 
 
1471
    def get_user(self, scheme, host, port=None, realm=None, path=None,
 
1472
                 prompt=None, ask=False, default=None):
1058
1473
        """Get a user from authentication file.
1059
1474
 
1060
1475
        :param scheme: protocol
1067
1482
 
1068
1483
        :param path: the absolute path on the server (optional)
1069
1484
 
 
1485
        :param ask: Ask the user if there is no explicitly configured username 
 
1486
                    (optional)
 
1487
 
 
1488
        :param default: The username returned if none is defined (optional).
 
1489
 
1070
1490
        :return: The found user.
1071
1491
        """
1072
1492
        credentials = self.get_credentials(scheme, host, port, user=None,
1073
 
                                           path=path)
 
1493
                                           path=path, realm=realm)
1074
1494
        if credentials is not None:
1075
1495
            user = credentials['user']
1076
1496
        else:
1077
1497
            user = None
 
1498
        if user is None:
 
1499
            if ask:
 
1500
                if prompt is None:
 
1501
                    # Create a default prompt suitable for most cases
 
1502
                    prompt = scheme.upper() + ' %(host)s username'
 
1503
                # Special handling for optional fields in the prompt
 
1504
                if port is not None:
 
1505
                    prompt_host = '%s:%d' % (host, port)
 
1506
                else:
 
1507
                    prompt_host = host
 
1508
                user = ui.ui_factory.get_username(prompt, host=prompt_host)
 
1509
            else:
 
1510
                user = default
1078
1511
        return user
1079
1512
 
1080
1513
    def get_password(self, scheme, host, user, port=None,
1095
1528
 
1096
1529
        :return: The found password or the one entered by the user.
1097
1530
        """
1098
 
        credentials = self.get_credentials(scheme, host, port, user, path)
 
1531
        credentials = self.get_credentials(scheme, host, port, user, path,
 
1532
                                           realm)
1099
1533
        if credentials is not None:
1100
1534
            password = credentials['password']
 
1535
            if password is not None and scheme is 'ssh':
 
1536
                trace.warning('password ignored in section [%s],'
 
1537
                              ' use an ssh agent instead'
 
1538
                              % credentials['name'])
 
1539
                password = None
1101
1540
        else:
1102
1541
            password = None
1103
1542
        # Prompt user only if we could't find a password
1104
1543
        if password is None:
1105
1544
            if prompt is None:
1106
 
                # Create a default prompt suitable for most of the cases
 
1545
                # Create a default prompt suitable for most cases
1107
1546
                prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
1108
1547
            # Special handling for optional fields in the prompt
1109
1548
            if port is not None:
1115
1554
        return password
1116
1555
 
1117
1556
    def decode_password(self, credentials, encoding):
1118
 
        return credentials
 
1557
        try:
 
1558
            cs = credential_store_registry.get_credential_store(encoding)
 
1559
        except KeyError:
 
1560
            raise ValueError('%r is not a known password_encoding' % encoding)
 
1561
        credentials['password'] = cs.decode_password(credentials)
 
1562
        return credentials
 
1563
 
 
1564
 
 
1565
class CredentialStoreRegistry(registry.Registry):
 
1566
    """A class that registers credential stores.
 
1567
 
 
1568
    A credential store provides access to credentials via the password_encoding
 
1569
    field in authentication.conf sections.
 
1570
 
 
1571
    Except for stores provided by bzr itself, most stores are expected to be
 
1572
    provided by plugins that will therefore use
 
1573
    register_lazy(password_encoding, module_name, member_name, help=help,
 
1574
    fallback=fallback) to install themselves.
 
1575
 
 
1576
    A fallback credential store is one that is queried if no credentials can be
 
1577
    found via authentication.conf.
 
1578
    """
 
1579
 
 
1580
    def get_credential_store(self, encoding=None):
 
1581
        cs = self.get(encoding)
 
1582
        if callable(cs):
 
1583
            cs = cs()
 
1584
        return cs
 
1585
 
 
1586
    def is_fallback(self, name):
 
1587
        """Check if the named credentials store should be used as fallback."""
 
1588
        return self.get_info(name)
 
1589
 
 
1590
    def get_fallback_credentials(self, scheme, host, port=None, user=None,
 
1591
                                 path=None, realm=None):
 
1592
        """Request credentials from all fallback credentials stores.
 
1593
 
 
1594
        The first credentials store that can provide credentials wins.
 
1595
        """
 
1596
        credentials = None
 
1597
        for name in self.keys():
 
1598
            if not self.is_fallback(name):
 
1599
                continue
 
1600
            cs = self.get_credential_store(name)
 
1601
            credentials = cs.get_credentials(scheme, host, port, user,
 
1602
                                             path, realm)
 
1603
            if credentials is not None:
 
1604
                # We found some credentials
 
1605
                break
 
1606
        return credentials
 
1607
 
 
1608
    def register(self, key, obj, help=None, override_existing=False,
 
1609
                 fallback=False):
 
1610
        """Register a new object to a name.
 
1611
 
 
1612
        :param key: This is the key to use to request the object later.
 
1613
        :param obj: The object to register.
 
1614
        :param help: Help text for this entry. This may be a string or
 
1615
                a callable. If it is a callable, it should take two
 
1616
                parameters (registry, key): this registry and the key that
 
1617
                the help was registered under.
 
1618
        :param override_existing: Raise KeyErorr if False and something has
 
1619
                already been registered for that key. If True, ignore if there
 
1620
                is an existing key (always register the new value).
 
1621
        :param fallback: Whether this credential store should be 
 
1622
                used as fallback.
 
1623
        """
 
1624
        return super(CredentialStoreRegistry,
 
1625
                     self).register(key, obj, help, info=fallback,
 
1626
                                    override_existing=override_existing)
 
1627
 
 
1628
    def register_lazy(self, key, module_name, member_name,
 
1629
                      help=None, override_existing=False,
 
1630
                      fallback=False):
 
1631
        """Register a new credential store to be loaded on request.
 
1632
 
 
1633
        :param module_name: The python path to the module. Such as 'os.path'.
 
1634
        :param member_name: The member of the module to return.  If empty or
 
1635
                None, get() will return the module itself.
 
1636
        :param help: Help text for this entry. This may be a string or
 
1637
                a callable.
 
1638
        :param override_existing: If True, replace the existing object
 
1639
                with the new one. If False, if there is already something
 
1640
                registered with the same key, raise a KeyError
 
1641
        :param fallback: Whether this credential store should be 
 
1642
                used as fallback.
 
1643
        """
 
1644
        return super(CredentialStoreRegistry, self).register_lazy(
 
1645
            key, module_name, member_name, help,
 
1646
            info=fallback, override_existing=override_existing)
 
1647
 
 
1648
 
 
1649
credential_store_registry = CredentialStoreRegistry()
 
1650
 
 
1651
 
 
1652
class CredentialStore(object):
 
1653
    """An abstract class to implement storage for credentials"""
 
1654
 
 
1655
    def decode_password(self, credentials):
 
1656
        """Returns a clear text password for the provided credentials."""
 
1657
        raise NotImplementedError(self.decode_password)
 
1658
 
 
1659
    def get_credentials(self, scheme, host, port=None, user=None, path=None,
 
1660
                        realm=None):
 
1661
        """Return the matching credentials from this credential store.
 
1662
 
 
1663
        This method is only called on fallback credential stores.
 
1664
        """
 
1665
        raise NotImplementedError(self.get_credentials)
 
1666
 
 
1667
 
 
1668
 
 
1669
class PlainTextCredentialStore(CredentialStore):
 
1670
    __doc__ = """Plain text credential store for the authentication.conf file"""
 
1671
 
 
1672
    def decode_password(self, credentials):
 
1673
        """See CredentialStore.decode_password."""
 
1674
        return credentials['password']
 
1675
 
 
1676
 
 
1677
credential_store_registry.register('plain', PlainTextCredentialStore,
 
1678
                                   help=PlainTextCredentialStore.__doc__)
 
1679
credential_store_registry.default_key = 'plain'
 
1680
 
 
1681
 
 
1682
class BzrDirConfig(object):
 
1683
 
 
1684
    def __init__(self, bzrdir):
 
1685
        self._bzrdir = bzrdir
 
1686
        self._config = bzrdir._get_config()
 
1687
 
 
1688
    def set_default_stack_on(self, value):
 
1689
        """Set the default stacking location.
 
1690
 
 
1691
        It may be set to a location, or None.
 
1692
 
 
1693
        This policy affects all branches contained by this bzrdir, except for
 
1694
        those under repositories.
 
1695
        """
 
1696
        if self._config is None:
 
1697
            raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
 
1698
        if value is None:
 
1699
            self._config.set_option('', 'default_stack_on')
 
1700
        else:
 
1701
            self._config.set_option(value, 'default_stack_on')
 
1702
 
 
1703
    def get_default_stack_on(self):
 
1704
        """Return the default stacking location.
 
1705
 
 
1706
        This will either be a location, or None.
 
1707
 
 
1708
        This policy affects all branches contained by this bzrdir, except for
 
1709
        those under repositories.
 
1710
        """
 
1711
        if self._config is None:
 
1712
            return None
 
1713
        value = self._config.get_option('default_stack_on')
 
1714
        if value == '':
 
1715
            value = None
 
1716
        return value
 
1717
 
 
1718
 
 
1719
class TransportConfig(object):
 
1720
    """A Config that reads/writes a config file on a Transport.
 
1721
 
 
1722
    It is a low-level object that considers config data to be name/value pairs
 
1723
    that may be associated with a section.  Assigning meaning to these values
 
1724
    is done at higher levels like TreeConfig.
 
1725
    """
 
1726
 
 
1727
    def __init__(self, transport, filename):
 
1728
        self._transport = transport
 
1729
        self._filename = filename
 
1730
 
 
1731
    def get_option(self, name, section=None, default=None):
 
1732
        """Return the value associated with a named option.
 
1733
 
 
1734
        :param name: The name of the value
 
1735
        :param section: The section the option is in (if any)
 
1736
        :param default: The value to return if the value is not set
 
1737
        :return: The value or default value
 
1738
        """
 
1739
        configobj = self._get_configobj()
 
1740
        if section is None:
 
1741
            section_obj = configobj
 
1742
        else:
 
1743
            try:
 
1744
                section_obj = configobj[section]
 
1745
            except KeyError:
 
1746
                return default
 
1747
        return section_obj.get(name, default)
 
1748
 
 
1749
    def set_option(self, value, name, section=None):
 
1750
        """Set the value associated with a named option.
 
1751
 
 
1752
        :param value: The value to set
 
1753
        :param name: The name of the value to set
 
1754
        :param section: The section the option is in (if any)
 
1755
        """
 
1756
        configobj = self._get_configobj()
 
1757
        if section is None:
 
1758
            configobj[name] = value
 
1759
        else:
 
1760
            configobj.setdefault(section, {})[name] = value
 
1761
        self._set_configobj(configobj)
 
1762
 
 
1763
    def remove_option(self, option_name, section_name=None):
 
1764
        configobj = self._get_configobj()
 
1765
        if section_name is None:
 
1766
            del configobj[option_name]
 
1767
        else:
 
1768
            del configobj[section_name][option_name]
 
1769
        self._set_configobj(configobj)
 
1770
 
 
1771
    def _get_config_file(self):
 
1772
        try:
 
1773
            return StringIO(self._transport.get_bytes(self._filename))
 
1774
        except errors.NoSuchFile:
 
1775
            return StringIO()
 
1776
 
 
1777
    def _get_configobj(self):
 
1778
        f = self._get_config_file()
 
1779
        try:
 
1780
            return ConfigObj(f, encoding='utf-8')
 
1781
        finally:
 
1782
            f.close()
 
1783
 
 
1784
    def _set_configobj(self, configobj):
 
1785
        out_file = StringIO()
 
1786
        configobj.write(out_file)
 
1787
        out_file.seek(0)
 
1788
        self._transport.put_file(self._filename, out_file)
 
1789
 
 
1790
 
 
1791
class cmd_config(commands.Command):
 
1792
    __doc__ = """Display, set or remove a configuration option.
 
1793
 
 
1794
    Display the active value for a given option.
 
1795
 
 
1796
    If --all is specified, NAME is interpreted as a regular expression and all
 
1797
    matching options are displayed mentioning their scope. The active value
 
1798
    that bzr will take into account is the first one displayed for each option.
 
1799
 
 
1800
    If no NAME is given, --all .* is implied.
 
1801
 
 
1802
    Setting a value is achieved by using name=value without spaces. The value
 
1803
    is set in the most relevant scope and can be checked by displaying the
 
1804
    option again.
 
1805
    """
 
1806
 
 
1807
    takes_args = ['name?']
 
1808
 
 
1809
    takes_options = [
 
1810
        'directory',
 
1811
        # FIXME: This should be a registry option so that plugins can register
 
1812
        # their own config files (or not) -- vila 20101002
 
1813
        commands.Option('scope', help='Reduce the scope to the specified'
 
1814
                        ' configuration file',
 
1815
                        type=unicode),
 
1816
        commands.Option('all',
 
1817
            help='Display all the defined values for the matching options.',
 
1818
            ),
 
1819
        commands.Option('remove', help='Remove the option from'
 
1820
                        ' the configuration file'),
 
1821
        ]
 
1822
 
 
1823
    @commands.display_command
 
1824
    def run(self, name=None, all=False, directory=None, scope=None,
 
1825
            remove=False):
 
1826
        if directory is None:
 
1827
            directory = '.'
 
1828
        directory = urlutils.normalize_url(directory)
 
1829
        if remove and all:
 
1830
            raise errors.BzrError(
 
1831
                '--all and --remove are mutually exclusive.')
 
1832
        elif remove:
 
1833
            # Delete the option in the given scope
 
1834
            self._remove_config_option(name, directory, scope)
 
1835
        elif name is None:
 
1836
            # Defaults to all options
 
1837
            self._show_matching_options('.*', directory, scope)
 
1838
        else:
 
1839
            try:
 
1840
                name, value = name.split('=', 1)
 
1841
            except ValueError:
 
1842
                # Display the option(s) value(s)
 
1843
                if all:
 
1844
                    self._show_matching_options(name, directory, scope)
 
1845
                else:
 
1846
                    self._show_value(name, directory, scope)
 
1847
            else:
 
1848
                if all:
 
1849
                    raise errors.BzrError(
 
1850
                        'Only one option can be set.')
 
1851
                # Set the option value
 
1852
                self._set_config_option(name, value, directory, scope)
 
1853
 
 
1854
    def _get_configs(self, directory, scope=None):
 
1855
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
1856
 
 
1857
        :param directory: Where the configurations are derived from.
 
1858
 
 
1859
        :param scope: A specific config to start from.
 
1860
        """
 
1861
        if scope is not None:
 
1862
            if scope == 'bazaar':
 
1863
                yield GlobalConfig()
 
1864
            elif scope == 'locations':
 
1865
                yield LocationConfig(directory)
 
1866
            elif scope == 'branch':
 
1867
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1868
                    directory)
 
1869
                yield br.get_config()
 
1870
        else:
 
1871
            try:
 
1872
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1873
                    directory)
 
1874
                yield br.get_config()
 
1875
            except errors.NotBranchError:
 
1876
                yield LocationConfig(directory)
 
1877
                yield GlobalConfig()
 
1878
 
 
1879
    def _show_value(self, name, directory, scope):
 
1880
        displayed = False
 
1881
        for c in self._get_configs(directory, scope):
 
1882
            if displayed:
 
1883
                break
 
1884
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1885
                if name == oname:
 
1886
                    # Display only the first value and exit
 
1887
 
 
1888
                    # FIXME: We need to use get_user_option to take policies
 
1889
                    # into account and we need to make sure the option exists
 
1890
                    # too (hence the two for loops), this needs a better API
 
1891
                    # -- vila 20101117
 
1892
                    value = c.get_user_option(name)
 
1893
                    # Quote the value appropriately
 
1894
                    value = parser._quote(value)
 
1895
                    self.outf.write('%s\n' % (value,))
 
1896
                    displayed = True
 
1897
                    break
 
1898
        if not displayed:
 
1899
            raise errors.NoSuchConfigOption(name)
 
1900
 
 
1901
    def _show_matching_options(self, name, directory, scope):
 
1902
        name = re.compile(name)
 
1903
        # We want any error in the regexp to be raised *now* so we need to
 
1904
        # avoid the delay introduced by the lazy regexp.
 
1905
        name._compile_and_collapse()
 
1906
        cur_conf_id = None
 
1907
        cur_section = None
 
1908
        for c in self._get_configs(directory, scope):
 
1909
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1910
                if name.search(oname):
 
1911
                    if cur_conf_id != conf_id:
 
1912
                        # Explain where the options are defined
 
1913
                        self.outf.write('%s:\n' % (conf_id,))
 
1914
                        cur_conf_id = conf_id
 
1915
                        cur_section = None
 
1916
                    if (section not in (None, 'DEFAULT')
 
1917
                        and cur_section != section):
 
1918
                        # Display the section if it's not the default (or only)
 
1919
                        # one.
 
1920
                        self.outf.write('  [%s]\n' % (section,))
 
1921
                        cur_section = section
 
1922
                    self.outf.write('  %s = %s\n' % (oname, value))
 
1923
 
 
1924
    def _set_config_option(self, name, value, directory, scope):
 
1925
        for conf in self._get_configs(directory, scope):
 
1926
            conf.set_user_option(name, value)
 
1927
            break
 
1928
        else:
 
1929
            raise errors.NoSuchConfig(scope)
 
1930
 
 
1931
    def _remove_config_option(self, name, directory, scope):
 
1932
        if name is None:
 
1933
            raise errors.BzrCommandError(
 
1934
                '--remove expects an option to remove.')
 
1935
        removed = False
 
1936
        for conf in self._get_configs(directory, scope):
 
1937
            for (section_name, section, conf_id) in conf._get_sections():
 
1938
                if scope is not None and conf_id != scope:
 
1939
                    # Not the right configuration file
 
1940
                    continue
 
1941
                if name in section:
 
1942
                    if conf_id != conf.config_id():
 
1943
                        conf = self._get_configs(directory, conf_id).next()
 
1944
                    # We use the first section in the first config where the
 
1945
                    # option is defined to remove it
 
1946
                    conf.remove_user_option(name, section_name)
 
1947
                    removed = True
 
1948
                    break
 
1949
            break
 
1950
        else:
 
1951
            raise errors.NoSuchConfig(scope)
 
1952
        if not removed:
 
1953
            raise errors.NoSuchConfigOption(name)