~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-31 16:12:57 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060731161257-91a231523255332c
new official bzr.ico

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
from bzrlib import errors, urlutils
 
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."""
447
374
            location = urlutils.local_path_from_url(location)
448
375
        self.location = location
449
376
 
450
 
    def _get_matching_sections(self):
451
 
        """Return an ordered list of section names matching this location."""
 
377
    def _get_section(self):
 
378
        """Get the section we should look in for config items.
 
379
 
 
380
        Returns None if none exists. 
 
381
        TODO: perhaps return a NullSection that thunks through to the 
 
382
              global config.
 
383
        """
452
384
        sections = self._get_parser()
453
385
        location_names = self.location.split('/')
454
386
        if self.location.endswith('/'):
478
410
            # if section is longer, no match.
479
411
            if len(section_names) > len(location_names):
480
412
                continue
481
 
            matches.append((len(section_names), section,
482
 
                            '/'.join(location_names[len(section_names):])))
 
413
            # if path is longer, and recurse is not true, no match
 
414
            if len(section_names) < len(location_names):
 
415
                try:
 
416
                    if not self._get_parser()[section].as_bool('recurse'):
 
417
                        continue
 
418
                except KeyError:
 
419
                    pass
 
420
            matches.append((len(section_names), section))
 
421
        if not len(matches):
 
422
            return None
483
423
        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):
 
424
        return matches[0][1]
 
425
 
 
426
    def set_user_option(self, option, value):
544
427
        """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
428
        # FIXME: RBC 20051029 This should refresh the parser and also take a
549
429
        # file lock on locations.conf.
550
430
        conf_dir = os.path.dirname(self._get_filename())
558
438
        elif location + '/' in self._get_parser():
559
439
            location = location + '/'
560
440
        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
441
        self._get_parser().write(file(self._get_filename(), 'wb'))
564
442
 
565
443
 
640
518
                return value
641
519
        return None
642
520
 
643
 
    def set_user_option(self, name, value, store=STORE_BRANCH,
644
 
        warn_masked=False):
645
 
        if store == STORE_BRANCH:
 
521
    def set_user_option(self, name, value, local=False):
 
522
        if local is True:
 
523
            self._get_location_config().set_user_option(name, value)
 
524
        else:
646
525
            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
526
 
666
527
 
667
528
    def _gpg_signing_command(self):
686
547
        value = self._get_explicit_nickname()
687
548
        if value is not None:
688
549
            return value
689
 
        return urlutils.unescape(self.branch.base.split('/')[-2])
 
550
        return self.branch.base.split('/')[-2]
690
551
 
691
552
    def has_explicit_nickname(self):
692
553
        """Return true if a nickname has been explicitly assigned."""
728
589
    base = os.environ.get('BZR_HOME', None)
729
590
    if sys.platform == 'win32':
730
591
        if base is None:
731
 
            base = win32utils.get_appdata_location_unicode()
 
592
            base = os.environ.get('APPDATA', None)
732
593
        if base is None:
733
594
            base = os.environ.get('HOME', None)
734
595
        if base is None:
735
596
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
736
 
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
597
        return pathjoin(base, 'bazaar', '2.0')
737
598
    else:
738
599
        # cygwin, linux, and darwin all have a $HOME directory
739
600
        if base is None:
740
601
            base = os.path.expanduser("~")
741
 
        return osutils.pathjoin(base, ".bazaar")
 
602
        return pathjoin(base, ".bazaar")
742
603
 
743
604
 
744
605
def config_filename():
745
606
    """Return per-user configuration ini file filename."""
746
 
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
 
607
    return pathjoin(config_dir(), 'bazaar.conf')
747
608
 
748
609
 
749
610
def branches_config_filename():
750
611
    """Return per-user configuration ini file filename."""
751
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
 
612
    return pathjoin(config_dir(), 'branches.conf')
752
613
 
753
614
 
754
615
def locations_config_filename():
755
616
    """Return per-user configuration ini file filename."""
756
 
    return osutils.pathjoin(config_dir(), 'locations.conf')
 
617
    return pathjoin(config_dir(), 'locations.conf')
757
618
 
758
619
 
759
620
def user_ignore_config_filename():
760
621
    """Return the user default ignore filename"""
761
 
    return osutils.pathjoin(config_dir(), 'ignore')
 
622
    return pathjoin(config_dir(), 'ignore')
762
623
 
763
624
 
764
625
def _auto_user_id():
774
635
    """
775
636
    import socket
776
637
 
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)
 
638
    # XXX: Any good way to get real user name on win32?
787
639
 
788
640
    try:
789
641
        import pwd
841
693
    """
842
694
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
843
695
    if not m:
844
 
        raise errors.NoEmailInUsername(e)
 
696
        raise errors.BzrError("%r doesn't seem to contain "
 
697
                              "a reasonable email address" % e)
845
698
    return m.group(0)
846
699
 
847
700
 
857
710
 
858
711
    def _get_config(self):
859
712
        try:
860
 
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),
 
713
            obj = ConfigObj(self.branch.control_files.get('branch.conf'), 
861
714
                            encoding='utf-8')
862
715
        except errors.NoSuchFile:
863
716
            obj = ConfigObj(encoding='utf=8')
869
722
            obj = self._get_config()
870
723
            try:
871
724
                if section is not None:
872
 
                    obj = obj[section]
 
725
                    obj[section]
873
726
                result = obj[name]
874
727
            except KeyError:
875
728
                result = default