/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: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
65
65
import os
66
66
import sys
67
67
 
68
 
from bzrlib import commands
69
 
from bzrlib.decorators import needs_write_lock
70
68
from bzrlib.lazy_import import lazy_import
71
69
lazy_import(globals(), """
72
70
import errno
73
 
import fnmatch
 
71
from fnmatch import fnmatch
74
72
import re
75
73
from cStringIO import StringIO
76
74
 
77
75
import bzrlib
78
76
from bzrlib import (
79
 
    atomicfile,
80
 
    bzrdir,
81
77
    debug,
82
78
    errors,
83
 
    lockdir,
84
79
    mail_client,
85
80
    osutils,
86
81
    registry,
87
82
    symbol_versioning,
88
83
    trace,
89
 
    transport,
90
84
    ui,
91
85
    urlutils,
92
86
    win32utils,
155
149
    def __init__(self):
156
150
        super(Config, self).__init__()
157
151
 
158
 
    def config_id(self):
159
 
        """Returns a unique ID for the config."""
160
 
        raise NotImplementedError(self.config_id)
161
 
 
162
152
    def get_editor(self):
163
153
        """Get the users pop up editor."""
164
154
        raise NotImplementedError
267
257
 
268
258
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
269
259
 
270
 
        $BZR_EMAIL can be set to override this, then
 
260
        $BZR_EMAIL can be set to override this (as well as the
 
261
        deprecated $BZREMAIL), then
271
262
        the concrete policy type is checked, and finally
272
263
        $EMAIL is examined.
273
 
        If no username can be found, errors.NoWhoami exception is raised.
 
264
        If none is found, a reasonable default is (hopefully)
 
265
        created.
274
266
 
275
267
        TODO: Check it's reasonably well-formed.
276
268
        """
286
278
        if v:
287
279
            return v.decode(osutils.get_user_encoding())
288
280
 
289
 
        raise errors.NoWhoami()
290
 
 
291
 
    def ensure_username(self):
292
 
        """Raise errors.NoWhoami if username is not set.
293
 
 
294
 
        This method relies on the username() function raising the error.
295
 
        """
296
 
        self.username()
 
281
        name, email = _auto_user_id()
 
282
        if name:
 
283
            return '%s <%s>' % (name, email)
 
284
        else:
 
285
            return email
297
286
 
298
287
    def signature_checking(self):
299
288
        """What is the current policy for signature checking?."""
361
350
class IniBasedConfig(Config):
362
351
    """A configuration policy that draws from ini files."""
363
352
 
364
 
    def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
365
 
                 file_name=None):
366
 
        """Base class for configuration files using an ini-like syntax.
367
 
 
368
 
        :param file_name: The configuration file path.
369
 
        """
 
353
    def __init__(self, get_filename):
370
354
        super(IniBasedConfig, self).__init__()
371
 
        self.file_name = file_name
372
 
        if symbol_versioning.deprecated_passed(get_filename):
373
 
            symbol_versioning.warn(
374
 
                'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
375
 
                ' Use file_name instead.',
376
 
                DeprecationWarning,
377
 
                stacklevel=2)
378
 
            if get_filename is not None:
379
 
                self.file_name = get_filename()
380
 
        else:
381
 
            self.file_name = file_name
382
 
        self._content = None
 
355
        self._get_filename = get_filename
383
356
        self._parser = None
384
357
 
385
 
    @classmethod
386
 
    def from_string(cls, str_or_unicode, file_name=None, save=False):
387
 
        """Create a config object from a string.
388
 
 
389
 
        :param str_or_unicode: A string representing the file content. This will
390
 
            be utf-8 encoded.
391
 
 
392
 
        :param file_name: The configuration file path.
393
 
 
394
 
        :param _save: Whether the file should be saved upon creation.
395
 
        """
396
 
        conf = cls(file_name=file_name)
397
 
        conf._create_from_string(str_or_unicode, save)
398
 
        return conf
399
 
 
400
 
    def _create_from_string(self, str_or_unicode, save):
401
 
        self._content = StringIO(str_or_unicode.encode('utf-8'))
402
 
        # Some tests use in-memory configs, some other always need the config
403
 
        # file to exist on disk.
404
 
        if save:
405
 
            self._write_config_file()
406
 
 
407
 
    def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
 
358
    def _get_parser(self, file=None):
408
359
        if self._parser is not None:
409
360
            return self._parser
410
 
        if symbol_versioning.deprecated_passed(file):
411
 
            symbol_versioning.warn(
412
 
                'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
413
 
                ' Use IniBasedConfig(_content=xxx) instead.',
414
 
                DeprecationWarning,
415
 
                stacklevel=2)
416
 
        if self._content is not None:
417
 
            co_input = self._content
418
 
        elif self.file_name is None:
419
 
            raise AssertionError('We have no content to create the config')
 
361
        if file is None:
 
362
            input = self._get_filename()
420
363
        else:
421
 
            co_input = self.file_name
 
364
            input = file
422
365
        try:
423
 
            self._parser = ConfigObj(co_input, encoding='utf-8')
 
366
            self._parser = ConfigObj(input, encoding='utf-8')
424
367
        except configobj.ConfigObjError, e:
425
368
            raise errors.ParseConfigError(e.errors, e.config.filename)
426
 
        # Make sure self.reload() will use the right file name
427
 
        self._parser.filename = self.file_name
428
369
        return self._parser
429
370
 
430
 
    def reload(self):
431
 
        """Reload the config file from disk."""
432
 
        if self.file_name is None:
433
 
            raise AssertionError('We need a file name to reload the config')
434
 
        if self._parser is not None:
435
 
            self._parser.reload()
436
 
 
437
371
    def _get_matching_sections(self):
438
372
        """Return an ordered list of (section_name, extra_path) pairs.
439
373
 
450
384
        """Override this to define the section used by the config."""
451
385
        return "DEFAULT"
452
386
 
453
 
    def _get_sections(self, name=None):
454
 
        """Returns an iterator of the sections specified by ``name``.
455
 
 
456
 
        :param name: The section name. If None is supplied, the default
457
 
            configurations are yielded.
458
 
 
459
 
        :return: A tuple (name, section, config_id) for all sections that will
460
 
            be walked by user_get_option() in the 'right' order. The first one
461
 
            is where set_user_option() will update the value.
462
 
        """
463
 
        parser = self._get_parser()
464
 
        if name is not None:
465
 
            yield (name, parser[name], self.config_id())
466
 
        else:
467
 
            # No section name has been given so we fallback to the configobj
468
 
            # itself which holds the variables defined outside of any section.
469
 
            yield (None, parser, self.config_id())
470
 
 
471
 
    def _get_options(self, sections=None):
472
 
        """Return an ordered list of (name, value, section, config_id) tuples.
473
 
 
474
 
        All options are returned with their associated value and the section
475
 
        they appeared in. ``config_id`` is a unique identifier for the
476
 
        configuration file the option is defined in.
477
 
 
478
 
        :param sections: Default to ``_get_matching_sections`` if not
479
 
            specified. This gives a better control to daughter classes about
480
 
            which sections should be searched. This is a list of (name,
481
 
            configobj) tuples.
482
 
        """
483
 
        opts = []
484
 
        if sections is None:
485
 
            parser = self._get_parser()
486
 
            sections = []
487
 
            for (section_name, _) in self._get_matching_sections():
488
 
                try:
489
 
                    section = parser[section_name]
490
 
                except KeyError:
491
 
                    # This could happen for an empty file for which we define a
492
 
                    # DEFAULT section. FIXME: Force callers to provide sections
493
 
                    # instead ? -- vila 20100930
494
 
                    continue
495
 
                sections.append((section_name, section))
496
 
        config_id = self.config_id()
497
 
        for (section_name, section) in sections:
498
 
            for (name, value) in section.iteritems():
499
 
                yield (name, parser._quote(value), section_name,
500
 
                       config_id, parser)
501
 
 
502
387
    def _get_option_policy(self, section, option_name):
503
388
        """Return the policy for the given (section, option_name) pair."""
504
389
        return POLICY_NONE
591
476
    def _get_nickname(self):
592
477
        return self.get_user_option('nickname')
593
478
 
594
 
    def remove_user_option(self, option_name, section_name=None):
595
 
        """Remove a user option and save the configuration file.
596
 
 
597
 
        :param option_name: The option to be removed.
598
 
 
599
 
        :param section_name: The section the option is defined in, default to
600
 
            the default section.
601
 
        """
602
 
        self.reload()
603
 
        parser = self._get_parser()
604
 
        if section_name is None:
605
 
            section = parser
606
 
        else:
607
 
            section = parser[section_name]
608
 
        try:
609
 
            del section[option_name]
610
 
        except KeyError:
611
 
            raise errors.NoSuchConfigOption(option_name)
612
 
        self._write_config_file()
613
 
 
614
 
    def _write_config_file(self):
615
 
        if self.file_name is None:
616
 
            raise AssertionError('We cannot save, self.file_name is None')
617
 
        conf_dir = os.path.dirname(self.file_name)
618
 
        ensure_config_dir_exists(conf_dir)
619
 
        atomic_file = atomicfile.AtomicFile(self.file_name)
620
 
        self._get_parser().write(atomic_file)
621
 
        atomic_file.commit()
622
 
        atomic_file.close()
623
 
        osutils.copy_ownership_from_path(self.file_name)
624
 
 
625
 
 
626
 
class LockableConfig(IniBasedConfig):
627
 
    """A configuration needing explicit locking for access.
628
 
 
629
 
    If several processes try to write the config file, the accesses need to be
630
 
    serialized.
631
 
 
632
 
    Daughter classes should decorate all methods that update a config with the
633
 
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
634
 
    ``_write_config_file()`` method. These methods (typically ``set_option()``
635
 
    and variants must reload the config file from disk before calling
636
 
    ``_write_config_file()``), this can be achieved by calling the
637
 
    ``self.reload()`` method. Note that the lock scope should cover both the
638
 
    reading and the writing of the config file which is why the decorator can't
639
 
    be applied to ``_write_config_file()`` only.
640
 
 
641
 
    This should be enough to implement the following logic:
642
 
    - lock for exclusive write access,
643
 
    - reload the config file from disk,
644
 
    - set the new value
645
 
    - unlock
646
 
 
647
 
    This logic guarantees that a writer can update a value without erasing an
648
 
    update made by another writer.
649
 
    """
650
 
 
651
 
    lock_name = 'lock'
652
 
 
653
 
    def __init__(self, file_name):
654
 
        super(LockableConfig, self).__init__(file_name=file_name)
655
 
        self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
656
 
        self.transport = transport.get_transport(self.dir)
657
 
        self._lock = lockdir.LockDir(self.transport, 'lock')
658
 
 
659
 
    def _create_from_string(self, unicode_bytes, save):
660
 
        super(LockableConfig, self)._create_from_string(unicode_bytes, False)
661
 
        if save:
662
 
            # We need to handle the saving here (as opposed to IniBasedConfig)
663
 
            # to be able to lock
664
 
            self.lock_write()
665
 
            self._write_config_file()
666
 
            self.unlock()
667
 
 
668
 
    def lock_write(self, token=None):
669
 
        """Takes a write lock in the directory containing the config file.
670
 
 
671
 
        If the directory doesn't exist it is created.
672
 
        """
673
 
        ensure_config_dir_exists(self.dir)
674
 
        return self._lock.lock_write(token)
675
 
 
676
 
    def unlock(self):
677
 
        self._lock.unlock()
678
 
 
679
 
    def break_lock(self):
680
 
        self._lock.break_lock()
681
 
 
682
 
    @needs_write_lock
683
 
    def remove_user_option(self, option_name, section_name=None):
684
 
        super(LockableConfig, self).remove_user_option(option_name,
685
 
                                                       section_name)
686
 
 
687
 
    def _write_config_file(self):
688
 
        if self._lock is None or not self._lock.is_held:
689
 
            # NB: if the following exception is raised it probably means a
690
 
            # missing @needs_write_lock decorator on one of the callers.
691
 
            raise errors.ObjectNotLocked(self)
692
 
        super(LockableConfig, self)._write_config_file()
693
 
 
694
 
 
695
 
class GlobalConfig(LockableConfig):
 
479
 
 
480
class GlobalConfig(IniBasedConfig):
696
481
    """The configuration that should be used for a specific location."""
697
482
 
698
 
    def __init__(self):
699
 
        super(GlobalConfig, self).__init__(file_name=config_filename())
700
 
 
701
 
    def config_id(self):
702
 
        return 'bazaar'
703
 
 
704
 
    @classmethod
705
 
    def from_string(cls, str_or_unicode, save=False):
706
 
        """Create a config object from a string.
707
 
 
708
 
        :param str_or_unicode: A string representing the file content. This
709
 
            will be utf-8 encoded.
710
 
 
711
 
        :param save: Whether the file should be saved upon creation.
712
 
        """
713
 
        conf = cls()
714
 
        conf._create_from_string(str_or_unicode, save)
715
 
        return conf
716
 
 
717
483
    def get_editor(self):
718
484
        return self._get_user_option('editor')
719
485
 
720
 
    @needs_write_lock
 
486
    def __init__(self):
 
487
        super(GlobalConfig, self).__init__(config_filename)
 
488
 
721
489
    def set_user_option(self, option, value):
722
490
        """Save option and its value in the configuration."""
723
491
        self._set_option(option, value, 'DEFAULT')
729
497
        else:
730
498
            return {}
731
499
 
732
 
    @needs_write_lock
733
500
    def set_alias(self, alias_name, alias_command):
734
501
        """Save the alias in the configuration."""
735
502
        self._set_option(alias_name, alias_command, 'ALIASES')
736
503
 
737
 
    @needs_write_lock
738
504
    def unset_alias(self, alias_name):
739
505
        """Unset an existing alias."""
740
 
        self.reload()
741
506
        aliases = self._get_parser().get('ALIASES')
742
507
        if not aliases or alias_name not in aliases:
743
508
            raise errors.NoSuchAlias(alias_name)
745
510
        self._write_config_file()
746
511
 
747
512
    def _set_option(self, option, value, section):
748
 
        self.reload()
 
513
        # FIXME: RBC 20051029 This should refresh the parser and also take a
 
514
        # file lock on bazaar.conf.
 
515
        conf_dir = os.path.dirname(self._get_filename())
 
516
        ensure_config_dir_exists(conf_dir)
749
517
        self._get_parser().setdefault(section, {})[option] = value
750
518
        self._write_config_file()
751
519
 
752
 
 
753
 
    def _get_sections(self, name=None):
754
 
        """See IniBasedConfig._get_sections()."""
755
 
        parser = self._get_parser()
756
 
        # We don't give access to options defined outside of any section, we
757
 
        # used the DEFAULT section by... default.
758
 
        if name in (None, 'DEFAULT'):
759
 
            # This could happen for an empty file where the DEFAULT section
760
 
            # doesn't exist yet. So we force DEFAULT when yielding
761
 
            name = 'DEFAULT'
762
 
            if 'DEFAULT' not in parser:
763
 
               parser['DEFAULT']= {}
764
 
        yield (name, parser[name], self.config_id())
765
 
 
766
 
    @needs_write_lock
767
 
    def remove_user_option(self, option_name, section_name=None):
768
 
        if section_name is None:
769
 
            # We need to force the default section.
770
 
            section_name = 'DEFAULT'
771
 
        # We need to avoid the LockableConfig implementation or we'll lock
772
 
        # twice
773
 
        super(LockableConfig, self).remove_user_option(option_name,
774
 
                                                       section_name)
775
 
 
776
 
 
777
 
class LocationConfig(LockableConfig):
 
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
 
 
528
class LocationConfig(IniBasedConfig):
778
529
    """A configuration object that gives the policy for a location."""
779
530
 
780
531
    def __init__(self, location):
781
 
        super(LocationConfig, self).__init__(
782
 
            file_name=locations_config_filename())
 
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)
783
544
        # local file locations are looked up by local path, rather than
784
545
        # by file url. This is because the config file is a user
785
546
        # file, and we would rather not expose the user to file urls.
787
548
            location = urlutils.local_path_from_url(location)
788
549
        self.location = location
789
550
 
790
 
    def config_id(self):
791
 
        return 'locations'
792
 
 
793
 
    @classmethod
794
 
    def from_string(cls, str_or_unicode, location, save=False):
795
 
        """Create a config object from a string.
796
 
 
797
 
        :param str_or_unicode: A string representing the file content. This will
798
 
            be utf-8 encoded.
799
 
 
800
 
        :param location: The location url to filter the configuration.
801
 
 
802
 
        :param save: Whether the file should be saved upon creation.
803
 
        """
804
 
        conf = cls(location)
805
 
        conf._create_from_string(str_or_unicode, save)
806
 
        return conf
807
 
 
808
551
    def _get_matching_sections(self):
809
552
        """Return an ordered list of section names matching this location."""
810
553
        sections = self._get_parser()
827
570
            names = zip(location_names, section_names)
828
571
            matched = True
829
572
            for name in names:
830
 
                if not fnmatch.fnmatch(name[0], name[1]):
 
573
                if not fnmatch(name[0], name[1]):
831
574
                    matched = False
832
575
                    break
833
576
            if not matched:
838
581
                continue
839
582
            matches.append((len(section_names), section,
840
583
                            '/'.join(location_names[len(section_names):])))
841
 
        # put the longest (aka more specific) locations first
842
584
        matches.sort(reverse=True)
843
585
        sections = []
844
586
        for (length, section, extra_path) in matches:
851
593
                pass
852
594
        return sections
853
595
 
854
 
    def _get_sections(self, name=None):
855
 
        """See IniBasedConfig._get_sections()."""
856
 
        # We ignore the name here as the only sections handled are named with
857
 
        # the location path and we don't expose embedded sections either.
858
 
        parser = self._get_parser()
859
 
        for name, extra_path in self._get_matching_sections():
860
 
            yield (name, parser[name], self.config_id())
861
 
 
862
596
    def _get_option_policy(self, section, option_name):
863
597
        """Return the policy for the given (section, option_name) pair."""
864
598
        # check for the old 'recurse=False' flag
907
641
            if policy_key in self._get_parser()[section]:
908
642
                del self._get_parser()[section][policy_key]
909
643
 
910
 
    @needs_write_lock
911
644
    def set_user_option(self, option, value, store=STORE_LOCATION):
912
645
        """Save option and its value in the configuration."""
913
646
        if store not in [STORE_LOCATION,
915
648
                         STORE_LOCATION_APPENDPATH]:
916
649
            raise ValueError('bad storage policy %r for %r' %
917
650
                (store, option))
918
 
        self.reload()
 
651
        # FIXME: RBC 20051029 This should refresh the parser and also take a
 
652
        # file lock on locations.conf.
 
653
        conf_dir = os.path.dirname(self._get_filename())
 
654
        ensure_config_dir_exists(conf_dir)
919
655
        location = self.location
920
656
        if location.endswith('/'):
921
657
            location = location[:-1]
922
 
        parser = self._get_parser()
923
 
        if not location in parser and not location + '/' in parser:
924
 
            parser[location] = {}
925
 
        elif location + '/' in parser:
 
658
        if (not location in self._get_parser() and
 
659
            not location + '/' in self._get_parser()):
 
660
            self._get_parser()[location]={}
 
661
        elif location + '/' in self._get_parser():
926
662
            location = location + '/'
927
 
        parser[location][option]=value
 
663
        self._get_parser()[location][option]=value
928
664
        # the allowed values of store match the config policies
929
665
        self._set_option_policy(location, option, store)
930
 
        self._write_config_file()
 
666
        self._get_parser().write(file(self._get_filename(), 'wb'))
931
667
 
932
668
 
933
669
class BranchConfig(Config):
934
670
    """A configuration object giving the policy for a branch."""
935
671
 
936
 
    def __init__(self, branch):
937
 
        super(BranchConfig, self).__init__()
938
 
        self._location_config = None
939
 
        self._branch_data_config = None
940
 
        self._global_config = None
941
 
        self.branch = branch
942
 
        self.option_sources = (self._get_location_config,
943
 
                               self._get_branch_data_config,
944
 
                               self._get_global_config)
945
 
 
946
 
    def config_id(self):
947
 
        return 'branch'
948
 
 
949
672
    def _get_branch_data_config(self):
950
673
        if self._branch_data_config is None:
951
674
            self._branch_data_config = TreeConfig(self.branch)
952
 
            self._branch_data_config.config_id = self.config_id
953
675
        return self._branch_data_config
954
676
 
955
677
    def _get_location_config(self):
1023
745
                return value
1024
746
        return None
1025
747
 
1026
 
    def _get_sections(self, name=None):
1027
 
        """See IniBasedConfig.get_sections()."""
1028
 
        for source in self.option_sources:
1029
 
            for section in source()._get_sections(name):
1030
 
                yield section
1031
 
 
1032
 
    def _get_options(self, sections=None):
1033
 
        opts = []
1034
 
        # First the locations options
1035
 
        for option in self._get_location_config()._get_options():
1036
 
            yield option
1037
 
        # Then the branch options
1038
 
        branch_config = self._get_branch_data_config()
1039
 
        if sections is None:
1040
 
            sections = [('DEFAULT', branch_config._get_parser())]
1041
 
        # FIXME: We shouldn't have to duplicate the code in IniBasedConfig but
1042
 
        # Config itself has no notion of sections :( -- vila 20101001
1043
 
        config_id = self.config_id()
1044
 
        for (section_name, section) in sections:
1045
 
            for (name, value) in section.iteritems():
1046
 
                yield (name, value, section_name,
1047
 
                       config_id, branch_config._get_parser())
1048
 
        # Then the global options
1049
 
        for option in self._get_global_config()._get_options():
1050
 
            yield option
1051
 
 
1052
748
    def set_user_option(self, name, value, store=STORE_BRANCH,
1053
749
        warn_masked=False):
1054
750
        if store == STORE_BRANCH:
1072
768
                        trace.warning('Value "%s" is masked by "%s" from'
1073
769
                                      ' branch.conf', value, mask_value)
1074
770
 
1075
 
    def remove_user_option(self, option_name, section_name=None):
1076
 
        self._get_branch_data_config().remove_option(option_name, section_name)
1077
 
 
1078
771
    def _gpg_signing_command(self):
1079
772
        """See Config.gpg_signing_command."""
1080
773
        return self._get_safe_value('_gpg_signing_command')
1081
774
 
 
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
 
1082
785
    def _post_commit(self):
1083
786
        """See Config.post_commit."""
1084
787
        return self._get_safe_value('_post_commit')
1114
817
            parent_dir = os.path.dirname(path)
1115
818
            if not os.path.isdir(parent_dir):
1116
819
                trace.mutter('creating config parent directory: %r', parent_dir)
1117
 
                os.mkdir(parent_dir)
 
820
            os.mkdir(parent_dir)
1118
821
        trace.mutter('creating config directory: %r', path)
1119
822
        os.mkdir(path)
1120
823
        osutils.copy_ownership_from_path(path)
1123
826
def config_dir():
1124
827
    """Return per-user configuration directory.
1125
828
 
1126
 
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1127
 
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1128
 
    that will be used instead.
 
829
    By default this is ~/.bazaar/
1129
830
 
1130
831
    TODO: Global option --config-dir to override this.
1131
832
    """
1132
833
    base = os.environ.get('BZR_HOME', None)
1133
834
    if sys.platform == 'win32':
1134
 
        # environ variables on Windows are in user encoding/mbcs. So decode
1135
 
        # before using one
1136
 
        if base is not None:
1137
 
            base = base.decode('mbcs')
1138
835
        if base is None:
1139
836
            base = win32utils.get_appdata_location_unicode()
1140
837
        if base is None:
1141
838
            base = os.environ.get('HOME', None)
1142
 
            if base is not None:
1143
 
                base = base.decode('mbcs')
1144
839
        if base is None:
1145
840
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1146
841
                                  ' or HOME set')
1147
842
        return osutils.pathjoin(base, 'bazaar', '2.0')
1148
 
    elif sys.platform == 'darwin':
1149
 
        if base is None:
1150
 
            # this takes into account $HOME
1151
 
            base = os.path.expanduser("~")
1152
 
        return osutils.pathjoin(base, '.bazaar')
1153
843
    else:
 
844
        # cygwin, linux, and darwin all have a $HOME directory
1154
845
        if base is None:
1155
 
 
1156
 
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1157
 
            if xdg_dir is None:
1158
 
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1159
 
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1160
 
            if osutils.isdir(xdg_dir):
1161
 
                trace.mutter(
1162
 
                    "Using configuration in XDG directory %s." % xdg_dir)
1163
 
                return xdg_dir
1164
 
 
1165
846
            base = os.path.expanduser("~")
1166
847
        return osutils.pathjoin(base, ".bazaar")
1167
848
 
1171
852
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
1172
853
 
1173
854
 
 
855
def branches_config_filename():
 
856
    """Return per-user configuration ini file filename."""
 
857
    return osutils.pathjoin(config_dir(), 'branches.conf')
 
858
 
 
859
 
1174
860
def locations_config_filename():
1175
861
    """Return per-user configuration ini file filename."""
1176
862
    return osutils.pathjoin(config_dir(), 'locations.conf')
1213
899
        return os.path.expanduser('~/.cache')
1214
900
 
1215
901
 
 
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
 
1216
975
def parse_username(username):
1217
976
    """Parse e-mail username and return a (name, address) tuple."""
1218
977
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1261
1020
 
1262
1021
    def set_option(self, value, name, section=None):
1263
1022
        """Set a per-branch configuration option"""
1264
 
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
1265
 
        # higher levels providing the right lock -- vila 20101004
1266
1023
        self.branch.lock_write()
1267
1024
        try:
1268
1025
            self._config.set_option(value, name, section)
1269
1026
        finally:
1270
1027
            self.branch.unlock()
1271
1028
 
1272
 
    def remove_option(self, option_name, section_name=None):
1273
 
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
1274
 
        # higher levels providing the right lock -- vila 20101004
1275
 
        self.branch.lock_write()
1276
 
        try:
1277
 
            self._config.remove_option(option_name, section_name)
1278
 
        finally:
1279
 
            self.branch.unlock()
1280
 
 
1281
1029
 
1282
1030
class AuthenticationConfig(object):
1283
1031
    """The authentication configuration file based on a ini file.
1315
1063
        """Save the config file, only tests should use it for now."""
1316
1064
        conf_dir = os.path.dirname(self._filename)
1317
1065
        ensure_config_dir_exists(conf_dir)
1318
 
        f = file(self._filename, 'wb')
1319
 
        try:
1320
 
            self._get_config().write(f)
1321
 
        finally:
1322
 
            f.close()
 
1066
        self._get_config().write(file(self._filename, 'wb'))
1323
1067
 
1324
1068
    def _set_option(self, section_name, option_name, value):
1325
1069
        """Set an authentication configuration option"""
1726
1470
    """A Config that reads/writes a config file on a Transport.
1727
1471
 
1728
1472
    It is a low-level object that considers config data to be name/value pairs
1729
 
    that may be associated with a section.  Assigning meaning to these values
1730
 
    is done at higher levels like TreeConfig.
 
1473
    that may be associated with a section.  Assigning meaning to the these
 
1474
    values is done at higher levels like TreeConfig.
1731
1475
    """
1732
1476
 
1733
1477
    def __init__(self, transport, filename):
1766
1510
            configobj.setdefault(section, {})[name] = value
1767
1511
        self._set_configobj(configobj)
1768
1512
 
1769
 
    def remove_option(self, option_name, section_name=None):
1770
 
        configobj = self._get_configobj()
1771
 
        if section_name is None:
1772
 
            del configobj[option_name]
1773
 
        else:
1774
 
            del configobj[section_name][option_name]
1775
 
        self._set_configobj(configobj)
1776
 
 
1777
1513
    def _get_config_file(self):
1778
1514
        try:
1779
1515
            return StringIO(self._transport.get_bytes(self._filename))
1781
1517
            return StringIO()
1782
1518
 
1783
1519
    def _get_configobj(self):
1784
 
        f = self._get_config_file()
1785
 
        try:
1786
 
            return ConfigObj(f, encoding='utf-8')
1787
 
        finally:
1788
 
            f.close()
 
1520
        return ConfigObj(self._get_config_file(), encoding='utf-8')
1789
1521
 
1790
1522
    def _set_configobj(self, configobj):
1791
1523
        out_file = StringIO()
1792
1524
        configobj.write(out_file)
1793
1525
        out_file.seek(0)
1794
1526
        self._transport.put_file(self._filename, out_file)
1795
 
 
1796
 
 
1797
 
class cmd_config(commands.Command):
1798
 
    __doc__ = """Display, set or remove a configuration option.
1799
 
 
1800
 
    Display the active value for a given option.
1801
 
 
1802
 
    If --all is specified, NAME is interpreted as a regular expression and all
1803
 
    matching options are displayed mentioning their scope. The active value
1804
 
    that bzr will take into account is the first one displayed for each option.
1805
 
 
1806
 
    If no NAME is given, --all .* is implied.
1807
 
 
1808
 
    Setting a value is achieved by using name=value without spaces. The value
1809
 
    is set in the most relevant scope and can be checked by displaying the
1810
 
    option again.
1811
 
    """
1812
 
 
1813
 
    takes_args = ['name?']
1814
 
 
1815
 
    takes_options = [
1816
 
        'directory',
1817
 
        # FIXME: This should be a registry option so that plugins can register
1818
 
        # their own config files (or not) -- vila 20101002
1819
 
        commands.Option('scope', help='Reduce the scope to the specified'
1820
 
                        ' configuration file',
1821
 
                        type=unicode),
1822
 
        commands.Option('all',
1823
 
            help='Display all the defined values for the matching options.',
1824
 
            ),
1825
 
        commands.Option('remove', help='Remove the option from'
1826
 
                        ' the configuration file'),
1827
 
        ]
1828
 
 
1829
 
    @commands.display_command
1830
 
    def run(self, name=None, all=False, directory=None, scope=None,
1831
 
            remove=False):
1832
 
        if directory is None:
1833
 
            directory = '.'
1834
 
        directory = urlutils.normalize_url(directory)
1835
 
        if remove and all:
1836
 
            raise errors.BzrError(
1837
 
                '--all and --remove are mutually exclusive.')
1838
 
        elif remove:
1839
 
            # Delete the option in the given scope
1840
 
            self._remove_config_option(name, directory, scope)
1841
 
        elif name is None:
1842
 
            # Defaults to all options
1843
 
            self._show_matching_options('.*', directory, scope)
1844
 
        else:
1845
 
            try:
1846
 
                name, value = name.split('=', 1)
1847
 
            except ValueError:
1848
 
                # Display the option(s) value(s)
1849
 
                if all:
1850
 
                    self._show_matching_options(name, directory, scope)
1851
 
                else:
1852
 
                    self._show_value(name, directory, scope)
1853
 
            else:
1854
 
                if all:
1855
 
                    raise errors.BzrError(
1856
 
                        'Only one option can be set.')
1857
 
                # Set the option value
1858
 
                self._set_config_option(name, value, directory, scope)
1859
 
 
1860
 
    def _get_configs(self, directory, scope=None):
1861
 
        """Iterate the configurations specified by ``directory`` and ``scope``.
1862
 
 
1863
 
        :param directory: Where the configurations are derived from.
1864
 
 
1865
 
        :param scope: A specific config to start from.
1866
 
        """
1867
 
        if scope is not None:
1868
 
            if scope == 'bazaar':
1869
 
                yield GlobalConfig()
1870
 
            elif scope == 'locations':
1871
 
                yield LocationConfig(directory)
1872
 
            elif scope == 'branch':
1873
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
1874
 
                    directory)
1875
 
                yield br.get_config()
1876
 
        else:
1877
 
            try:
1878
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
1879
 
                    directory)
1880
 
                yield br.get_config()
1881
 
            except errors.NotBranchError:
1882
 
                yield LocationConfig(directory)
1883
 
                yield GlobalConfig()
1884
 
 
1885
 
    def _show_value(self, name, directory, scope):
1886
 
        displayed = False
1887
 
        for c in self._get_configs(directory, scope):
1888
 
            if displayed:
1889
 
                break
1890
 
            for (oname, value, section, conf_id, parser) in c._get_options():
1891
 
                if name == oname:
1892
 
                    # Display only the first value and exit
1893
 
 
1894
 
                    # FIXME: We need to use get_user_option to take policies
1895
 
                    # into account and we need to make sure the option exists
1896
 
                    # too (hence the two for loops), this needs a better API
1897
 
                    # -- vila 20101117
1898
 
                    value = c.get_user_option(name)
1899
 
                    # Quote the value appropriately
1900
 
                    value = parser._quote(value)
1901
 
                    self.outf.write('%s\n' % (value,))
1902
 
                    displayed = True
1903
 
                    break
1904
 
        if not displayed:
1905
 
            raise errors.NoSuchConfigOption(name)
1906
 
 
1907
 
    def _show_matching_options(self, name, directory, scope):
1908
 
        name = re.compile(name)
1909
 
        # We want any error in the regexp to be raised *now* so we need to
1910
 
        # avoid the delay introduced by the lazy regexp.
1911
 
        name._compile_and_collapse()
1912
 
        cur_conf_id = None
1913
 
        cur_section = None
1914
 
        for c in self._get_configs(directory, scope):
1915
 
            for (oname, value, section, conf_id, parser) in c._get_options():
1916
 
                if name.search(oname):
1917
 
                    if cur_conf_id != conf_id:
1918
 
                        # Explain where the options are defined
1919
 
                        self.outf.write('%s:\n' % (conf_id,))
1920
 
                        cur_conf_id = conf_id
1921
 
                        cur_section = None
1922
 
                    if (section not in (None, 'DEFAULT')
1923
 
                        and cur_section != section):
1924
 
                        # Display the section if it's not the default (or only)
1925
 
                        # one.
1926
 
                        self.outf.write('  [%s]\n' % (section,))
1927
 
                        cur_section = section
1928
 
                    self.outf.write('  %s = %s\n' % (oname, value))
1929
 
 
1930
 
    def _set_config_option(self, name, value, directory, scope):
1931
 
        for conf in self._get_configs(directory, scope):
1932
 
            conf.set_user_option(name, value)
1933
 
            break
1934
 
        else:
1935
 
            raise errors.NoSuchConfig(scope)
1936
 
 
1937
 
    def _remove_config_option(self, name, directory, scope):
1938
 
        if name is None:
1939
 
            raise errors.BzrCommandError(
1940
 
                '--remove expects an option to remove.')
1941
 
        removed = False
1942
 
        for conf in self._get_configs(directory, scope):
1943
 
            for (section_name, section, conf_id) in conf._get_sections():
1944
 
                if scope is not None and conf_id != scope:
1945
 
                    # Not the right configuration file
1946
 
                    continue
1947
 
                if name in section:
1948
 
                    if conf_id != conf.config_id():
1949
 
                        conf = self._get_configs(directory, conf_id).next()
1950
 
                    # We use the first section in the first config where the
1951
 
                    # option is defined to remove it
1952
 
                    conf.remove_user_option(name, section_name)
1953
 
                    removed = True
1954
 
                    break
1955
 
            break
1956
 
        else:
1957
 
            raise errors.NoSuchConfig(scope)
1958
 
        if not removed:
1959
 
            raise errors.NoSuchConfigOption(name)