/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Vincent Ladeuil
  • Date: 2010-08-28 16:56:36 UTC
  • mto: (5345.5.13 lockable-config-files)
  • mto: This revision was merged to the branch mainline in revision 5395.
  • Revision ID: v.ladeuil+lp@free.fr-20100828165636-8e2wziacdpog1adg
Rename IniBaseConfig.from_bytes to from_string.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
 
75
75
import bzrlib
76
76
from bzrlib import (
 
77
    atomicfile,
77
78
    debug,
78
79
    errors,
79
80
    mail_client,
257
258
 
258
259
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
259
260
 
260
 
        $BZR_EMAIL can be set to override this (as well as the
261
 
        deprecated $BZREMAIL), then
 
261
        $BZR_EMAIL can be set to override this, then
262
262
        the concrete policy type is checked, and finally
263
263
        $EMAIL is examined.
264
 
        If none is found, a reasonable default is (hopefully)
265
 
        created.
 
264
        If no username can be found, errors.NoWhoami exception is raised.
266
265
 
267
266
        TODO: Check it's reasonably well-formed.
268
267
        """
278
277
        if v:
279
278
            return v.decode(osutils.get_user_encoding())
280
279
 
281
 
        name, email = _auto_user_id()
282
 
        if name:
283
 
            return '%s <%s>' % (name, email)
284
 
        else:
285
 
            return email
 
280
        raise errors.NoWhoami()
 
281
 
 
282
    def ensure_username(self):
 
283
        """Raise errors.NoWhoami if username is not set.
 
284
 
 
285
        This method relies on the username() function raising the error.
 
286
        """
 
287
        self.username()
286
288
 
287
289
    def signature_checking(self):
288
290
        """What is the current policy for signature checking?."""
350
352
class IniBasedConfig(Config):
351
353
    """A configuration policy that draws from ini files."""
352
354
 
353
 
    def __init__(self, get_filename):
 
355
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
 
356
                 file_name=None):
 
357
        """Base class for configuration files using an ini-like syntax.
 
358
 
 
359
        :param file_name: The configuration file path.
 
360
        """
354
361
        super(IniBasedConfig, self).__init__()
355
 
        self._get_filename = get_filename
 
362
        if symbol_versioning.deprecated_passed(get_filename):
 
363
            symbol_versioning.warn(
 
364
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
365
                ' Use file_name instead.',
 
366
                DeprecationWarning,
 
367
                stacklevel=2)
 
368
            if get_filename is None:
 
369
                # Tests use in-memory config files that doesn't need to be
 
370
                # saved on disk
 
371
                self.file_name = None
 
372
            else:
 
373
                self.file_name = get_filename()
 
374
        else:
 
375
            self.file_name = file_name
 
376
        self._content = None
356
377
        self._parser = None
357
378
 
358
 
    def _get_parser(self, file=None):
 
379
    @classmethod
 
380
    def from_string(cls, str_or_unicode):
 
381
        """Create a config object from bytes.
 
382
 
 
383
        :param str_or_unicode: A string representing the file content. This will
 
384
            be utf-8 encoded.
 
385
        """
 
386
        conf = cls()
 
387
        conf._content = StringIO(str_or_unicode.encode('utf-8'))
 
388
        return conf
 
389
 
 
390
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
359
391
        if self._parser is not None:
360
392
            return self._parser
361
 
        if file is None:
362
 
            input = self._get_filename()
 
393
        if symbol_versioning.deprecated_passed(file):
 
394
            symbol_versioning.warn(
 
395
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
396
                ' Use IniBasedConfig(_content=xxx) instead.',
 
397
                DeprecationWarning,
 
398
                stacklevel=2)
 
399
        if self._content is not None:
 
400
            co_input = self._content
 
401
        elif self.file_name is None:
 
402
            raise AssertionError('We have no content to create the config')
363
403
        else:
364
 
            input = file
 
404
            co_input = self.file_name
365
405
        try:
366
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
406
            self._parser = ConfigObj(co_input, encoding='utf-8')
367
407
        except configobj.ConfigObjError, e:
368
408
            raise errors.ParseConfigError(e.errors, e.config.filename)
369
409
        return self._parser
476
516
    def _get_nickname(self):
477
517
        return self.get_user_option('nickname')
478
518
 
 
519
    def _write_config_file(self):
 
520
        if self.file_name is None:
 
521
            raise AssertionError('We cannot save, self.file_name is None')
 
522
        atomic_file = atomicfile.AtomicFile(self.file_name)
 
523
        self._get_parser().write(atomic_file)
 
524
        atomic_file.commit()
 
525
        atomic_file.close()
 
526
        osutils.copy_ownership_from_path(self.file_name)
 
527
 
479
528
 
480
529
class GlobalConfig(IniBasedConfig):
481
530
    """The configuration that should be used for a specific location."""
482
531
 
 
532
    def __init__(self):
 
533
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
534
 
483
535
    def get_editor(self):
484
536
        return self._get_user_option('editor')
485
537
 
486
 
    def __init__(self):
487
 
        super(GlobalConfig, self).__init__(config_filename)
488
 
 
489
538
    def set_user_option(self, option, value):
490
539
        """Save option and its value in the configuration."""
491
540
        self._set_option(option, value, 'DEFAULT')
512
561
    def _set_option(self, option, value, section):
513
562
        # FIXME: RBC 20051029 This should refresh the parser and also take a
514
563
        # file lock on bazaar.conf.
515
 
        conf_dir = os.path.dirname(self._get_filename())
 
564
        conf_dir = os.path.dirname(self.file_name)
516
565
        ensure_config_dir_exists(conf_dir)
517
566
        self._get_parser().setdefault(section, {})[option] = value
518
567
        self._write_config_file()
519
568
 
520
 
    def _write_config_file(self):
521
 
        path = self._get_filename()
522
 
        f = open(path, 'wb')
523
 
        osutils.copy_ownership_from_path(path)
524
 
        self._get_parser().write(f)
525
 
        f.close()
526
 
 
527
569
 
528
570
class LocationConfig(IniBasedConfig):
529
571
    """A configuration object that gives the policy for a location."""
530
572
 
531
573
    def __init__(self, location):
532
 
        name_generator = locations_config_filename
533
 
        if (not os.path.exists(name_generator()) and
534
 
                os.path.exists(branches_config_filename())):
535
 
            if sys.platform == 'win32':
536
 
                trace.warning('Please rename %s to %s'
537
 
                              % (branches_config_filename(),
538
 
                                 locations_config_filename()))
539
 
            else:
540
 
                trace.warning('Please rename ~/.bazaar/branches.conf'
541
 
                              ' to ~/.bazaar/locations.conf')
542
 
            name_generator = branches_config_filename
543
 
        super(LocationConfig, self).__init__(name_generator)
 
574
        super(LocationConfig, self).__init__(
 
575
            file_name=locations_config_filename())
544
576
        # local file locations are looked up by local path, rather than
545
577
        # by file url. This is because the config file is a user
546
578
        # file, and we would rather not expose the user to file urls.
548
580
            location = urlutils.local_path_from_url(location)
549
581
        self.location = location
550
582
 
 
583
    @classmethod
 
584
    def from_string(cls, str_or_unicode, location):
 
585
        """Create a config object from bytes.
 
586
 
 
587
        :param str_or_unicode: A string representing the file content. This will
 
588
            be utf-8 encoded.
 
589
 
 
590
        :param location: The location url to filter the configuration.
 
591
        """
 
592
        conf = cls(location)
 
593
        conf._content = StringIO(str_or_unicode.encode('utf-8'))
 
594
        return conf
 
595
 
551
596
    def _get_matching_sections(self):
552
597
        """Return an ordered list of section names matching this location."""
553
598
        sections = self._get_parser()
650
695
                (store, option))
651
696
        # FIXME: RBC 20051029 This should refresh the parser and also take a
652
697
        # file lock on locations.conf.
653
 
        conf_dir = os.path.dirname(self._get_filename())
 
698
        conf_dir = os.path.dirname(self.file_name)
654
699
        ensure_config_dir_exists(conf_dir)
655
700
        location = self.location
656
701
        if location.endswith('/'):
663
708
        self._get_parser()[location][option]=value
664
709
        # the allowed values of store match the config policies
665
710
        self._set_option_policy(location, option, store)
666
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
711
        self._write_config_file()
667
712
 
668
713
 
669
714
class BranchConfig(Config):
670
715
    """A configuration object giving the policy for a branch."""
671
716
 
 
717
    def __init__(self, branch):
 
718
        super(BranchConfig, self).__init__()
 
719
        self._location_config = None
 
720
        self._branch_data_config = None
 
721
        self._global_config = None
 
722
        self.branch = branch
 
723
        self.option_sources = (self._get_location_config,
 
724
                               self._get_branch_data_config,
 
725
                               self._get_global_config)
 
726
 
672
727
    def _get_branch_data_config(self):
673
728
        if self._branch_data_config is None:
674
729
            self._branch_data_config = TreeConfig(self.branch)
772
827
        """See Config.gpg_signing_command."""
773
828
        return self._get_safe_value('_gpg_signing_command')
774
829
 
775
 
    def __init__(self, branch):
776
 
        super(BranchConfig, self).__init__()
777
 
        self._location_config = None
778
 
        self._branch_data_config = None
779
 
        self._global_config = None
780
 
        self.branch = branch
781
 
        self.option_sources = (self._get_location_config,
782
 
                               self._get_branch_data_config,
783
 
                               self._get_global_config)
784
 
 
785
830
    def _post_commit(self):
786
831
        """See Config.post_commit."""
787
832
        return self._get_safe_value('_post_commit')
841
886
                                  ' or HOME set')
842
887
        return osutils.pathjoin(base, 'bazaar', '2.0')
843
888
    else:
844
 
        # cygwin, linux, and darwin all have a $HOME directory
845
889
        if base is None:
846
890
            base = os.path.expanduser("~")
847
891
        return osutils.pathjoin(base, ".bazaar")
852
896
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
853
897
 
854
898
 
855
 
def branches_config_filename():
856
 
    """Return per-user configuration ini file filename."""
857
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
858
 
 
859
 
 
860
899
def locations_config_filename():
861
900
    """Return per-user configuration ini file filename."""
862
901
    return osutils.pathjoin(config_dir(), 'locations.conf')
899
938
        return os.path.expanduser('~/.cache')
900
939
 
901
940
 
902
 
def _auto_user_id():
903
 
    """Calculate automatic user identification.
904
 
 
905
 
    Returns (realname, email).
906
 
 
907
 
    Only used when none is set in the environment or the id file.
908
 
 
909
 
    This previously used the FQDN as the default domain, but that can
910
 
    be very slow on machines where DNS is broken.  So now we simply
911
 
    use the hostname.
912
 
    """
913
 
    import socket
914
 
 
915
 
    if sys.platform == 'win32':
916
 
        name = win32utils.get_user_name_unicode()
917
 
        if name is None:
918
 
            raise errors.BzrError("Cannot autodetect user name.\n"
919
 
                                  "Please, set your name with command like:\n"
920
 
                                  'bzr whoami "Your Name <name@domain.com>"')
921
 
        host = win32utils.get_host_name_unicode()
922
 
        if host is None:
923
 
            host = socket.gethostname()
924
 
        return name, (name + '@' + host)
925
 
 
926
 
    try:
927
 
        import pwd
928
 
        uid = os.getuid()
929
 
        try:
930
 
            w = pwd.getpwuid(uid)
931
 
        except KeyError:
932
 
            raise errors.BzrCommandError('Unable to determine your name.  '
933
 
                'Please use "bzr whoami" to set it.')
934
 
 
935
 
        # we try utf-8 first, because on many variants (like Linux),
936
 
        # /etc/passwd "should" be in utf-8, and because it's unlikely to give
937
 
        # false positives.  (many users will have their user encoding set to
938
 
        # latin-1, which cannot raise UnicodeError.)
939
 
        try:
940
 
            gecos = w.pw_gecos.decode('utf-8')
941
 
            encoding = 'utf-8'
942
 
        except UnicodeError:
943
 
            try:
944
 
                encoding = osutils.get_user_encoding()
945
 
                gecos = w.pw_gecos.decode(encoding)
946
 
            except UnicodeError:
947
 
                raise errors.BzrCommandError('Unable to determine your name.  '
948
 
                   'Use "bzr whoami" to set it.')
949
 
        try:
950
 
            username = w.pw_name.decode(encoding)
951
 
        except UnicodeError:
952
 
            raise errors.BzrCommandError('Unable to determine your name.  '
953
 
                'Use "bzr whoami" to set it.')
954
 
 
955
 
        comma = gecos.find(',')
956
 
        if comma == -1:
957
 
            realname = gecos
958
 
        else:
959
 
            realname = gecos[:comma]
960
 
        if not realname:
961
 
            realname = username
962
 
 
963
 
    except ImportError:
964
 
        import getpass
965
 
        try:
966
 
            user_encoding = osutils.get_user_encoding()
967
 
            realname = username = getpass.getuser().decode(user_encoding)
968
 
        except UnicodeDecodeError:
969
 
            raise errors.BzrError("Can't decode username as %s." % \
970
 
                    user_encoding)
971
 
 
972
 
    return realname, (username + '@' + socket.gethostname())
973
 
 
974
 
 
975
941
def parse_username(username):
976
942
    """Parse e-mail username and return a (name, address) tuple."""
977
943
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1063
1029
        """Save the config file, only tests should use it for now."""
1064
1030
        conf_dir = os.path.dirname(self._filename)
1065
1031
        ensure_config_dir_exists(conf_dir)
1066
 
        self._get_config().write(file(self._filename, 'wb'))
 
1032
        f = file(self._filename, 'wb')
 
1033
        try:
 
1034
            self._get_config().write(f)
 
1035
        finally:
 
1036
            f.close()
1067
1037
 
1068
1038
    def _set_option(self, section_name, option_name, value):
1069
1039
        """Set an authentication configuration option"""
1517
1487
            return StringIO()
1518
1488
 
1519
1489
    def _get_configobj(self):
1520
 
        return ConfigObj(self._get_config_file(), encoding='utf-8')
 
1490
        f = self._get_config_file()
 
1491
        try:
 
1492
            return ConfigObj(f, encoding='utf-8')
 
1493
        finally:
 
1494
            f.close()
1521
1495
 
1522
1496
    def _set_configobj(self, configobj):
1523
1497
        out_file = StringIO()