/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: 2011-07-06 08:58:15 UTC
  • mfrom: (5609.48.2 2.3)
  • mto: (6012.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 6013.
  • Revision ID: v.ladeuil+lp@free.fr-20110706085815-6leauod52jq2u43d
MergingĀ inĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
63
63
"""
64
64
 
65
65
import os
 
66
import string
66
67
import sys
67
68
 
 
69
from bzrlib import commands
 
70
from bzrlib.decorators import needs_write_lock
68
71
from bzrlib.lazy_import import lazy_import
69
72
lazy_import(globals(), """
70
73
import errno
71
 
from fnmatch import fnmatch
 
74
import fnmatch
72
75
import re
73
76
from cStringIO import StringIO
74
77
 
75
78
import bzrlib
76
79
from bzrlib import (
77
80
    atomicfile,
 
81
    bzrdir,
78
82
    debug,
79
83
    errors,
 
84
    lockdir,
80
85
    mail_client,
81
86
    osutils,
82
87
    registry,
83
88
    symbol_versioning,
84
89
    trace,
 
90
    transport,
85
91
    ui,
86
92
    urlutils,
87
93
    win32utils,
150
156
    def __init__(self):
151
157
        super(Config, self).__init__()
152
158
 
 
159
    def config_id(self):
 
160
        """Returns a unique ID for the config."""
 
161
        raise NotImplementedError(self.config_id)
 
162
 
153
163
    def get_editor(self):
154
164
        """Get the users pop up editor."""
155
165
        raise NotImplementedError
262
272
        the concrete policy type is checked, and finally
263
273
        $EMAIL is examined.
264
274
        If no username can be found, errors.NoWhoami exception is raised.
265
 
 
266
 
        TODO: Check it's reasonably well-formed.
267
275
        """
268
276
        v = os.environ.get('BZR_EMAIL')
269
277
        if v:
270
278
            return v.decode(osutils.get_user_encoding())
271
 
 
272
279
        v = self._get_user_id()
273
280
        if v:
274
281
            return v
275
 
 
276
282
        v = os.environ.get('EMAIL')
277
283
        if v:
278
284
            return v.decode(osutils.get_user_encoding())
279
 
 
 
285
        name, email = _auto_user_id()
 
286
        if name and email:
 
287
            return '%s <%s>' % (name, email)
 
288
        elif email:
 
289
            return email
280
290
        raise errors.NoWhoami()
281
291
 
282
292
    def ensure_username(self):
352
362
class IniBasedConfig(Config):
353
363
    """A configuration policy that draws from ini files."""
354
364
 
355
 
    def __init__(self, get_filename):
 
365
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
 
366
                 file_name=None):
 
367
        """Base class for configuration files using an ini-like syntax.
 
368
 
 
369
        :param file_name: The configuration file path.
 
370
        """
356
371
        super(IniBasedConfig, self).__init__()
357
 
        self._get_filename = get_filename
 
372
        self.file_name = file_name
 
373
        if symbol_versioning.deprecated_passed(get_filename):
 
374
            symbol_versioning.warn(
 
375
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
376
                ' Use file_name instead.',
 
377
                DeprecationWarning,
 
378
                stacklevel=2)
 
379
            if get_filename is not None:
 
380
                self.file_name = get_filename()
 
381
        else:
 
382
            self.file_name = file_name
 
383
        self._content = None
358
384
        self._parser = None
359
385
 
360
 
    def _get_parser(self, file=None):
 
386
    @classmethod
 
387
    def from_string(cls, str_or_unicode, file_name=None, save=False):
 
388
        """Create a config object from a string.
 
389
 
 
390
        :param str_or_unicode: A string representing the file content. This will
 
391
            be utf-8 encoded.
 
392
 
 
393
        :param file_name: The configuration file path.
 
394
 
 
395
        :param _save: Whether the file should be saved upon creation.
 
396
        """
 
397
        conf = cls(file_name=file_name)
 
398
        conf._create_from_string(str_or_unicode, save)
 
399
        return conf
 
400
 
 
401
    def _create_from_string(self, str_or_unicode, save):
 
402
        self._content = StringIO(str_or_unicode.encode('utf-8'))
 
403
        # Some tests use in-memory configs, some other always need the config
 
404
        # file to exist on disk.
 
405
        if save:
 
406
            self._write_config_file()
 
407
 
 
408
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
361
409
        if self._parser is not None:
362
410
            return self._parser
363
 
        if file is None:
364
 
            input = self._get_filename()
 
411
        if symbol_versioning.deprecated_passed(file):
 
412
            symbol_versioning.warn(
 
413
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
414
                ' Use IniBasedConfig(_content=xxx) instead.',
 
415
                DeprecationWarning,
 
416
                stacklevel=2)
 
417
        if self._content is not None:
 
418
            co_input = self._content
 
419
        elif self.file_name is None:
 
420
            raise AssertionError('We have no content to create the config')
365
421
        else:
366
 
            input = file
 
422
            co_input = self.file_name
367
423
        try:
368
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
424
            self._parser = ConfigObj(co_input, encoding='utf-8')
369
425
        except configobj.ConfigObjError, e:
370
426
            raise errors.ParseConfigError(e.errors, e.config.filename)
 
427
        # Make sure self.reload() will use the right file name
 
428
        self._parser.filename = self.file_name
371
429
        return self._parser
372
430
 
 
431
    def reload(self):
 
432
        """Reload the config file from disk."""
 
433
        if self.file_name is None:
 
434
            raise AssertionError('We need a file name to reload the config')
 
435
        if self._parser is not None:
 
436
            self._parser.reload()
 
437
 
373
438
    def _get_matching_sections(self):
374
439
        """Return an ordered list of (section_name, extra_path) pairs.
375
440
 
386
451
        """Override this to define the section used by the config."""
387
452
        return "DEFAULT"
388
453
 
 
454
    def _get_sections(self, name=None):
 
455
        """Returns an iterator of the sections specified by ``name``.
 
456
 
 
457
        :param name: The section name. If None is supplied, the default
 
458
            configurations are yielded.
 
459
 
 
460
        :return: A tuple (name, section, config_id) for all sections that will
 
461
            be walked by user_get_option() in the 'right' order. The first one
 
462
            is where set_user_option() will update the value.
 
463
        """
 
464
        parser = self._get_parser()
 
465
        if name is not None:
 
466
            yield (name, parser[name], self.config_id())
 
467
        else:
 
468
            # No section name has been given so we fallback to the configobj
 
469
            # itself which holds the variables defined outside of any section.
 
470
            yield (None, parser, self.config_id())
 
471
 
 
472
    def _get_options(self, sections=None):
 
473
        """Return an ordered list of (name, value, section, config_id) tuples.
 
474
 
 
475
        All options are returned with their associated value and the section
 
476
        they appeared in. ``config_id`` is a unique identifier for the
 
477
        configuration file the option is defined in.
 
478
 
 
479
        :param sections: Default to ``_get_matching_sections`` if not
 
480
            specified. This gives a better control to daughter classes about
 
481
            which sections should be searched. This is a list of (name,
 
482
            configobj) tuples.
 
483
        """
 
484
        opts = []
 
485
        if sections is None:
 
486
            parser = self._get_parser()
 
487
            sections = []
 
488
            for (section_name, _) in self._get_matching_sections():
 
489
                try:
 
490
                    section = parser[section_name]
 
491
                except KeyError:
 
492
                    # This could happen for an empty file for which we define a
 
493
                    # DEFAULT section. FIXME: Force callers to provide sections
 
494
                    # instead ? -- vila 20100930
 
495
                    continue
 
496
                sections.append((section_name, section))
 
497
        config_id = self.config_id()
 
498
        for (section_name, section) in sections:
 
499
            for (name, value) in section.iteritems():
 
500
                yield (name, parser._quote(value), section_name,
 
501
                       config_id, parser)
 
502
 
389
503
    def _get_option_policy(self, section, option_name):
390
504
        """Return the policy for the given (section, option_name) pair."""
391
505
        return POLICY_NONE
478
592
    def _get_nickname(self):
479
593
        return self.get_user_option('nickname')
480
594
 
 
595
    def remove_user_option(self, option_name, section_name=None):
 
596
        """Remove a user option and save the configuration file.
 
597
 
 
598
        :param option_name: The option to be removed.
 
599
 
 
600
        :param section_name: The section the option is defined in, default to
 
601
            the default section.
 
602
        """
 
603
        self.reload()
 
604
        parser = self._get_parser()
 
605
        if section_name is None:
 
606
            section = parser
 
607
        else:
 
608
            section = parser[section_name]
 
609
        try:
 
610
            del section[option_name]
 
611
        except KeyError:
 
612
            raise errors.NoSuchConfigOption(option_name)
 
613
        self._write_config_file()
 
614
 
481
615
    def _write_config_file(self):
482
 
        filename = self._get_filename()
483
 
        atomic_file = atomicfile.AtomicFile(filename)
 
616
        if self.file_name is None:
 
617
            raise AssertionError('We cannot save, self.file_name is None')
 
618
        conf_dir = os.path.dirname(self.file_name)
 
619
        ensure_config_dir_exists(conf_dir)
 
620
        atomic_file = atomicfile.AtomicFile(self.file_name)
484
621
        self._get_parser().write(atomic_file)
485
622
        atomic_file.commit()
486
623
        atomic_file.close()
487
 
        osutils.copy_ownership_from_path(filename)
488
 
 
489
 
 
490
 
class GlobalConfig(IniBasedConfig):
 
624
        osutils.copy_ownership_from_path(self.file_name)
 
625
 
 
626
 
 
627
class LockableConfig(IniBasedConfig):
 
628
    """A configuration needing explicit locking for access.
 
629
 
 
630
    If several processes try to write the config file, the accesses need to be
 
631
    serialized.
 
632
 
 
633
    Daughter classes should decorate all methods that update a config with the
 
634
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
 
635
    ``_write_config_file()`` method. These methods (typically ``set_option()``
 
636
    and variants must reload the config file from disk before calling
 
637
    ``_write_config_file()``), this can be achieved by calling the
 
638
    ``self.reload()`` method. Note that the lock scope should cover both the
 
639
    reading and the writing of the config file which is why the decorator can't
 
640
    be applied to ``_write_config_file()`` only.
 
641
 
 
642
    This should be enough to implement the following logic:
 
643
    - lock for exclusive write access,
 
644
    - reload the config file from disk,
 
645
    - set the new value
 
646
    - unlock
 
647
 
 
648
    This logic guarantees that a writer can update a value without erasing an
 
649
    update made by another writer.
 
650
    """
 
651
 
 
652
    lock_name = 'lock'
 
653
 
 
654
    def __init__(self, file_name):
 
655
        super(LockableConfig, self).__init__(file_name=file_name)
 
656
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
 
657
        self.transport = transport.get_transport(self.dir)
 
658
        self._lock = lockdir.LockDir(self.transport, 'lock')
 
659
 
 
660
    def _create_from_string(self, unicode_bytes, save):
 
661
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
 
662
        if save:
 
663
            # We need to handle the saving here (as opposed to IniBasedConfig)
 
664
            # to be able to lock
 
665
            self.lock_write()
 
666
            self._write_config_file()
 
667
            self.unlock()
 
668
 
 
669
    def lock_write(self, token=None):
 
670
        """Takes a write lock in the directory containing the config file.
 
671
 
 
672
        If the directory doesn't exist it is created.
 
673
        """
 
674
        ensure_config_dir_exists(self.dir)
 
675
        return self._lock.lock_write(token)
 
676
 
 
677
    def unlock(self):
 
678
        self._lock.unlock()
 
679
 
 
680
    def break_lock(self):
 
681
        self._lock.break_lock()
 
682
 
 
683
    @needs_write_lock
 
684
    def remove_user_option(self, option_name, section_name=None):
 
685
        super(LockableConfig, self).remove_user_option(option_name,
 
686
                                                       section_name)
 
687
 
 
688
    def _write_config_file(self):
 
689
        if self._lock is None or not self._lock.is_held:
 
690
            # NB: if the following exception is raised it probably means a
 
691
            # missing @needs_write_lock decorator on one of the callers.
 
692
            raise errors.ObjectNotLocked(self)
 
693
        super(LockableConfig, self)._write_config_file()
 
694
 
 
695
 
 
696
class GlobalConfig(LockableConfig):
491
697
    """The configuration that should be used for a specific location."""
492
698
 
 
699
    def __init__(self):
 
700
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
701
 
 
702
    def config_id(self):
 
703
        return 'bazaar'
 
704
 
 
705
    @classmethod
 
706
    def from_string(cls, str_or_unicode, save=False):
 
707
        """Create a config object from a string.
 
708
 
 
709
        :param str_or_unicode: A string representing the file content. This
 
710
            will be utf-8 encoded.
 
711
 
 
712
        :param save: Whether the file should be saved upon creation.
 
713
        """
 
714
        conf = cls()
 
715
        conf._create_from_string(str_or_unicode, save)
 
716
        return conf
 
717
 
493
718
    def get_editor(self):
494
719
        return self._get_user_option('editor')
495
720
 
496
 
    def __init__(self):
497
 
        super(GlobalConfig, self).__init__(config_filename)
498
 
 
 
721
    @needs_write_lock
499
722
    def set_user_option(self, option, value):
500
723
        """Save option and its value in the configuration."""
501
724
        self._set_option(option, value, 'DEFAULT')
507
730
        else:
508
731
            return {}
509
732
 
 
733
    @needs_write_lock
510
734
    def set_alias(self, alias_name, alias_command):
511
735
        """Save the alias in the configuration."""
512
736
        self._set_option(alias_name, alias_command, 'ALIASES')
513
737
 
 
738
    @needs_write_lock
514
739
    def unset_alias(self, alias_name):
515
740
        """Unset an existing alias."""
 
741
        self.reload()
516
742
        aliases = self._get_parser().get('ALIASES')
517
743
        if not aliases or alias_name not in aliases:
518
744
            raise errors.NoSuchAlias(alias_name)
520
746
        self._write_config_file()
521
747
 
522
748
    def _set_option(self, option, value, section):
523
 
        # FIXME: RBC 20051029 This should refresh the parser and also take a
524
 
        # file lock on bazaar.conf.
525
 
        conf_dir = os.path.dirname(self._get_filename())
526
 
        ensure_config_dir_exists(conf_dir)
 
749
        self.reload()
527
750
        self._get_parser().setdefault(section, {})[option] = value
528
751
        self._write_config_file()
529
752
 
530
753
 
531
 
class LocationConfig(IniBasedConfig):
 
754
    def _get_sections(self, name=None):
 
755
        """See IniBasedConfig._get_sections()."""
 
756
        parser = self._get_parser()
 
757
        # We don't give access to options defined outside of any section, we
 
758
        # used the DEFAULT section by... default.
 
759
        if name in (None, 'DEFAULT'):
 
760
            # This could happen for an empty file where the DEFAULT section
 
761
            # doesn't exist yet. So we force DEFAULT when yielding
 
762
            name = 'DEFAULT'
 
763
            if 'DEFAULT' not in parser:
 
764
               parser['DEFAULT']= {}
 
765
        yield (name, parser[name], self.config_id())
 
766
 
 
767
    @needs_write_lock
 
768
    def remove_user_option(self, option_name, section_name=None):
 
769
        if section_name is None:
 
770
            # We need to force the default section.
 
771
            section_name = 'DEFAULT'
 
772
        # We need to avoid the LockableConfig implementation or we'll lock
 
773
        # twice
 
774
        super(LockableConfig, self).remove_user_option(option_name,
 
775
                                                       section_name)
 
776
 
 
777
 
 
778
class LocationConfig(LockableConfig):
532
779
    """A configuration object that gives the policy for a location."""
533
780
 
534
781
    def __init__(self, location):
535
 
        name_generator = locations_config_filename
536
 
        if (not os.path.exists(name_generator()) and
537
 
                os.path.exists(branches_config_filename())):
538
 
            if sys.platform == 'win32':
539
 
                trace.warning('Please rename %s to %s'
540
 
                              % (branches_config_filename(),
541
 
                                 locations_config_filename()))
542
 
            else:
543
 
                trace.warning('Please rename ~/.bazaar/branches.conf'
544
 
                              ' to ~/.bazaar/locations.conf')
545
 
            name_generator = branches_config_filename
546
 
        super(LocationConfig, self).__init__(name_generator)
 
782
        super(LocationConfig, self).__init__(
 
783
            file_name=locations_config_filename())
547
784
        # local file locations are looked up by local path, rather than
548
785
        # by file url. This is because the config file is a user
549
786
        # file, and we would rather not expose the user to file urls.
551
788
            location = urlutils.local_path_from_url(location)
552
789
        self.location = location
553
790
 
 
791
    def config_id(self):
 
792
        return 'locations'
 
793
 
 
794
    @classmethod
 
795
    def from_string(cls, str_or_unicode, location, save=False):
 
796
        """Create a config object from a string.
 
797
 
 
798
        :param str_or_unicode: A string representing the file content. This will
 
799
            be utf-8 encoded.
 
800
 
 
801
        :param location: The location url to filter the configuration.
 
802
 
 
803
        :param save: Whether the file should be saved upon creation.
 
804
        """
 
805
        conf = cls(location)
 
806
        conf._create_from_string(str_or_unicode, save)
 
807
        return conf
 
808
 
554
809
    def _get_matching_sections(self):
555
810
        """Return an ordered list of section names matching this location."""
556
811
        sections = self._get_parser()
573
828
            names = zip(location_names, section_names)
574
829
            matched = True
575
830
            for name in names:
576
 
                if not fnmatch(name[0], name[1]):
 
831
                if not fnmatch.fnmatch(name[0], name[1]):
577
832
                    matched = False
578
833
                    break
579
834
            if not matched:
584
839
                continue
585
840
            matches.append((len(section_names), section,
586
841
                            '/'.join(location_names[len(section_names):])))
 
842
        # put the longest (aka more specific) locations first
587
843
        matches.sort(reverse=True)
588
844
        sections = []
589
845
        for (length, section, extra_path) in matches:
596
852
                pass
597
853
        return sections
598
854
 
 
855
    def _get_sections(self, name=None):
 
856
        """See IniBasedConfig._get_sections()."""
 
857
        # We ignore the name here as the only sections handled are named with
 
858
        # the location path and we don't expose embedded sections either.
 
859
        parser = self._get_parser()
 
860
        for name, extra_path in self._get_matching_sections():
 
861
            yield (name, parser[name], self.config_id())
 
862
 
599
863
    def _get_option_policy(self, section, option_name):
600
864
        """Return the policy for the given (section, option_name) pair."""
601
865
        # check for the old 'recurse=False' flag
644
908
            if policy_key in self._get_parser()[section]:
645
909
                del self._get_parser()[section][policy_key]
646
910
 
 
911
    @needs_write_lock
647
912
    def set_user_option(self, option, value, store=STORE_LOCATION):
648
913
        """Save option and its value in the configuration."""
649
914
        if store not in [STORE_LOCATION,
651
916
                         STORE_LOCATION_APPENDPATH]:
652
917
            raise ValueError('bad storage policy %r for %r' %
653
918
                (store, option))
654
 
        # FIXME: RBC 20051029 This should refresh the parser and also take a
655
 
        # file lock on locations.conf.
656
 
        conf_dir = os.path.dirname(self._get_filename())
657
 
        ensure_config_dir_exists(conf_dir)
 
919
        self.reload()
658
920
        location = self.location
659
921
        if location.endswith('/'):
660
922
            location = location[:-1]
661
 
        if (not location in self._get_parser() and
662
 
            not location + '/' in self._get_parser()):
663
 
            self._get_parser()[location]={}
664
 
        elif location + '/' in self._get_parser():
 
923
        parser = self._get_parser()
 
924
        if not location in parser and not location + '/' in parser:
 
925
            parser[location] = {}
 
926
        elif location + '/' in parser:
665
927
            location = location + '/'
666
 
        self._get_parser()[location][option]=value
 
928
        parser[location][option]=value
667
929
        # the allowed values of store match the config policies
668
930
        self._set_option_policy(location, option, store)
669
931
        self._write_config_file()
672
934
class BranchConfig(Config):
673
935
    """A configuration object giving the policy for a branch."""
674
936
 
 
937
    def __init__(self, branch):
 
938
        super(BranchConfig, self).__init__()
 
939
        self._location_config = None
 
940
        self._branch_data_config = None
 
941
        self._global_config = None
 
942
        self.branch = branch
 
943
        self.option_sources = (self._get_location_config,
 
944
                               self._get_branch_data_config,
 
945
                               self._get_global_config)
 
946
 
 
947
    def config_id(self):
 
948
        return 'branch'
 
949
 
675
950
    def _get_branch_data_config(self):
676
951
        if self._branch_data_config is None:
677
952
            self._branch_data_config = TreeConfig(self.branch)
 
953
            self._branch_data_config.config_id = self.config_id
678
954
        return self._branch_data_config
679
955
 
680
956
    def _get_location_config(self):
748
1024
                return value
749
1025
        return None
750
1026
 
 
1027
    def _get_sections(self, name=None):
 
1028
        """See IniBasedConfig.get_sections()."""
 
1029
        for source in self.option_sources:
 
1030
            for section in source()._get_sections(name):
 
1031
                yield section
 
1032
 
 
1033
    def _get_options(self, sections=None):
 
1034
        opts = []
 
1035
        # First the locations options
 
1036
        for option in self._get_location_config()._get_options():
 
1037
            yield option
 
1038
        # Then the branch options
 
1039
        branch_config = self._get_branch_data_config()
 
1040
        if sections is None:
 
1041
            sections = [('DEFAULT', branch_config._get_parser())]
 
1042
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
 
1043
        # Config itself has no notion of sections :( -- vila 20101001
 
1044
        config_id = self.config_id()
 
1045
        for (section_name, section) in sections:
 
1046
            for (name, value) in section.iteritems():
 
1047
                yield (name, value, section_name,
 
1048
                       config_id, branch_config._get_parser())
 
1049
        # Then the global options
 
1050
        for option in self._get_global_config()._get_options():
 
1051
            yield option
 
1052
 
751
1053
    def set_user_option(self, name, value, store=STORE_BRANCH,
752
1054
        warn_masked=False):
753
1055
        if store == STORE_BRANCH:
771
1073
                        trace.warning('Value "%s" is masked by "%s" from'
772
1074
                                      ' branch.conf', value, mask_value)
773
1075
 
 
1076
    def remove_user_option(self, option_name, section_name=None):
 
1077
        self._get_branch_data_config().remove_option(option_name, section_name)
 
1078
 
774
1079
    def _gpg_signing_command(self):
775
1080
        """See Config.gpg_signing_command."""
776
1081
        return self._get_safe_value('_gpg_signing_command')
777
1082
 
778
 
    def __init__(self, branch):
779
 
        super(BranchConfig, self).__init__()
780
 
        self._location_config = None
781
 
        self._branch_data_config = None
782
 
        self._global_config = None
783
 
        self.branch = branch
784
 
        self.option_sources = (self._get_location_config,
785
 
                               self._get_branch_data_config,
786
 
                               self._get_global_config)
787
 
 
788
1083
    def _post_commit(self):
789
1084
        """See Config.post_commit."""
790
1085
        return self._get_safe_value('_post_commit')
820
1115
            parent_dir = os.path.dirname(path)
821
1116
            if not os.path.isdir(parent_dir):
822
1117
                trace.mutter('creating config parent directory: %r', parent_dir)
823
 
            os.mkdir(parent_dir)
 
1118
                os.mkdir(parent_dir)
824
1119
        trace.mutter('creating config directory: %r', path)
825
1120
        os.mkdir(path)
826
1121
        osutils.copy_ownership_from_path(path)
829
1124
def config_dir():
830
1125
    """Return per-user configuration directory.
831
1126
 
832
 
    By default this is ~/.bazaar/
 
1127
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
 
1128
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1129
    that will be used instead.
833
1130
 
834
1131
    TODO: Global option --config-dir to override this.
835
1132
    """
836
1133
    base = os.environ.get('BZR_HOME', None)
837
1134
    if sys.platform == 'win32':
 
1135
        # environ variables on Windows are in user encoding/mbcs. So decode
 
1136
        # before using one
 
1137
        if base is not None:
 
1138
            base = base.decode('mbcs')
838
1139
        if base is None:
839
1140
            base = win32utils.get_appdata_location_unicode()
840
1141
        if base is None:
841
1142
            base = os.environ.get('HOME', None)
 
1143
            if base is not None:
 
1144
                base = base.decode('mbcs')
842
1145
        if base is None:
843
1146
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
844
1147
                                  ' or HOME set')
845
1148
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
1149
    elif sys.platform == 'darwin':
 
1150
        if base is None:
 
1151
            # this takes into account $HOME
 
1152
            base = os.path.expanduser("~")
 
1153
        return osutils.pathjoin(base, '.bazaar')
846
1154
    else:
847
1155
        if base is None:
 
1156
 
 
1157
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1158
            if xdg_dir is None:
 
1159
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1160
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1161
            if osutils.isdir(xdg_dir):
 
1162
                trace.mutter(
 
1163
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1164
                return xdg_dir
 
1165
 
848
1166
            base = os.path.expanduser("~")
849
1167
        return osutils.pathjoin(base, ".bazaar")
850
1168
 
854
1172
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
855
1173
 
856
1174
 
857
 
def branches_config_filename():
858
 
    """Return per-user configuration ini file filename."""
859
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
860
 
 
861
 
 
862
1175
def locations_config_filename():
863
1176
    """Return per-user configuration ini file filename."""
864
1177
    return osutils.pathjoin(config_dir(), 'locations.conf')
901
1214
        return os.path.expanduser('~/.cache')
902
1215
 
903
1216
 
 
1217
def _get_default_mail_domain():
 
1218
    """If possible, return the assumed default email domain.
 
1219
 
 
1220
    :returns: string mail domain, or None.
 
1221
    """
 
1222
    if sys.platform == 'win32':
 
1223
        # No implementation yet; patches welcome
 
1224
        return None
 
1225
    try:
 
1226
        f = open('/etc/mailname')
 
1227
    except (IOError, OSError), e:
 
1228
        return None
 
1229
    try:
 
1230
        domain = f.read().strip()
 
1231
        return domain
 
1232
    finally:
 
1233
        f.close()
 
1234
 
 
1235
 
 
1236
def _auto_user_id():
 
1237
    """Calculate automatic user identification.
 
1238
 
 
1239
    :returns: (realname, email), either of which may be None if they can't be
 
1240
    determined.
 
1241
 
 
1242
    Only used when none is set in the environment or the id file.
 
1243
 
 
1244
    This only returns an email address if we can be fairly sure the 
 
1245
    address is reasonable, ie if /etc/mailname is set on unix.
 
1246
 
 
1247
    This doesn't use the FQDN as the default domain because that may be 
 
1248
    slow, and it doesn't use the hostname alone because that's not normally 
 
1249
    a reasonable address.
 
1250
    """
 
1251
    if sys.platform == 'win32':
 
1252
        # No implementation to reliably determine Windows default mail
 
1253
        # address; please add one.
 
1254
        return None, None
 
1255
 
 
1256
    default_mail_domain = _get_default_mail_domain()
 
1257
    if not default_mail_domain:
 
1258
        return None, None
 
1259
 
 
1260
    import pwd
 
1261
    uid = os.getuid()
 
1262
    try:
 
1263
        w = pwd.getpwuid(uid)
 
1264
    except KeyError:
 
1265
        mutter('no passwd entry for uid %d?' % uid)
 
1266
        return None, None
 
1267
 
 
1268
    # we try utf-8 first, because on many variants (like Linux),
 
1269
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
 
1270
    # false positives.  (many users will have their user encoding set to
 
1271
    # latin-1, which cannot raise UnicodeError.)
 
1272
    try:
 
1273
        gecos = w.pw_gecos.decode('utf-8')
 
1274
        encoding = 'utf-8'
 
1275
    except UnicodeError:
 
1276
        try:
 
1277
            encoding = osutils.get_user_encoding()
 
1278
            gecos = w.pw_gecos.decode(encoding)
 
1279
        except UnicodeError, e:
 
1280
            mutter("cannot decode passwd entry %s" % w)
 
1281
            return None, None
 
1282
    try:
 
1283
        username = w.pw_name.decode(encoding)
 
1284
    except UnicodeError, e:
 
1285
        mutter("cannot decode passwd entry %s" % w)
 
1286
        return None, None
 
1287
 
 
1288
    comma = gecos.find(',')
 
1289
    if comma == -1:
 
1290
        realname = gecos
 
1291
    else:
 
1292
        realname = gecos[:comma]
 
1293
 
 
1294
    return realname, (username + '@' + default_mail_domain)
 
1295
 
 
1296
 
904
1297
def parse_username(username):
905
1298
    """Parse e-mail username and return a (name, address) tuple."""
906
1299
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
949
1342
 
950
1343
    def set_option(self, value, name, section=None):
951
1344
        """Set a per-branch configuration option"""
 
1345
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1346
        # higher levels providing the right lock -- vila 20101004
952
1347
        self.branch.lock_write()
953
1348
        try:
954
1349
            self._config.set_option(value, name, section)
955
1350
        finally:
956
1351
            self.branch.unlock()
957
1352
 
 
1353
    def remove_option(self, option_name, section_name=None):
 
1354
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1355
        # higher levels providing the right lock -- vila 20101004
 
1356
        self.branch.lock_write()
 
1357
        try:
 
1358
            self._config.remove_option(option_name, section_name)
 
1359
        finally:
 
1360
            self.branch.unlock()
 
1361
 
958
1362
 
959
1363
class AuthenticationConfig(object):
960
1364
    """The authentication configuration file based on a ini file.
1403
1807
    """A Config that reads/writes a config file on a Transport.
1404
1808
 
1405
1809
    It is a low-level object that considers config data to be name/value pairs
1406
 
    that may be associated with a section.  Assigning meaning to the these
1407
 
    values is done at higher levels like TreeConfig.
 
1810
    that may be associated with a section.  Assigning meaning to these values
 
1811
    is done at higher levels like TreeConfig.
1408
1812
    """
1409
1813
 
1410
1814
    def __init__(self, transport, filename):
1443
1847
            configobj.setdefault(section, {})[name] = value
1444
1848
        self._set_configobj(configobj)
1445
1849
 
 
1850
    def remove_option(self, option_name, section_name=None):
 
1851
        configobj = self._get_configobj()
 
1852
        if section_name is None:
 
1853
            del configobj[option_name]
 
1854
        else:
 
1855
            del configobj[section_name][option_name]
 
1856
        self._set_configobj(configobj)
 
1857
 
1446
1858
    def _get_config_file(self):
1447
1859
        try:
1448
1860
            return StringIO(self._transport.get_bytes(self._filename))
1461
1873
        configobj.write(out_file)
1462
1874
        out_file.seek(0)
1463
1875
        self._transport.put_file(self._filename, out_file)
 
1876
 
 
1877
 
 
1878
class cmd_config(commands.Command):
 
1879
    __doc__ = """Display, set or remove a configuration option.
 
1880
 
 
1881
    Display the active value for a given option.
 
1882
 
 
1883
    If --all is specified, NAME is interpreted as a regular expression and all
 
1884
    matching options are displayed mentioning their scope. The active value
 
1885
    that bzr will take into account is the first one displayed for each option.
 
1886
 
 
1887
    If no NAME is given, --all .* is implied.
 
1888
 
 
1889
    Setting a value is achieved by using name=value without spaces. The value
 
1890
    is set in the most relevant scope and can be checked by displaying the
 
1891
    option again.
 
1892
    """
 
1893
 
 
1894
    takes_args = ['name?']
 
1895
 
 
1896
    takes_options = [
 
1897
        'directory',
 
1898
        # FIXME: This should be a registry option so that plugins can register
 
1899
        # their own config files (or not) -- vila 20101002
 
1900
        commands.Option('scope', help='Reduce the scope to the specified'
 
1901
                        ' configuration file',
 
1902
                        type=unicode),
 
1903
        commands.Option('all',
 
1904
            help='Display all the defined values for the matching options.',
 
1905
            ),
 
1906
        commands.Option('remove', help='Remove the option from'
 
1907
                        ' the configuration file'),
 
1908
        ]
 
1909
 
 
1910
    @commands.display_command
 
1911
    def run(self, name=None, all=False, directory=None, scope=None,
 
1912
            remove=False):
 
1913
        if directory is None:
 
1914
            directory = '.'
 
1915
        directory = urlutils.normalize_url(directory)
 
1916
        if remove and all:
 
1917
            raise errors.BzrError(
 
1918
                '--all and --remove are mutually exclusive.')
 
1919
        elif remove:
 
1920
            # Delete the option in the given scope
 
1921
            self._remove_config_option(name, directory, scope)
 
1922
        elif name is None:
 
1923
            # Defaults to all options
 
1924
            self._show_matching_options('.*', directory, scope)
 
1925
        else:
 
1926
            try:
 
1927
                name, value = name.split('=', 1)
 
1928
            except ValueError:
 
1929
                # Display the option(s) value(s)
 
1930
                if all:
 
1931
                    self._show_matching_options(name, directory, scope)
 
1932
                else:
 
1933
                    self._show_value(name, directory, scope)
 
1934
            else:
 
1935
                if all:
 
1936
                    raise errors.BzrError(
 
1937
                        'Only one option can be set.')
 
1938
                # Set the option value
 
1939
                self._set_config_option(name, value, directory, scope)
 
1940
 
 
1941
    def _get_configs(self, directory, scope=None):
 
1942
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
1943
 
 
1944
        :param directory: Where the configurations are derived from.
 
1945
 
 
1946
        :param scope: A specific config to start from.
 
1947
        """
 
1948
        if scope is not None:
 
1949
            if scope == 'bazaar':
 
1950
                yield GlobalConfig()
 
1951
            elif scope == 'locations':
 
1952
                yield LocationConfig(directory)
 
1953
            elif scope == 'branch':
 
1954
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1955
                    directory)
 
1956
                yield br.get_config()
 
1957
        else:
 
1958
            try:
 
1959
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1960
                    directory)
 
1961
                yield br.get_config()
 
1962
            except errors.NotBranchError:
 
1963
                yield LocationConfig(directory)
 
1964
                yield GlobalConfig()
 
1965
 
 
1966
    def _show_value(self, name, directory, scope):
 
1967
        displayed = False
 
1968
        for c in self._get_configs(directory, scope):
 
1969
            if displayed:
 
1970
                break
 
1971
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1972
                if name == oname:
 
1973
                    # Display only the first value and exit
 
1974
 
 
1975
                    # FIXME: We need to use get_user_option to take policies
 
1976
                    # into account and we need to make sure the option exists
 
1977
                    # too (hence the two for loops), this needs a better API
 
1978
                    # -- vila 20101117
 
1979
                    value = c.get_user_option(name)
 
1980
                    # Quote the value appropriately
 
1981
                    value = parser._quote(value)
 
1982
                    self.outf.write('%s\n' % (value,))
 
1983
                    displayed = True
 
1984
                    break
 
1985
        if not displayed:
 
1986
            raise errors.NoSuchConfigOption(name)
 
1987
 
 
1988
    def _show_matching_options(self, name, directory, scope):
 
1989
        name = re.compile(name)
 
1990
        # We want any error in the regexp to be raised *now* so we need to
 
1991
        # avoid the delay introduced by the lazy regexp.
 
1992
        name._compile_and_collapse()
 
1993
        cur_conf_id = None
 
1994
        cur_section = None
 
1995
        for c in self._get_configs(directory, scope):
 
1996
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1997
                if name.search(oname):
 
1998
                    if cur_conf_id != conf_id:
 
1999
                        # Explain where the options are defined
 
2000
                        self.outf.write('%s:\n' % (conf_id,))
 
2001
                        cur_conf_id = conf_id
 
2002
                        cur_section = None
 
2003
                    if (section not in (None, 'DEFAULT')
 
2004
                        and cur_section != section):
 
2005
                        # Display the section if it's not the default (or only)
 
2006
                        # one.
 
2007
                        self.outf.write('  [%s]\n' % (section,))
 
2008
                        cur_section = section
 
2009
                    self.outf.write('  %s = %s\n' % (oname, value))
 
2010
 
 
2011
    def _set_config_option(self, name, value, directory, scope):
 
2012
        for conf in self._get_configs(directory, scope):
 
2013
            conf.set_user_option(name, value)
 
2014
            break
 
2015
        else:
 
2016
            raise errors.NoSuchConfig(scope)
 
2017
 
 
2018
    def _remove_config_option(self, name, directory, scope):
 
2019
        if name is None:
 
2020
            raise errors.BzrCommandError(
 
2021
                '--remove expects an option to remove.')
 
2022
        removed = False
 
2023
        for conf in self._get_configs(directory, scope):
 
2024
            for (section_name, section, conf_id) in conf._get_sections():
 
2025
                if scope is not None and conf_id != scope:
 
2026
                    # Not the right configuration file
 
2027
                    continue
 
2028
                if name in section:
 
2029
                    if conf_id != conf.config_id():
 
2030
                        conf = self._get_configs(directory, conf_id).next()
 
2031
                    # We use the first section in the first config where the
 
2032
                    # option is defined to remove it
 
2033
                    conf.remove_user_option(name, section_name)
 
2034
                    removed = True
 
2035
                    break
 
2036
            break
 
2037
        else:
 
2038
            raise errors.NoSuchConfig(scope)
 
2039
        if not removed:
 
2040
            raise errors.NoSuchConfigOption(name)