~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Andrew Bennetts
  • Date: 2011-01-06 06:26:23 UTC
  • mto: This revision was merged to the branch mainline in revision 5612.
  • Revision ID: andrew.bennetts@canonical.com-20110106062623-43tda58mqroybjui
Start of a developer doc describing how fetch works.

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
import os
66
66
import sys
67
67
 
 
68
from bzrlib import commands
 
69
from bzrlib.decorators import needs_write_lock
68
70
from bzrlib.lazy_import import lazy_import
69
71
lazy_import(globals(), """
70
72
import errno
71
 
from fnmatch import fnmatch
 
73
import fnmatch
72
74
import re
73
75
from cStringIO import StringIO
74
76
 
75
77
import bzrlib
76
78
from bzrlib import (
 
79
    atomicfile,
 
80
    bzrdir,
77
81
    debug,
78
82
    errors,
 
83
    lockdir,
79
84
    mail_client,
80
85
    osutils,
81
86
    registry,
82
87
    symbol_versioning,
83
88
    trace,
 
89
    transport,
84
90
    ui,
85
91
    urlutils,
86
92
    win32utils,
149
155
    def __init__(self):
150
156
        super(Config, self).__init__()
151
157
 
 
158
    def config_id(self):
 
159
        """Returns a unique ID for the config."""
 
160
        raise NotImplementedError(self.config_id)
 
161
 
152
162
    def get_editor(self):
153
163
        """Get the users pop up editor."""
154
164
        raise NotImplementedError
257
267
 
258
268
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
259
269
 
260
 
        $BZR_EMAIL can be set to override this (as well as the
261
 
        deprecated $BZREMAIL), then
 
270
        $BZR_EMAIL can be set to override this, then
262
271
        the concrete policy type is checked, and finally
263
272
        $EMAIL is examined.
264
 
        If none is found, a reasonable default is (hopefully)
265
 
        created.
 
273
        If no username can be found, errors.NoWhoami exception is raised.
266
274
 
267
275
        TODO: Check it's reasonably well-formed.
268
276
        """
278
286
        if v:
279
287
            return v.decode(osutils.get_user_encoding())
280
288
 
281
 
        name, email = _auto_user_id()
282
 
        if name:
283
 
            return '%s <%s>' % (name, email)
284
 
        else:
285
 
            return email
 
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()
286
297
 
287
298
    def signature_checking(self):
288
299
        """What is the current policy for signature checking?."""
350
361
class IniBasedConfig(Config):
351
362
    """A configuration policy that draws from ini files."""
352
363
 
353
 
    def __init__(self, get_filename):
 
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
        """
354
370
        super(IniBasedConfig, self).__init__()
355
 
        self._get_filename = get_filename
 
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
356
383
        self._parser = None
357
384
 
358
 
    def _get_parser(self, file=None):
 
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):
359
408
        if self._parser is not None:
360
409
            return self._parser
361
 
        if file is None:
362
 
            input = self._get_filename()
 
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')
363
420
        else:
364
 
            input = file
 
421
            co_input = self.file_name
365
422
        try:
366
 
            self._parser = ConfigObj(input, encoding='utf-8')
 
423
            self._parser = ConfigObj(co_input, encoding='utf-8')
367
424
        except configobj.ConfigObjError, e:
368
425
            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
369
428
        return self._parser
370
429
 
 
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
 
371
437
    def _get_matching_sections(self):
372
438
        """Return an ordered list of (section_name, extra_path) pairs.
373
439
 
384
450
        """Override this to define the section used by the config."""
385
451
        return "DEFAULT"
386
452
 
 
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
 
387
502
    def _get_option_policy(self, section, option_name):
388
503
        """Return the policy for the given (section, option_name) pair."""
389
504
        return POLICY_NONE
476
591
    def _get_nickname(self):
477
592
        return self.get_user_option('nickname')
478
593
 
479
 
 
480
 
class GlobalConfig(IniBasedConfig):
 
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):
481
696
    """The configuration that should be used for a specific location."""
482
697
 
 
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
 
483
717
    def get_editor(self):
484
718
        return self._get_user_option('editor')
485
719
 
486
 
    def __init__(self):
487
 
        super(GlobalConfig, self).__init__(config_filename)
488
 
 
 
720
    @needs_write_lock
489
721
    def set_user_option(self, option, value):
490
722
        """Save option and its value in the configuration."""
491
723
        self._set_option(option, value, 'DEFAULT')
497
729
        else:
498
730
            return {}
499
731
 
 
732
    @needs_write_lock
500
733
    def set_alias(self, alias_name, alias_command):
501
734
        """Save the alias in the configuration."""
502
735
        self._set_option(alias_name, alias_command, 'ALIASES')
503
736
 
 
737
    @needs_write_lock
504
738
    def unset_alias(self, alias_name):
505
739
        """Unset an existing alias."""
 
740
        self.reload()
506
741
        aliases = self._get_parser().get('ALIASES')
507
742
        if not aliases or alias_name not in aliases:
508
743
            raise errors.NoSuchAlias(alias_name)
510
745
        self._write_config_file()
511
746
 
512
747
    def _set_option(self, option, value, section):
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)
 
748
        self.reload()
517
749
        self._get_parser().setdefault(section, {})[option] = value
518
750
        self._write_config_file()
519
751
 
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):
 
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):
529
778
    """A configuration object that gives the policy for a location."""
530
779
 
531
780
    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)
 
781
        super(LocationConfig, self).__init__(
 
782
            file_name=locations_config_filename())
544
783
        # local file locations are looked up by local path, rather than
545
784
        # by file url. This is because the config file is a user
546
785
        # file, and we would rather not expose the user to file urls.
548
787
            location = urlutils.local_path_from_url(location)
549
788
        self.location = location
550
789
 
 
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
 
551
808
    def _get_matching_sections(self):
552
809
        """Return an ordered list of section names matching this location."""
553
810
        sections = self._get_parser()
570
827
            names = zip(location_names, section_names)
571
828
            matched = True
572
829
            for name in names:
573
 
                if not fnmatch(name[0], name[1]):
 
830
                if not fnmatch.fnmatch(name[0], name[1]):
574
831
                    matched = False
575
832
                    break
576
833
            if not matched:
581
838
                continue
582
839
            matches.append((len(section_names), section,
583
840
                            '/'.join(location_names[len(section_names):])))
 
841
        # put the longest (aka more specific) locations first
584
842
        matches.sort(reverse=True)
585
843
        sections = []
586
844
        for (length, section, extra_path) in matches:
593
851
                pass
594
852
        return sections
595
853
 
 
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
 
596
862
    def _get_option_policy(self, section, option_name):
597
863
        """Return the policy for the given (section, option_name) pair."""
598
864
        # check for the old 'recurse=False' flag
641
907
            if policy_key in self._get_parser()[section]:
642
908
                del self._get_parser()[section][policy_key]
643
909
 
 
910
    @needs_write_lock
644
911
    def set_user_option(self, option, value, store=STORE_LOCATION):
645
912
        """Save option and its value in the configuration."""
646
913
        if store not in [STORE_LOCATION,
648
915
                         STORE_LOCATION_APPENDPATH]:
649
916
            raise ValueError('bad storage policy %r for %r' %
650
917
                (store, option))
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)
 
918
        self.reload()
655
919
        location = self.location
656
920
        if location.endswith('/'):
657
921
            location = location[:-1]
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():
 
922
        parser = self._get_parser()
 
923
        if not location in parser and not location + '/' in parser:
 
924
            parser[location] = {}
 
925
        elif location + '/' in parser:
662
926
            location = location + '/'
663
 
        self._get_parser()[location][option]=value
 
927
        parser[location][option]=value
664
928
        # the allowed values of store match the config policies
665
929
        self._set_option_policy(location, option, store)
666
 
        self._get_parser().write(file(self._get_filename(), 'wb'))
 
930
        self._write_config_file()
667
931
 
668
932
 
669
933
class BranchConfig(Config):
670
934
    """A configuration object giving the policy for a branch."""
671
935
 
 
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
 
672
949
    def _get_branch_data_config(self):
673
950
        if self._branch_data_config is None:
674
951
            self._branch_data_config = TreeConfig(self.branch)
 
952
            self._branch_data_config.config_id = self.config_id
675
953
        return self._branch_data_config
676
954
 
677
955
    def _get_location_config(self):
745
1023
                return value
746
1024
        return None
747
1025
 
 
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
 
748
1052
    def set_user_option(self, name, value, store=STORE_BRANCH,
749
1053
        warn_masked=False):
750
1054
        if store == STORE_BRANCH:
768
1072
                        trace.warning('Value "%s" is masked by "%s" from'
769
1073
                                      ' branch.conf', value, mask_value)
770
1074
 
 
1075
    def remove_user_option(self, option_name, section_name=None):
 
1076
        self._get_branch_data_config().remove_option(option_name, section_name)
 
1077
 
771
1078
    def _gpg_signing_command(self):
772
1079
        """See Config.gpg_signing_command."""
773
1080
        return self._get_safe_value('_gpg_signing_command')
774
1081
 
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
1082
    def _post_commit(self):
786
1083
        """See Config.post_commit."""
787
1084
        return self._get_safe_value('_post_commit')
817
1114
            parent_dir = os.path.dirname(path)
818
1115
            if not os.path.isdir(parent_dir):
819
1116
                trace.mutter('creating config parent directory: %r', parent_dir)
820
 
            os.mkdir(parent_dir)
 
1117
                os.mkdir(parent_dir)
821
1118
        trace.mutter('creating config directory: %r', path)
822
1119
        os.mkdir(path)
823
1120
        osutils.copy_ownership_from_path(path)
826
1123
def config_dir():
827
1124
    """Return per-user configuration directory.
828
1125
 
829
 
    By default this is ~/.bazaar/
 
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.
830
1129
 
831
1130
    TODO: Global option --config-dir to override this.
832
1131
    """
840
1139
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
841
1140
                                  ' or HOME set')
842
1141
        return osutils.pathjoin(base, 'bazaar', '2.0')
 
1142
    elif sys.platform == 'darwin':
 
1143
        if base is None:
 
1144
            # this takes into account $HOME
 
1145
            base = os.path.expanduser("~")
 
1146
        return osutils.pathjoin(base, '.bazaar')
843
1147
    else:
844
 
        # cygwin, linux, and darwin all have a $HOME directory
845
1148
        if base is None:
 
1149
 
 
1150
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1151
            if xdg_dir is None:
 
1152
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1153
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1154
            if osutils.isdir(xdg_dir):
 
1155
                trace.mutter(
 
1156
                    "Using configuration in XDG directory %s." % xdg_dir)
 
1157
                return xdg_dir
 
1158
 
846
1159
            base = os.path.expanduser("~")
847
1160
        return osutils.pathjoin(base, ".bazaar")
848
1161
 
852
1165
    return osutils.pathjoin(config_dir(), 'bazaar.conf')
853
1166
 
854
1167
 
855
 
def branches_config_filename():
856
 
    """Return per-user configuration ini file filename."""
857
 
    return osutils.pathjoin(config_dir(), 'branches.conf')
858
 
 
859
 
 
860
1168
def locations_config_filename():
861
1169
    """Return per-user configuration ini file filename."""
862
1170
    return osutils.pathjoin(config_dir(), 'locations.conf')
899
1207
        return os.path.expanduser('~/.cache')
900
1208
 
901
1209
 
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
1210
def parse_username(username):
976
1211
    """Parse e-mail username and return a (name, address) tuple."""
977
1212
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1020
1255
 
1021
1256
    def set_option(self, value, name, section=None):
1022
1257
        """Set a per-branch configuration option"""
 
1258
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1259
        # higher levels providing the right lock -- vila 20101004
1023
1260
        self.branch.lock_write()
1024
1261
        try:
1025
1262
            self._config.set_option(value, name, section)
1026
1263
        finally:
1027
1264
            self.branch.unlock()
1028
1265
 
 
1266
    def remove_option(self, option_name, section_name=None):
 
1267
        # FIXME: We shouldn't need to lock explicitly here but rather rely on
 
1268
        # higher levels providing the right lock -- vila 20101004
 
1269
        self.branch.lock_write()
 
1270
        try:
 
1271
            self._config.remove_option(option_name, section_name)
 
1272
        finally:
 
1273
            self.branch.unlock()
 
1274
 
1029
1275
 
1030
1276
class AuthenticationConfig(object):
1031
1277
    """The authentication configuration file based on a ini file.
1063
1309
        """Save the config file, only tests should use it for now."""
1064
1310
        conf_dir = os.path.dirname(self._filename)
1065
1311
        ensure_config_dir_exists(conf_dir)
1066
 
        self._get_config().write(file(self._filename, 'wb'))
 
1312
        f = file(self._filename, 'wb')
 
1313
        try:
 
1314
            self._get_config().write(f)
 
1315
        finally:
 
1316
            f.close()
1067
1317
 
1068
1318
    def _set_option(self, section_name, option_name, value):
1069
1319
        """Set an authentication configuration option"""
1470
1720
    """A Config that reads/writes a config file on a Transport.
1471
1721
 
1472
1722
    It is a low-level object that considers config data to be name/value pairs
1473
 
    that may be associated with a section.  Assigning meaning to the these
1474
 
    values is done at higher levels like TreeConfig.
 
1723
    that may be associated with a section.  Assigning meaning to these values
 
1724
    is done at higher levels like TreeConfig.
1475
1725
    """
1476
1726
 
1477
1727
    def __init__(self, transport, filename):
1510
1760
            configobj.setdefault(section, {})[name] = value
1511
1761
        self._set_configobj(configobj)
1512
1762
 
 
1763
    def remove_option(self, option_name, section_name=None):
 
1764
        configobj = self._get_configobj()
 
1765
        if section_name is None:
 
1766
            del configobj[option_name]
 
1767
        else:
 
1768
            del configobj[section_name][option_name]
 
1769
        self._set_configobj(configobj)
 
1770
 
1513
1771
    def _get_config_file(self):
1514
1772
        try:
1515
1773
            return StringIO(self._transport.get_bytes(self._filename))
1517
1775
            return StringIO()
1518
1776
 
1519
1777
    def _get_configobj(self):
1520
 
        return ConfigObj(self._get_config_file(), encoding='utf-8')
 
1778
        f = self._get_config_file()
 
1779
        try:
 
1780
            return ConfigObj(f, encoding='utf-8')
 
1781
        finally:
 
1782
            f.close()
1521
1783
 
1522
1784
    def _set_configobj(self, configobj):
1523
1785
        out_file = StringIO()
1524
1786
        configobj.write(out_file)
1525
1787
        out_file.seek(0)
1526
1788
        self._transport.put_file(self._filename, out_file)
 
1789
 
 
1790
 
 
1791
class cmd_config(commands.Command):
 
1792
    __doc__ = """Display, set or remove a configuration option.
 
1793
 
 
1794
    Display the active value for a given option.
 
1795
 
 
1796
    If --all is specified, NAME is interpreted as a regular expression and all
 
1797
    matching options are displayed mentioning their scope. The active value
 
1798
    that bzr will take into account is the first one displayed for each option.
 
1799
 
 
1800
    If no NAME is given, --all .* is implied.
 
1801
 
 
1802
    Setting a value is achieved by using name=value without spaces. The value
 
1803
    is set in the most relevant scope and can be checked by displaying the
 
1804
    option again.
 
1805
    """
 
1806
 
 
1807
    takes_args = ['name?']
 
1808
 
 
1809
    takes_options = [
 
1810
        'directory',
 
1811
        # FIXME: This should be a registry option so that plugins can register
 
1812
        # their own config files (or not) -- vila 20101002
 
1813
        commands.Option('scope', help='Reduce the scope to the specified'
 
1814
                        ' configuration file',
 
1815
                        type=unicode),
 
1816
        commands.Option('all',
 
1817
            help='Display all the defined values for the matching options.',
 
1818
            ),
 
1819
        commands.Option('remove', help='Remove the option from'
 
1820
                        ' the configuration file'),
 
1821
        ]
 
1822
 
 
1823
    @commands.display_command
 
1824
    def run(self, name=None, all=False, directory=None, scope=None,
 
1825
            remove=False):
 
1826
        if directory is None:
 
1827
            directory = '.'
 
1828
        directory = urlutils.normalize_url(directory)
 
1829
        if remove and all:
 
1830
            raise errors.BzrError(
 
1831
                '--all and --remove are mutually exclusive.')
 
1832
        elif remove:
 
1833
            # Delete the option in the given scope
 
1834
            self._remove_config_option(name, directory, scope)
 
1835
        elif name is None:
 
1836
            # Defaults to all options
 
1837
            self._show_matching_options('.*', directory, scope)
 
1838
        else:
 
1839
            try:
 
1840
                name, value = name.split('=', 1)
 
1841
            except ValueError:
 
1842
                # Display the option(s) value(s)
 
1843
                if all:
 
1844
                    self._show_matching_options(name, directory, scope)
 
1845
                else:
 
1846
                    self._show_value(name, directory, scope)
 
1847
            else:
 
1848
                if all:
 
1849
                    raise errors.BzrError(
 
1850
                        'Only one option can be set.')
 
1851
                # Set the option value
 
1852
                self._set_config_option(name, value, directory, scope)
 
1853
 
 
1854
    def _get_configs(self, directory, scope=None):
 
1855
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
1856
 
 
1857
        :param directory: Where the configurations are derived from.
 
1858
 
 
1859
        :param scope: A specific config to start from.
 
1860
        """
 
1861
        if scope is not None:
 
1862
            if scope == 'bazaar':
 
1863
                yield GlobalConfig()
 
1864
            elif scope == 'locations':
 
1865
                yield LocationConfig(directory)
 
1866
            elif scope == 'branch':
 
1867
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1868
                    directory)
 
1869
                yield br.get_config()
 
1870
        else:
 
1871
            try:
 
1872
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1873
                    directory)
 
1874
                yield br.get_config()
 
1875
            except errors.NotBranchError:
 
1876
                yield LocationConfig(directory)
 
1877
                yield GlobalConfig()
 
1878
 
 
1879
    def _show_value(self, name, directory, scope):
 
1880
        displayed = False
 
1881
        for c in self._get_configs(directory, scope):
 
1882
            if displayed:
 
1883
                break
 
1884
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1885
                if name == oname:
 
1886
                    # Display only the first value and exit
 
1887
 
 
1888
                    # FIXME: We need to use get_user_option to take policies
 
1889
                    # into account and we need to make sure the option exists
 
1890
                    # too (hence the two for loops), this needs a better API
 
1891
                    # -- vila 20101117
 
1892
                    value = c.get_user_option(name)
 
1893
                    # Quote the value appropriately
 
1894
                    value = parser._quote(value)
 
1895
                    self.outf.write('%s\n' % (value,))
 
1896
                    displayed = True
 
1897
                    break
 
1898
        if not displayed:
 
1899
            raise errors.NoSuchConfigOption(name)
 
1900
 
 
1901
    def _show_matching_options(self, name, directory, scope):
 
1902
        name = re.compile(name)
 
1903
        # We want any error in the regexp to be raised *now* so we need to
 
1904
        # avoid the delay introduced by the lazy regexp.
 
1905
        name._compile_and_collapse()
 
1906
        cur_conf_id = None
 
1907
        cur_section = None
 
1908
        for c in self._get_configs(directory, scope):
 
1909
            for (oname, value, section, conf_id, parser) in c._get_options():
 
1910
                if name.search(oname):
 
1911
                    if cur_conf_id != conf_id:
 
1912
                        # Explain where the options are defined
 
1913
                        self.outf.write('%s:\n' % (conf_id,))
 
1914
                        cur_conf_id = conf_id
 
1915
                        cur_section = None
 
1916
                    if (section not in (None, 'DEFAULT')
 
1917
                        and cur_section != section):
 
1918
                        # Display the section if it's not the default (or only)
 
1919
                        # one.
 
1920
                        self.outf.write('  [%s]\n' % (section,))
 
1921
                        cur_section = section
 
1922
                    self.outf.write('  %s = %s\n' % (oname, value))
 
1923
 
 
1924
    def _set_config_option(self, name, value, directory, scope):
 
1925
        for conf in self._get_configs(directory, scope):
 
1926
            conf.set_user_option(name, value)
 
1927
            break
 
1928
        else:
 
1929
            raise errors.NoSuchConfig(scope)
 
1930
 
 
1931
    def _remove_config_option(self, name, directory, scope):
 
1932
        if name is None:
 
1933
            raise errors.BzrCommandError(
 
1934
                '--remove expects an option to remove.')
 
1935
        removed = False
 
1936
        for conf in self._get_configs(directory, scope):
 
1937
            for (section_name, section, conf_id) in conf._get_sections():
 
1938
                if scope is not None and conf_id != scope:
 
1939
                    # Not the right configuration file
 
1940
                    continue
 
1941
                if name in section:
 
1942
                    if conf_id != conf.config_id():
 
1943
                        conf = self._get_configs(directory, conf_id).next()
 
1944
                    # We use the first section in the first config where the
 
1945
                    # option is defined to remove it
 
1946
                    conf.remove_user_option(name, section_name)
 
1947
                    removed = True
 
1948
                    break
 
1949
            break
 
1950
        else:
 
1951
            raise errors.NoSuchConfig(scope)
 
1952
        if not removed:
 
1953
            raise errors.NoSuchConfigOption(name)