~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-07-06 03:15:29 UTC
  • mfrom: (1711.2.78 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060706031529-e189d8c3f42076be
(jam) allow plugins to include benchmarks

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
 
#            and others
4
3
#
5
4
# This program is free software; you can redistribute it and/or modify
6
5
# it under the terms of the GNU General Public License as published by
50
49
create_signatures - this option controls whether bzr will always create 
51
50
                    gpg signatures, never create them, or create them if the
52
51
                    branch is configured to require them.
53
 
log_format - this option sets the default log format.  Possible values are
54
 
             long, short, line, or a plugin can register new formats.
 
52
log_format - This options set the default log format.  Options are long, 
 
53
             short, line, or a plugin can register new formats
55
54
 
56
55
In bazaar.conf you can also define aliases in the ALIASES sections, example
57
56
 
62
61
up=pull
63
62
"""
64
63
 
65
 
import os
66
 
import sys
67
64
 
68
 
from bzrlib.lazy_import import lazy_import
69
 
lazy_import(globals(), """
70
65
import errno
71
66
from fnmatch import fnmatch
 
67
import os
72
68
import re
 
69
import sys
73
70
from StringIO import StringIO
74
71
 
75
72
import bzrlib
76
 
from bzrlib import (
77
 
    errors,
78
 
    osutils,
79
 
    symbol_versioning,
80
 
    trace,
81
 
    urlutils,
82
 
    win32utils,
83
 
    )
 
73
import bzrlib.errors as errors
 
74
from bzrlib.osutils import pathjoin
 
75
from bzrlib.trace import mutter, warning
84
76
import bzrlib.util.configobj.configobj as configobj
85
 
""")
86
 
 
87
 
from bzrlib.trace import mutter, warning
88
77
 
89
78
 
90
79
CHECK_IF_POSSIBLE=0
97
86
SIGN_NEVER=2
98
87
 
99
88
 
100
 
POLICY_NONE = 0
101
 
POLICY_NORECURSE = 1
102
 
POLICY_APPENDPATH = 2
103
 
 
104
 
_policy_name = {
105
 
    POLICY_NONE: None,
106
 
    POLICY_NORECURSE: 'norecurse',
107
 
    POLICY_APPENDPATH: 'appendpath',
108
 
    }
109
 
_policy_value = {
110
 
    None: POLICY_NONE,
111
 
    'none': POLICY_NONE,
112
 
    'norecurse': POLICY_NORECURSE,
113
 
    'appendpath': POLICY_APPENDPATH,
114
 
    }
115
 
 
116
 
 
117
 
STORE_LOCATION = POLICY_NONE
118
 
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
119
 
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
120
 
STORE_BRANCH = 3
121
 
STORE_GLOBAL = 4
122
 
 
123
 
 
124
89
class ConfigObj(configobj.ConfigObj):
125
90
 
126
91
    def get_bool(self, section, key):
202
167
    
203
168
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
204
169
        
205
 
        $BZR_EMAIL can be set to override this (as well as the
206
 
        deprecated $BZREMAIL), then
 
170
        $BZREMAIL can be set to override this, then
207
171
        the concrete policy type is checked, and finally
208
172
        $EMAIL is examined.
209
173
        If none is found, a reasonable default is (hopefully)
211
175
    
212
176
        TODO: Check it's reasonably well-formed.
213
177
        """
214
 
        v = os.environ.get('BZR_EMAIL')
215
 
        if v:
216
 
            return v.decode(bzrlib.user_encoding)
217
178
        v = os.environ.get('BZREMAIL')
218
179
        if v:
219
 
            warning('BZREMAIL is deprecated in favor of BZR_EMAIL. Please update your configuration.')
220
180
            return v.decode(bzrlib.user_encoding)
221
181
    
222
182
        v = self._get_user_id()
290
250
            raise errors.ParseConfigError(e.errors, e.config.filename)
291
251
        return self._parser
292
252
 
293
 
    def _get_matching_sections(self):
294
 
        """Return an ordered list of (section_name, extra_path) pairs.
295
 
 
296
 
        If the section contains inherited configuration, extra_path is
297
 
        a string containing the additional path components.
298
 
        """
299
 
        section = self._get_section()
300
 
        if section is not None:
301
 
            return [(section, '')]
302
 
        else:
303
 
            return []
304
 
 
305
253
    def _get_section(self):
306
254
        """Override this to define the section used by the config."""
307
255
        return "DEFAULT"
308
256
 
309
 
    def _get_option_policy(self, section, option_name):
310
 
        """Return the policy for the given (section, option_name) pair."""
311
 
        return POLICY_NONE
312
 
 
313
257
    def _get_signature_checking(self):
314
258
        """See Config._get_signature_checking."""
315
259
        policy = self._get_user_option('check_signatures')
328
272
 
329
273
    def _get_user_option(self, option_name):
330
274
        """See Config._get_user_option."""
331
 
        for (section, extra_path) in self._get_matching_sections():
332
 
            try:
333
 
                value = self._get_parser().get_value(section, option_name)
334
 
            except KeyError:
335
 
                continue
336
 
            policy = self._get_option_policy(section, option_name)
337
 
            if policy == POLICY_NONE:
338
 
                return value
339
 
            elif policy == POLICY_NORECURSE:
340
 
                # norecurse items only apply to the exact path
341
 
                if extra_path:
342
 
                    continue
343
 
                else:
344
 
                    return value
345
 
            elif policy == POLICY_APPENDPATH:
346
 
                if extra_path:
347
 
                    value = urlutils.join(value, extra_path)
348
 
                return value
349
 
            else:
350
 
                raise AssertionError('Unexpected config policy %r' % policy)
351
 
        else:
352
 
            return None
 
275
        try:
 
276
            return self._get_parser().get_value(self._get_section(),
 
277
                                                option_name)
 
278
        except KeyError:
 
279
            pass
353
280
 
354
281
    def _gpg_signing_command(self):
355
282
        """See Config.gpg_signing_command."""
440
367
                        ' to ~/.bazaar/locations.conf')
441
368
            name_generator = branches_config_filename
442
369
        super(LocationConfig, self).__init__(name_generator)
443
 
        # local file locations are looked up by local path, rather than
444
 
        # by file url. This is because the config file is a user
445
 
        # file, and we would rather not expose the user to file urls.
446
 
        if location.startswith('file://'):
447
 
            location = urlutils.local_path_from_url(location)
448
370
        self.location = location
449
371
 
450
 
    def _get_matching_sections(self):
451
 
        """Return an ordered list of section names matching this location."""
 
372
    def _get_section(self):
 
373
        """Get the section we should look in for config items.
 
374
 
 
375
        Returns None if none exists. 
 
376
        TODO: perhaps return a NullSection that thunks through to the 
 
377
              global config.
 
378
        """
452
379
        sections = self._get_parser()
453
380
        location_names = self.location.split('/')
454
381
        if self.location.endswith('/'):
455
382
            del location_names[-1]
456
383
        matches=[]
457
384
        for section in sections:
458
 
            # location is a local path if possible, so we need
459
 
            # to convert 'file://' urls to local paths if necessary.
460
 
            # This also avoids having file:///path be a more exact
461
 
            # match than '/path'.
462
 
            if section.startswith('file://'):
463
 
                section_path = urlutils.local_path_from_url(section)
464
 
            else:
465
 
                section_path = section
466
 
            section_names = section_path.split('/')
 
385
            section_names = section.split('/')
467
386
            if section.endswith('/'):
468
387
                del section_names[-1]
469
388
            names = zip(location_names, section_names)
478
397
            # if section is longer, no match.
479
398
            if len(section_names) > len(location_names):
480
399
                continue
481
 
            matches.append((len(section_names), section,
482
 
                            '/'.join(location_names[len(section_names):])))
 
400
            # if path is longer, and recurse is not true, no match
 
401
            if len(section_names) < len(location_names):
 
402
                try:
 
403
                    if not self._get_parser()[section].as_bool('recurse'):
 
404
                        continue
 
405
                except KeyError:
 
406
                    pass
 
407
            matches.append((len(section_names), section))
 
408
        if not len(matches):
 
409
            return None
483
410
        matches.sort(reverse=True)
484
 
        sections = []
485
 
        for (length, section, extra_path) in matches:
486
 
            sections.append((section, extra_path))
487
 
            # should we stop looking for parent configs here?
488
 
            try:
489
 
                if self._get_parser()[section].as_bool('ignore_parents'):
490
 
                    break
491
 
            except KeyError:
492
 
                pass
493
 
        return sections
494
 
 
495
 
    def _get_option_policy(self, section, option_name):
496
 
        """Return the policy for the given (section, option_name) pair."""
497
 
        # check for the old 'recurse=False' flag
498
 
        try:
499
 
            recurse = self._get_parser()[section].as_bool('recurse')
500
 
        except KeyError:
501
 
            recurse = True
502
 
        if not recurse:
503
 
            return POLICY_NORECURSE
504
 
 
505
 
        policy_key = option_name + ':policy'
506
 
        try:
507
 
            policy_name = self._get_parser()[section][policy_key]
508
 
        except KeyError:
509
 
            policy_name = None
510
 
 
511
 
        return _policy_value[policy_name]
512
 
 
513
 
    def _set_option_policy(self, section, option_name, option_policy):
514
 
        """Set the policy for the given option name in the given section."""
515
 
        # The old recurse=False option affects all options in the
516
 
        # section.  To handle multiple policies in the section, we
517
 
        # need to convert it to a policy_norecurse key.
518
 
        try:
519
 
            recurse = self._get_parser()[section].as_bool('recurse')
520
 
        except KeyError:
521
 
            pass
522
 
        else:
523
 
            symbol_versioning.warn(
524
 
                'The recurse option is deprecated as of 0.14.  '
525
 
                'The section "%s" has been converted to use policies.'
526
 
                % section,
527
 
                DeprecationWarning)
528
 
            del self._get_parser()[section]['recurse']
529
 
            if not recurse:
530
 
                for key in self._get_parser()[section].keys():
531
 
                    if not key.endswith(':policy'):
532
 
                        self._get_parser()[section][key +
533
 
                                                    ':policy'] = 'norecurse'
534
 
 
535
 
        policy_key = option_name + ':policy'
536
 
        policy_name = _policy_name[option_policy]
537
 
        if policy_name is not None:
538
 
            self._get_parser()[section][policy_key] = policy_name
539
 
        else:
540
 
            if policy_key in self._get_parser()[section]:
541
 
                del self._get_parser()[section][policy_key]
542
 
 
543
 
    def set_user_option(self, option, value, store=STORE_LOCATION):
 
411
        return matches[0][1]
 
412
 
 
413
    def set_user_option(self, option, value):
544
414
        """Save option and its value in the configuration."""
545
 
        assert store in [STORE_LOCATION,
546
 
                         STORE_LOCATION_NORECURSE,
547
 
                         STORE_LOCATION_APPENDPATH], 'bad storage policy'
548
415
        # FIXME: RBC 20051029 This should refresh the parser and also take a
549
416
        # file lock on locations.conf.
550
417
        conf_dir = os.path.dirname(self._get_filename())
558
425
        elif location + '/' in self._get_parser():
559
426
            location = location + '/'
560
427
        self._get_parser()[location][option]=value
561
 
        # the allowed values of store match the config policies
562
 
        self._set_option_policy(location, option, store)
563
428
        self._get_parser().write(file(self._get_filename(), 'wb'))
564
429
 
565
430
 
640
505
                return value
641
506
        return None
642
507
 
643
 
    def set_user_option(self, name, value, store=STORE_BRANCH,
644
 
        warn_masked=False):
645
 
        if store == STORE_BRANCH:
 
508
    def set_user_option(self, name, value, local=False):
 
509
        if local is True:
 
510
            self._get_location_config().set_user_option(name, value)
 
511
        else:
646
512
            self._get_branch_data_config().set_option(value, name)
647
 
        elif store == STORE_GLOBAL:
648
 
            self._get_global_config().set_user_option(name, value)
649
 
        else:
650
 
            self._get_location_config().set_user_option(name, value, store)
651
 
        if not warn_masked:
652
 
            return
653
 
        if store in (STORE_GLOBAL, STORE_BRANCH):
654
 
            mask_value = self._get_location_config().get_user_option(name)
655
 
            if mask_value is not None:
656
 
                trace.warning('Value "%s" is masked by "%s" from'
657
 
                              ' locations.conf', value, mask_value)
658
 
            else:
659
 
                if store == STORE_GLOBAL:
660
 
                    branch_config = self._get_branch_data_config()
661
 
                    mask_value = branch_config.get_user_option(name)
662
 
                    if mask_value is not None:
663
 
                        trace.warning('Value "%s" is masked by "%s" from'
664
 
                                      ' branch.conf', value, mask_value)
665
513
 
666
514
 
667
515
    def _gpg_signing_command(self):
686
534
        value = self._get_explicit_nickname()
687
535
        if value is not None:
688
536
            return value
689
 
        return urlutils.unescape(self.branch.base.split('/')[-2])
 
537
        return self.branch.base.split('/')[-2]
690
538
 
691
539
    def has_explicit_nickname(self):
692
540
        """Return true if a nickname has been explicitly assigned."""
728
576
    base = os.environ.get('BZR_HOME', None)
729
577
    if sys.platform == 'win32':
730
578
        if base is None:
731
 
            base = win32utils.get_appdata_location_unicode()
 
579
            base = os.environ.get('APPDATA', None)
732
580
        if base is None:
733
581
            base = os.environ.get('HOME', None)
734
582
        if base is None:
735
583
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
736
 
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
584
        return pathjoin(base, 'bazaar', '2.0')
737
585
    else:
738
586
        # cygwin, linux, and darwin all have a $HOME directory
739
587
        if base is None:
740
588
            base = os.path.expanduser("~")
741
 
        return osutils.pathjoin(base, ".bazaar")
 
589
        return pathjoin(base, ".bazaar")
742
590
 
743
591
 
744
592
def config_filename():
745
593
    """Return per-user configuration ini file filename."""
746
 
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
 
594
    return pathjoin(config_dir(), 'bazaar.conf')
747
595
 
748
596
 
749
597
def branches_config_filename():
750
598
    """Return per-user configuration ini file filename."""
751
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
 
599
    return pathjoin(config_dir(), 'branches.conf')
752
600
 
753
601
 
754
602
def locations_config_filename():
755
603
    """Return per-user configuration ini file filename."""
756
 
    return osutils.pathjoin(config_dir(), 'locations.conf')
757
 
 
758
 
 
759
 
def user_ignore_config_filename():
760
 
    """Return the user default ignore filename"""
761
 
    return osutils.pathjoin(config_dir(), 'ignore')
 
604
    return pathjoin(config_dir(), 'locations.conf')
762
605
 
763
606
 
764
607
def _auto_user_id():
774
617
    """
775
618
    import socket
776
619
 
777
 
    if sys.platform == 'win32':
778
 
        name = win32utils.get_user_name_unicode()
779
 
        if name is None:
780
 
            raise errors.BzrError("Cannot autodetect user name.\n"
781
 
                                  "Please, set your name with command like:\n"
782
 
                                  'bzr whoami "Your Name <name@domain.com>"')
783
 
        host = win32utils.get_host_name_unicode()
784
 
        if host is None:
785
 
            host = socket.gethostname()
786
 
        return name, (name + '@' + host)
 
620
    # XXX: Any good way to get real user name on win32?
787
621
 
788
622
    try:
789
623
        import pwd
841
675
    """
842
676
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
843
677
    if not m:
844
 
        raise errors.NoEmailInUsername(e)
 
678
        raise errors.BzrError("%r doesn't seem to contain "
 
679
                              "a reasonable email address" % e)
845
680
    return m.group(0)
846
681
 
847
682
 
857
692
 
858
693
    def _get_config(self):
859
694
        try:
860
 
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),
 
695
            obj = ConfigObj(self.branch.control_files.get('branch.conf'), 
861
696
                            encoding='utf-8')
862
697
        except errors.NoSuchFile:
863
698
            obj = ConfigObj(encoding='utf=8')
869
704
            obj = self._get_config()
870
705
            try:
871
706
                if section is not None:
872
 
                    obj = obj[section]
 
707
                    obj[section]
873
708
                result = obj[name]
874
709
            except KeyError:
875
710
                result = default