~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

Merge in bzr-dir phase 3, enabling controlled upgrades and shared repositories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
84
84
        """Construct the current default format repository in a_bzrdir."""
85
85
        return RepositoryFormat.get_default_format().initialize(a_bzrdir)
86
86
 
87
 
    def __init__(self, transport, branch_format, _format=None, a_bzrdir=None):
 
87
    def __init__(self, _format, a_bzrdir):
88
88
        object.__init__(self)
89
 
        if transport is not None:
90
 
            warn("Repository.__init__(..., transport=XXX): The transport parameter is "
91
 
                 "deprecated and was never in a supported release. Please use "
92
 
                 "bzrdir.open_repository() or bzrdir.open_branch().repository.",
93
 
                 DeprecationWarning,
94
 
                 stacklevel=2)
95
 
            self.control_files = LockableFiles(transport.clone(bzrlib.BZRDIR), 'README')
96
 
        else: 
97
 
            # TODO: clone into repository if needed
98
 
            self.control_files = LockableFiles(a_bzrdir.get_repository_transport(None), 'README')
 
89
        if isinstance(_format, (RepositoryFormat4,
 
90
                                RepositoryFormat5,
 
91
                                RepositoryFormat6)):
 
92
            # legacy: use a common control files.
 
93
            self.control_files = a_bzrdir._control_files
 
94
        else:
 
95
            self.control_files = LockableFiles(a_bzrdir.get_repository_transport(None),
 
96
                                               'lock')
99
97
 
100
98
        dir_mode = self.control_files._dir_mode
101
99
        file_mode = self.control_files._file_mode
116
114
                ws.enable_cache = True
117
115
            return ws
118
116
 
119
 
 
120
117
        def get_store(name, compressed=True, prefixed=False):
121
118
            # FIXME: This approach of assuming stores are all entirely compressed
122
119
            # or entirely uncompressed is tidy, but breaks upgrade from 
137
134
            #    store = bzrlib.store.CachedStore(store, cache_path)
138
135
            return store
139
136
 
140
 
        if branch_format is not None:
141
 
            # circular dependencies:
142
 
            from bzrlib.branch import (BzrBranchFormat4,
143
 
                                       BzrBranchFormat5,
144
 
                                       BzrBranchFormat6,
145
 
                                       )
146
 
            if isinstance(branch_format, BzrBranchFormat4):
147
 
                self._format = RepositoryFormat4()
148
 
            elif isinstance(branch_format, BzrBranchFormat5):
149
 
                self._format = RepositoryFormat5()
150
 
            elif isinstance(branch_format, BzrBranchFormat6):
151
 
                self._format = RepositoryFormat6()
152
 
            
153
 
 
154
137
        if isinstance(self._format, RepositoryFormat4):
155
138
            self.inventory_store = get_store('inventory-store')
156
139
            self.text_store = get_store('text-store')
254
237
 
255
238
    @needs_read_lock
256
239
    def copy_content_into(self, destination, revision_id=None, basis=None):
257
 
        """Make a complete copy of the content in self into destination."""
 
240
        """Make a complete copy of the content in self into destination.
 
241
        
 
242
        This is a destructive operation! Do not use it on existing 
 
243
        repositories.
 
244
        """
258
245
        destination.lock_write()
259
246
        try:
 
247
            try:
 
248
                destination.set_make_working_trees(self.make_working_trees())
 
249
            except NotImplementedError:
 
250
                pass
260
251
            # optimised paths:
261
252
            # compatible stores
262
253
            if self._compatible_formats(destination):
326
317
                       bzrdir.BzrDirFormat6)):
327
318
            result = a_bzrdir.open_repository()
328
319
        else:
329
 
            result = self._format.initialize(a_bzrdir)
 
320
            result = self._format.initialize(a_bzrdir, shared=self.is_shared())
330
321
        self.copy_content_into(result, revision_id, basis)
331
322
        return result
332
323
 
518
509
            return self.get_inventory(revision_id)
519
510
 
520
511
    @needs_read_lock
 
512
    def is_shared(self):
 
513
        """Return True if this repository is flagged as a shared repository."""
 
514
        # FIXME format 4-6 cannot be shared, this is technically faulty.
 
515
        return self.control_files._transport.has('shared-storage')
 
516
 
 
517
    @needs_read_lock
521
518
    def revision_tree(self, revision_id):
522
519
        """Return Tree for a revision on this branch.
523
520
 
574
571
        return self.control_files.get_transaction()
575
572
 
576
573
    @needs_write_lock
 
574
    def set_make_working_trees(self, new_value):
 
575
        """Set the policy flag for making working trees when creating branches.
 
576
 
 
577
        This only applies to branches that use this repository.
 
578
 
 
579
        The default is 'True'.
 
580
        :param new_value: True to restore the default, False to disable making
 
581
                          working trees.
 
582
        """
 
583
        # FIXME: split out into a new class/strategy ?
 
584
        if isinstance(self._format, (RepositoryFormat4,
 
585
                                     RepositoryFormat5,
 
586
                                     RepositoryFormat6)):
 
587
            raise NotImplementedError(self.set_make_working_trees)
 
588
        if new_value:
 
589
            try:
 
590
                self.control_files._transport.delete('no-working-trees')
 
591
            except errors.NoSuchFile:
 
592
                pass
 
593
        else:
 
594
            self.control_files.put_utf8('no-working-trees', '')
 
595
    
 
596
    def make_working_trees(self):
 
597
        """Returns the policy for making working trees on new branches."""
 
598
        # FIXME: split out into a new class/strategy ?
 
599
        if isinstance(self._format, (RepositoryFormat4,
 
600
                                     RepositoryFormat5,
 
601
                                     RepositoryFormat6)):
 
602
            return True
 
603
        return not self.control_files._transport.has('no-working-trees')
 
604
 
 
605
    @needs_write_lock
577
606
    def sign_revision(self, revision_id, gpg_strategy):
578
607
        plaintext = Testament.from_revision(self, revision_id).as_short_text()
579
608
        self.store_revision_signature(gpg_strategy, plaintext, revision_id)
634
663
        """
635
664
        raise NotImplementedError(self.get_format_string)
636
665
 
637
 
    def initialize(self, a_bzrdir, _internal=False):
638
 
        """Create a weave repository.
639
 
        
640
 
        TODO: when creating split out bzr branch formats, move this to a common
641
 
        base for Format5, Format6. or something like that.
 
666
    def initialize(self, a_bzrdir, shared=False):
 
667
        """Initialize a repository of this format in a_bzrdir.
 
668
 
 
669
        :param a_bzrdir: The bzrdir to put the new repository in it.
 
670
        :param shared: The repository should be initialized as a sharable one.
 
671
 
 
672
        This may raise UninitializableFormat if shared repository are not
 
673
        compatible the a_bzrdir.
642
674
        """
643
 
        from bzrlib.weavefile import write_weave_v5
644
 
        from bzrlib.weave import Weave
645
 
 
646
 
        if not _internal:
647
 
            # always initialized when the bzrdir is.
648
 
            return Repository(None, branch_format=None, _format=self, a_bzrdir=a_bzrdir)
649
 
        
650
 
        # Create an empty weave
651
 
        sio = StringIO()
652
 
        bzrlib.weavefile.write_weave_v5(Weave(), sio)
653
 
        empty_weave = sio.getvalue()
654
 
 
655
 
        mutter('creating repository in %s.', a_bzrdir.transport.base)
656
 
        dirs = ['revision-store', 'weaves']
657
 
        lock_file = 'branch-lock'
658
 
        files = [('inventory.weave', StringIO(empty_weave)), 
659
 
                 ]
660
 
        
661
 
        # FIXME: RBC 20060125 dont peek under the covers
662
 
        # NB: no need to escape relative paths that are url safe.
663
 
        control_files = LockableFiles(a_bzrdir.transport, 'branch-lock')
664
 
        control_files.lock_write()
665
 
        control_files._transport.mkdir_multi(dirs,
666
 
                mode=control_files._dir_mode)
667
 
        try:
668
 
            for file, content in files:
669
 
                control_files.put(file, content)
670
 
        finally:
671
 
            control_files.unlock()
672
 
        return Repository(None, branch_format=None, _format=self, a_bzrdir=a_bzrdir)
673
675
 
674
676
    def is_supported(self):
675
677
        """Is this format supported?
688
690
        if not _found:
689
691
            # we are being called directly and must probe.
690
692
            raise NotImplementedError
691
 
        return Repository(None, branch_format=None, _format=self, a_bzrdir=a_bzrdir)
 
693
        return Repository(_format=self, a_bzrdir=a_bzrdir)
692
694
 
693
695
    @classmethod
694
696
    def register_format(klass, format):
704
706
        del klass._formats[format.get_format_string()]
705
707
 
706
708
 
707
 
class RepositoryFormat4(RepositoryFormat):
 
709
class PreSplitOutRepositoryFormat(RepositoryFormat):
 
710
    """Base class for the pre split out repository formats."""
 
711
 
 
712
    def initialize(self, a_bzrdir, shared=False, _internal=False):
 
713
        """Create a weave repository.
 
714
        
 
715
        TODO: when creating split out bzr branch formats, move this to a common
 
716
        base for Format5, Format6. or something like that.
 
717
        """
 
718
        from bzrlib.weavefile import write_weave_v5
 
719
        from bzrlib.weave import Weave
 
720
 
 
721
        if shared:
 
722
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
 
723
 
 
724
        if not _internal:
 
725
            # always initialized when the bzrdir is.
 
726
            return Repository(_format=self, a_bzrdir=a_bzrdir)
 
727
        
 
728
        # Create an empty weave
 
729
        sio = StringIO()
 
730
        bzrlib.weavefile.write_weave_v5(Weave(), sio)
 
731
        empty_weave = sio.getvalue()
 
732
 
 
733
        mutter('creating repository in %s.', a_bzrdir.transport.base)
 
734
        dirs = ['revision-store', 'weaves']
 
735
        lock_file = 'branch-lock'
 
736
        files = [('inventory.weave', StringIO(empty_weave)), 
 
737
                 ]
 
738
        
 
739
        # FIXME: RBC 20060125 dont peek under the covers
 
740
        # NB: no need to escape relative paths that are url safe.
 
741
        control_files = LockableFiles(a_bzrdir.transport, 'branch-lock')
 
742
        control_files.lock_write()
 
743
        control_files._transport.mkdir_multi(dirs,
 
744
                mode=control_files._dir_mode)
 
745
        try:
 
746
            for file, content in files:
 
747
                control_files.put(file, content)
 
748
        finally:
 
749
            control_files.unlock()
 
750
        return Repository(_format=self, a_bzrdir=a_bzrdir)
 
751
 
 
752
 
 
753
class RepositoryFormat4(PreSplitOutRepositoryFormat):
708
754
    """Bzr repository format 4.
709
755
 
710
756
    This repository format has:
720
766
        super(RepositoryFormat4, self).__init__()
721
767
        self._matchingbzrdir = bzrdir.BzrDirFormat4()
722
768
 
723
 
    def initialize(self, url, _internal=False):
 
769
    def initialize(self, url, shared=False, _internal=False):
724
770
        """Format 4 branches cannot be created."""
725
771
        raise errors.UninitializableFormat(self)
726
772
 
734
780
        return False
735
781
 
736
782
 
737
 
class RepositoryFormat5(RepositoryFormat):
 
783
class RepositoryFormat5(PreSplitOutRepositoryFormat):
738
784
    """Bzr control format 5.
739
785
 
740
786
    This repository format has:
748
794
        self._matchingbzrdir = bzrdir.BzrDirFormat5()
749
795
 
750
796
 
751
 
class RepositoryFormat6(RepositoryFormat):
 
797
class RepositoryFormat6(PreSplitOutRepositoryFormat):
752
798
    """Bzr control format 6.
753
799
 
754
800
    This repository format has:
770
816
     - hash subdirectory based stores.
771
817
     - TextStores for revisions and signatures.
772
818
     - a format marker of its own
 
819
     - an optional 'shared-storage' flag
773
820
    """
774
821
 
775
822
    def get_format_string(self):
776
823
        """See RepositoryFormat.get_format_string()."""
777
824
        return "Bazaar-NG Repository format 7"
778
825
 
779
 
    def initialize(self, a_bzrdir):
 
826
    def initialize(self, a_bzrdir, shared=False):
780
827
        """Create a weave repository.
 
828
 
 
829
        :param shared: If true the repository will be initialized as a shared
 
830
                       repository.
781
831
        """
782
832
        from bzrlib.weavefile import write_weave_v5
783
833
        from bzrlib.weave import Weave
807
857
                control_files.put(file, content)
808
858
            for file, content in utf8_files:
809
859
                control_files.put_utf8(file, content)
 
860
            if shared == True:
 
861
                control_files.put_utf8('shared-storage', '')
810
862
        finally:
811
863
            control_files.unlock()
812
 
        return Repository(None, branch_format=None, _format=self, a_bzrdir=a_bzrdir)
 
864
        return Repository(_format=self, a_bzrdir=a_bzrdir)
813
865
 
814
866
    def __init__(self):
815
867
        super(RepositoryFormat7, self).__init__()
826
878
                   RepositoryFormat6()]
827
879
 
828
880
 
829
 
# TODO: jam 20060108 Create a new branch format, and as part of upgrade
830
 
#       make sure that ancestry.weave is deleted (it is never used, but
831
 
#       used to be created)
832
 
 
833
881
class RepositoryTestProviderAdapter(object):
834
882
    """A tool to generate a suite testing multiple repository formats at once.
835
883