~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-08-17 07:52:09 UTC
  • mfrom: (1910.3.4 trivial)
  • Revision ID: pqm@pqm.ubuntu.com-20060817075209-e85a1f9e05ff8b87
(andrew) Trivial fixes to NotImplemented errors.

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
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
 
    mail_client,
79
 
    osutils,
80
 
    symbol_versioning,
81
 
    trace,
82
 
    urlutils,
83
 
    win32utils,
84
 
    )
 
73
from bzrlib import errors, urlutils
 
74
from bzrlib.osutils import pathjoin
 
75
from bzrlib.trace import mutter, warning
85
76
import bzrlib.util.configobj.configobj as configobj
86
 
""")
87
 
 
88
 
from bzrlib.trace import mutter, warning
89
77
 
90
78
 
91
79
CHECK_IF_POSSIBLE=0
98
86
SIGN_NEVER=2
99
87
 
100
88
 
101
 
POLICY_NONE = 0
102
 
POLICY_NORECURSE = 1
103
 
POLICY_APPENDPATH = 2
104
 
 
105
 
_policy_name = {
106
 
    POLICY_NONE: None,
107
 
    POLICY_NORECURSE: 'norecurse',
108
 
    POLICY_APPENDPATH: 'appendpath',
109
 
    }
110
 
_policy_value = {
111
 
    None: POLICY_NONE,
112
 
    'none': POLICY_NONE,
113
 
    'norecurse': POLICY_NORECURSE,
114
 
    'appendpath': POLICY_APPENDPATH,
115
 
    }
116
 
 
117
 
 
118
 
STORE_LOCATION = POLICY_NONE
119
 
STORE_LOCATION_NORECURSE = POLICY_NORECURSE
120
 
STORE_LOCATION_APPENDPATH = POLICY_APPENDPATH
121
 
STORE_BRANCH = 3
122
 
STORE_GLOBAL = 4
123
 
 
124
 
 
125
89
class ConfigObj(configobj.ConfigObj):
126
90
 
127
91
    def get_bool(self, section, key):
144
108
        """Get the users pop up editor."""
145
109
        raise NotImplementedError
146
110
 
147
 
    def get_mail_client(self):
148
 
        """Get a mail client to use"""
149
 
        selected_client = self.get_user_option('mail_client')
150
 
        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]
164
 
        except KeyError:
165
 
            raise errors.UnknownMailClient(selected_client)
166
 
        return mail_client_class(self)
167
 
 
168
111
    def _get_signature_checking(self):
169
112
        """Template method to override signature checking policy."""
170
113
 
295
238
    def _get_nickname(self):
296
239
        return None
297
240
 
298
 
    def get_bzr_remote_path(self):
299
 
        try:
300
 
            return os.environ['BZR_REMOTE_PATH']
301
 
        except KeyError:
302
 
            path = self.get_user_option("bzr_remote_path")
303
 
            if path is None:
304
 
                path = 'bzr'
305
 
            return path
306
 
 
307
241
 
308
242
class IniBasedConfig(Config):
309
243
    """A configuration policy that draws from ini files."""
321
255
            raise errors.ParseConfigError(e.errors, e.config.filename)
322
256
        return self._parser
323
257
 
324
 
    def _get_matching_sections(self):
325
 
        """Return an ordered list of (section_name, extra_path) pairs.
326
 
 
327
 
        If the section contains inherited configuration, extra_path is
328
 
        a string containing the additional path components.
329
 
        """
330
 
        section = self._get_section()
331
 
        if section is not None:
332
 
            return [(section, '')]
333
 
        else:
334
 
            return []
335
 
 
336
258
    def _get_section(self):
337
259
        """Override this to define the section used by the config."""
338
260
        return "DEFAULT"
339
261
 
340
 
    def _get_option_policy(self, section, option_name):
341
 
        """Return the policy for the given (section, option_name) pair."""
342
 
        return POLICY_NONE
343
 
 
344
262
    def _get_signature_checking(self):
345
263
        """See Config._get_signature_checking."""
346
264
        policy = self._get_user_option('check_signatures')
359
277
 
360
278
    def _get_user_option(self, option_name):
361
279
        """See Config._get_user_option."""
362
 
        for (section, extra_path) in self._get_matching_sections():
363
 
            try:
364
 
                value = self._get_parser().get_value(section, option_name)
365
 
            except KeyError:
366
 
                continue
367
 
            policy = self._get_option_policy(section, option_name)
368
 
            if policy == POLICY_NONE:
369
 
                return value
370
 
            elif policy == POLICY_NORECURSE:
371
 
                # norecurse items only apply to the exact path
372
 
                if extra_path:
373
 
                    continue
374
 
                else:
375
 
                    return value
376
 
            elif policy == POLICY_APPENDPATH:
377
 
                if extra_path:
378
 
                    value = urlutils.join(value, extra_path)
379
 
                return value
380
 
            else:
381
 
                raise AssertionError('Unexpected config policy %r' % policy)
382
 
        else:
383
 
            return None
 
280
        try:
 
281
            return self._get_parser().get_value(self._get_section(),
 
282
                                                option_name)
 
283
        except KeyError:
 
284
            pass
384
285
 
385
286
    def _gpg_signing_command(self):
386
287
        """See Config.gpg_signing_command."""
478
379
            location = urlutils.local_path_from_url(location)
479
380
        self.location = location
480
381
 
481
 
    def _get_matching_sections(self):
482
 
        """Return an ordered list of section names matching this location."""
 
382
    def _get_section(self):
 
383
        """Get the section we should look in for config items.
 
384
 
 
385
        Returns None if none exists. 
 
386
        TODO: perhaps return a NullSection that thunks through to the 
 
387
              global config.
 
388
        """
483
389
        sections = self._get_parser()
484
390
        location_names = self.location.split('/')
485
391
        if self.location.endswith('/'):
509
415
            # if section is longer, no match.
510
416
            if len(section_names) > len(location_names):
511
417
                continue
512
 
            matches.append((len(section_names), section,
513
 
                            '/'.join(location_names[len(section_names):])))
 
418
            # if path is longer, and recurse is not true, no match
 
419
            if len(section_names) < len(location_names):
 
420
                try:
 
421
                    if not self._get_parser()[section].as_bool('recurse'):
 
422
                        continue
 
423
                except KeyError:
 
424
                    pass
 
425
            matches.append((len(section_names), section))
 
426
        if not len(matches):
 
427
            return None
514
428
        matches.sort(reverse=True)
515
 
        sections = []
516
 
        for (length, section, extra_path) in matches:
517
 
            sections.append((section, extra_path))
518
 
            # should we stop looking for parent configs here?
519
 
            try:
520
 
                if self._get_parser()[section].as_bool('ignore_parents'):
521
 
                    break
522
 
            except KeyError:
523
 
                pass
524
 
        return sections
525
 
 
526
 
    def _get_option_policy(self, section, option_name):
527
 
        """Return the policy for the given (section, option_name) pair."""
528
 
        # check for the old 'recurse=False' flag
529
 
        try:
530
 
            recurse = self._get_parser()[section].as_bool('recurse')
531
 
        except KeyError:
532
 
            recurse = True
533
 
        if not recurse:
534
 
            return POLICY_NORECURSE
535
 
 
536
 
        policy_key = option_name + ':policy'
537
 
        try:
538
 
            policy_name = self._get_parser()[section][policy_key]
539
 
        except KeyError:
540
 
            policy_name = None
541
 
 
542
 
        return _policy_value[policy_name]
543
 
 
544
 
    def _set_option_policy(self, section, option_name, option_policy):
545
 
        """Set the policy for the given option name in the given section."""
546
 
        # The old recurse=False option affects all options in the
547
 
        # section.  To handle multiple policies in the section, we
548
 
        # need to convert it to a policy_norecurse key.
549
 
        try:
550
 
            recurse = self._get_parser()[section].as_bool('recurse')
551
 
        except KeyError:
552
 
            pass
553
 
        else:
554
 
            symbol_versioning.warn(
555
 
                'The recurse option is deprecated as of 0.14.  '
556
 
                'The section "%s" has been converted to use policies.'
557
 
                % section,
558
 
                DeprecationWarning)
559
 
            del self._get_parser()[section]['recurse']
560
 
            if not recurse:
561
 
                for key in self._get_parser()[section].keys():
562
 
                    if not key.endswith(':policy'):
563
 
                        self._get_parser()[section][key +
564
 
                                                    ':policy'] = 'norecurse'
565
 
 
566
 
        policy_key = option_name + ':policy'
567
 
        policy_name = _policy_name[option_policy]
568
 
        if policy_name is not None:
569
 
            self._get_parser()[section][policy_key] = policy_name
570
 
        else:
571
 
            if policy_key in self._get_parser()[section]:
572
 
                del self._get_parser()[section][policy_key]
573
 
 
574
 
    def set_user_option(self, option, value, store=STORE_LOCATION):
 
429
        return matches[0][1]
 
430
 
 
431
    def set_user_option(self, option, value):
575
432
        """Save option and its value in the configuration."""
576
 
        assert store in [STORE_LOCATION,
577
 
                         STORE_LOCATION_NORECURSE,
578
 
                         STORE_LOCATION_APPENDPATH], 'bad storage policy'
579
433
        # FIXME: RBC 20051029 This should refresh the parser and also take a
580
434
        # file lock on locations.conf.
581
435
        conf_dir = os.path.dirname(self._get_filename())
589
443
        elif location + '/' in self._get_parser():
590
444
            location = location + '/'
591
445
        self._get_parser()[location][option]=value
592
 
        # the allowed values of store match the config policies
593
 
        self._set_option_policy(location, option, store)
594
446
        self._get_parser().write(file(self._get_filename(), 'wb'))
595
447
 
596
448
 
671
523
                return value
672
524
        return None
673
525
 
674
 
    def set_user_option(self, name, value, store=STORE_BRANCH,
675
 
        warn_masked=False):
676
 
        if store == STORE_BRANCH:
 
526
    def set_user_option(self, name, value, local=False):
 
527
        if local is True:
 
528
            self._get_location_config().set_user_option(name, value)
 
529
        else:
677
530
            self._get_branch_data_config().set_option(value, name)
678
 
        elif store == STORE_GLOBAL:
679
 
            self._get_global_config().set_user_option(name, value)
680
 
        else:
681
 
            self._get_location_config().set_user_option(name, value, store)
682
 
        if not warn_masked:
683
 
            return
684
 
        if store in (STORE_GLOBAL, STORE_BRANCH):
685
 
            mask_value = self._get_location_config().get_user_option(name)
686
 
            if mask_value is not None:
687
 
                trace.warning('Value "%s" is masked by "%s" from'
688
 
                              ' locations.conf', value, mask_value)
689
 
            else:
690
 
                if store == STORE_GLOBAL:
691
 
                    branch_config = self._get_branch_data_config()
692
 
                    mask_value = branch_config.get_user_option(name)
693
 
                    if mask_value is not None:
694
 
                        trace.warning('Value "%s" is masked by "%s" from'
695
 
                                      ' branch.conf', value, mask_value)
696
531
 
697
532
 
698
533
    def _gpg_signing_command(self):
717
552
        value = self._get_explicit_nickname()
718
553
        if value is not None:
719
554
            return value
720
 
        return urlutils.unescape(self.branch.base.split('/')[-2])
 
555
        return self.branch.base.split('/')[-2]
721
556
 
722
557
    def has_explicit_nickname(self):
723
558
        """Return true if a nickname has been explicitly assigned."""
759
594
    base = os.environ.get('BZR_HOME', None)
760
595
    if sys.platform == 'win32':
761
596
        if base is None:
762
 
            base = win32utils.get_appdata_location_unicode()
 
597
            base = os.environ.get('APPDATA', None)
763
598
        if base is None:
764
599
            base = os.environ.get('HOME', None)
765
600
        if base is None:
766
601
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA, or HOME set')
767
 
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
602
        return pathjoin(base, 'bazaar', '2.0')
768
603
    else:
769
604
        # cygwin, linux, and darwin all have a $HOME directory
770
605
        if base is None:
771
606
            base = os.path.expanduser("~")
772
 
        return osutils.pathjoin(base, ".bazaar")
 
607
        return pathjoin(base, ".bazaar")
773
608
 
774
609
 
775
610
def config_filename():
776
611
    """Return per-user configuration ini file filename."""
777
 
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
 
612
    return pathjoin(config_dir(), 'bazaar.conf')
778
613
 
779
614
 
780
615
def branches_config_filename():
781
616
    """Return per-user configuration ini file filename."""
782
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
 
617
    return pathjoin(config_dir(), 'branches.conf')
783
618
 
784
619
 
785
620
def locations_config_filename():
786
621
    """Return per-user configuration ini file filename."""
787
 
    return osutils.pathjoin(config_dir(), 'locations.conf')
 
622
    return pathjoin(config_dir(), 'locations.conf')
788
623
 
789
624
 
790
625
def user_ignore_config_filename():
791
626
    """Return the user default ignore filename"""
792
 
    return osutils.pathjoin(config_dir(), 'ignore')
 
627
    return pathjoin(config_dir(), 'ignore')
793
628
 
794
629
 
795
630
def _auto_user_id():
805
640
    """
806
641
    import socket
807
642
 
808
 
    if sys.platform == 'win32':
809
 
        name = win32utils.get_user_name_unicode()
810
 
        if name is None:
811
 
            raise errors.BzrError("Cannot autodetect user name.\n"
812
 
                                  "Please, set your name with command like:\n"
813
 
                                  'bzr whoami "Your Name <name@domain.com>"')
814
 
        host = win32utils.get_host_name_unicode()
815
 
        if host is None:
816
 
            host = socket.gethostname()
817
 
        return name, (name + '@' + host)
 
643
    # XXX: Any good way to get real user name on win32?
818
644
 
819
645
    try:
820
646
        import pwd
872
698
    """
873
699
    m = re.search(r'[\w+.-]+@[\w+.-]+', e)
874
700
    if not m:
875
 
        raise errors.NoEmailInUsername(e)
 
701
        raise errors.BzrError("%r doesn't seem to contain "
 
702
                              "a reasonable email address" % e)
876
703
    return m.group(0)
877
704
 
878
705
 
888
715
 
889
716
    def _get_config(self):
890
717
        try:
891
 
            obj = ConfigObj(self.branch.control_files.get('branch.conf'),
 
718
            obj = ConfigObj(self.branch.control_files.get('branch.conf'), 
892
719
                            encoding='utf-8')
893
720
        except errors.NoSuchFile:
894
721
            obj = ConfigObj(encoding='utf=8')
900
727
            obj = self._get_config()
901
728
            try:
902
729
                if section is not None:
903
 
                    obj = obj[section]
 
730
                    obj[section]
904
731
                result = obj[name]
905
732
            except KeyError:
906
733
                result = default