~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
    
44
44
    transport
45
45
        the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
 
46
    root_transport
 
47
        a transport connected to the directory this bzr was opened from.
46
48
    """
47
49
 
48
50
    def _check_supported(self, format, allow_unsupported):
53
55
        if not allow_unsupported and not format.is_supported():
54
56
            raise errors.UnsupportedFormatError(format)
55
57
 
 
58
    def clone(self, url, revision_id=None, basis=None):
 
59
        """Clone this bzrdir and its contents to url verbatim.
 
60
 
 
61
        If urls last component does not exist, it will be created.
 
62
 
 
63
        if revision_id is not None, then the clone operation may tune
 
64
            itself to download less data.
 
65
        """
 
66
        self._make_tail(url)
 
67
        result = self._format.initialize(url)
 
68
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
 
69
        try:
 
70
            self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
 
71
        except errors.NoRepositoryPresent:
 
72
            pass
 
73
        try:
 
74
            self.open_branch().clone(result, revision_id=revision_id)
 
75
        except errors.NotBranchError:
 
76
            pass
 
77
        try:
 
78
            self.open_workingtree().clone(result, basis=basis_tree)
 
79
        except (errors.NotBranchError, errors.NotLocalUrl):
 
80
            pass
 
81
        return result
 
82
 
 
83
    def _get_basis_components(self, basis):
 
84
        """Retrieve the basis components that are available at basis."""
 
85
        if basis is None:
 
86
            return None, None, None
 
87
        try:
 
88
            basis_tree = basis.open_workingtree()
 
89
            basis_branch = basis_tree.branch
 
90
            basis_repo = basis_branch.repository
 
91
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
92
            basis_tree = None
 
93
            try:
 
94
                basis_branch = basis.open_branch()
 
95
                basis_repo = basis_branch.repository
 
96
            except errors.NotBranchError:
 
97
                basis_branch = None
 
98
                try:
 
99
                    basis_repo = basis.open_repository()
 
100
                except errors.NoRepositoryPresent:
 
101
                    basis_repo = None
 
102
        return basis_repo, basis_branch, basis_tree
 
103
 
 
104
    def _make_tail(self, url):
 
105
        segments = url.split('/')
 
106
        if segments and segments[-1] not in ('', '.'):
 
107
            parent = '/'.join(segments[:-1])
 
108
            t = bzrlib.transport.get_transport(parent)
 
109
            try:
 
110
                t.mkdir(segments[-1])
 
111
            except errors.FileExists:
 
112
                pass
 
113
 
56
114
    @staticmethod
57
115
    def create(base):
58
116
        """Create a new BzrDir at the url 'base'.
183
241
        """
184
242
        self._format = _format
185
243
        self.transport = _transport.clone('.bzr')
 
244
        self.root_transport = _transport
186
245
 
187
246
    @staticmethod
188
247
    def open_unsupported(base):
263
322
        """
264
323
        raise NotImplementedError(self.open_workingtree)
265
324
 
 
325
    def sprout(self, url, revision_id=None, basis=None):
 
326
        """Create a copy of this bzrdir prepared for use as a new line of
 
327
        development.
 
328
 
 
329
        If urls last component does not exist, it will be created.
 
330
 
 
331
        Attributes related to the identity of the source branch like
 
332
        branch nickname will be cleaned, a working tree is created
 
333
        whether one existed before or not; and a local branch is always
 
334
        created.
 
335
 
 
336
        if revision_id is not None, then the clone operation may tune
 
337
            itself to download less data.
 
338
        """
 
339
        self._make_tail(url)
 
340
        result = self._format.initialize(url)
 
341
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
 
342
        try:
 
343
            source_branch = self.open_branch()
 
344
            source_repository = source_branch.repository
 
345
        except errors.NotBranchError:
 
346
            source_branch = None
 
347
            try:
 
348
                source_repository = self.open_repository()
 
349
            except errors.NoRepositoryPresent:
 
350
                # copy the basis one if there is one
 
351
                source_repository = basis_repo
 
352
        if source_repository is not None:
 
353
            source_repository.clone(result,
 
354
                                    revision_id=revision_id,
 
355
                                    basis=basis_repo)
 
356
        else:
 
357
            # no repo available, make a new one
 
358
            result.create_repository()
 
359
        if source_branch is not None:
 
360
            source_branch.sprout(result, revision_id=revision_id)
 
361
        else:
 
362
            result.create_branch()
 
363
        try:
 
364
            self.open_workingtree().clone(result,
 
365
                                          revision_id=revision_id, 
 
366
                                          basis=basis_tree)
 
367
        except (errors.NotBranchError, errors.NotLocalUrl):
 
368
            result.create_workingtree()
 
369
        return result
 
370
 
266
371
 
267
372
class BzrDirPreSplitOut(BzrDir):
268
373
    """A common class for the all-in-one formats."""
269
374
 
 
375
    def clone(self, url, revision_id=None, basis=None):
 
376
        """See BzrDir.clone()."""
 
377
        from bzrlib.workingtree import WorkingTreeFormat2
 
378
        self._make_tail(url)
 
379
        result = self._format.initialize(url, _cloning=True)
 
380
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
 
381
        self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
 
382
        self.open_branch().clone(result, revision_id=revision_id)
 
383
        try:
 
384
            self.open_workingtree().clone(result, basis=basis_tree)
 
385
        except errors.NotLocalUrl:
 
386
            # make a new one, this format always has to have one.
 
387
            WorkingTreeFormat2().initialize(result)
 
388
        return result
 
389
 
270
390
    def create_branch(self):
271
391
        """See BzrDir.create_branch."""
272
 
        from bzrlib.branch import BzrBranchFormat4
273
 
        return BzrBranchFormat4().initialize(self)
 
392
        return self.open_branch()
 
393
 
 
394
    def create_repository(self):
 
395
        """See BzrDir.create_repository."""
 
396
        return self.open_repository()
 
397
 
 
398
    def create_workingtree(self):
 
399
        """See BzrDir.create_workingtree."""
 
400
        return self.open_workingtree()
274
401
 
275
402
    def get_branch_transport(self, branch_format):
276
403
        """See BzrDir.get_branch_transport()."""
309
436
        self._check_supported(format, unsupported)
310
437
        return format.open(self, _found=True)
311
438
 
 
439
    def sprout(self, url, revision_id=None, basis=None):
 
440
        """See BzrDir.sprout()."""
 
441
        from bzrlib.workingtree import WorkingTreeFormat2
 
442
        self._make_tail(url)
 
443
        result = self._format.initialize(url, _cloning=True)
 
444
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
 
445
        try:
 
446
            self.open_repository().clone(result, revision_id=revision_id, basis=basis_repo)
 
447
        except errors.NoRepositoryPresent:
 
448
            pass
 
449
        try:
 
450
            self.open_branch().sprout(result, revision_id=revision_id)
 
451
        except errors.NotBranchError:
 
452
            pass
 
453
        try:
 
454
            self.open_workingtree().clone(result, basis=basis_tree)
 
455
        except (errors.NotBranchError, errors.NotLocalUrl):
 
456
            # we always want a working tree
 
457
            WorkingTreeFormat2().initialize(result)
 
458
        return result
 
459
 
312
460
 
313
461
class BzrDir4(BzrDirPreSplitOut):
314
462
    """A .bzr version 4 control object."""
327
475
class BzrDir5(BzrDirPreSplitOut):
328
476
    """A .bzr version 5 control object."""
329
477
 
330
 
    def create_repository(self):
331
 
        """See BzrDir.create_repository."""
332
 
        from bzrlib.repository import RepositoryFormat5
333
 
        return RepositoryFormat5().initialize(self)
334
 
 
335
 
    def create_workingtree(self):
336
 
        """See BzrDir.create_workingtree."""
337
 
        from bzrlib.workingtree import WorkingTreeFormat2
338
 
        return WorkingTreeFormat2().initialize(self)
339
 
 
340
478
    def open_repository(self):
341
479
        """See BzrDir.open_repository."""
342
480
        from bzrlib.repository import RepositoryFormat5
351
489
class BzrDir6(BzrDirPreSplitOut):
352
490
    """A .bzr version 6 control object."""
353
491
 
354
 
    def create_repository(self):
355
 
        """See BzrDir.create_repository."""
356
 
        from bzrlib.repository import RepositoryFormat6
357
 
        return RepositoryFormat6().initialize(self)
358
 
 
359
 
    def create_workingtree(self):
360
 
        """See BzrDir.create_workingtree."""
361
 
        from bzrlib.workingtree import WorkingTreeFormat2
362
 
        return WorkingTreeFormat2().initialize(self)
363
 
 
364
492
    def open_repository(self):
365
493
        """See BzrDir.open_repository."""
366
494
        from bzrlib.repository import RepositoryFormat6
578
706
 
579
707
    This format is a combined format for working tree, branch and repository.
580
708
    It has:
581
 
     - Format 1 working trees
582
 
     - Format 4 branches
583
 
     - Format 4 repositories
 
709
     - Format 1 working trees [always]
 
710
     - Format 4 branches [always]
 
711
     - Format 4 repositories [always]
584
712
 
585
713
    This format is deprecated: it indexes texts using a text it which is
586
714
    removed in format 5; write support for this format has been removed.
613
741
 
614
742
    This format is a combined format for working tree, branch and repository.
615
743
    It has:
616
 
     - Format 2 working trees
617
 
     - Format 4 branches
618
 
     - Format 6 repositories
 
744
     - Format 2 working trees [always] 
 
745
     - Format 4 branches [always] 
 
746
     - Format 6 repositories [always]
 
747
       Unhashed stores in the repository.
619
748
    """
620
749
 
621
750
    def get_format_string(self):
622
751
        """See BzrDirFormat.get_format_string()."""
623
752
        return "Bazaar-NG branch, format 5\n"
624
753
 
 
754
    def initialize(self, url, _cloning=False):
 
755
        """Format 5 dirs always have working tree, branch and repository.
 
756
        
 
757
        Except when they are being cloned.
 
758
        """
 
759
        from bzrlib.branch import BzrBranchFormat4
 
760
        from bzrlib.repository import RepositoryFormat5
 
761
        from bzrlib.workingtree import WorkingTreeFormat2
 
762
        result = super(BzrDirFormat5, self).initialize(url)
 
763
        RepositoryFormat5().initialize(result, _internal=True)
 
764
        if not _cloning:
 
765
            BzrBranchFormat4().initialize(result)
 
766
            WorkingTreeFormat2().initialize(result)
 
767
        return result
 
768
 
625
769
    def _open(self, transport):
626
770
        """See BzrDirFormat._open."""
627
771
        return BzrDir5(transport, self)
632
776
 
633
777
    This format is a combined format for working tree, branch and repository.
634
778
    It has:
635
 
     - Format 2 working trees
636
 
     - Format 4 branches
637
 
     - Format 6 repositories
 
779
     - Format 2 working trees [always] 
 
780
     - Format 4 branches [always] 
 
781
     - Format 6 repositories [always]
638
782
    """
639
783
 
640
784
    def get_format_string(self):
641
785
        """See BzrDirFormat.get_format_string()."""
642
786
        return "Bazaar-NG branch, format 6\n"
643
787
 
 
788
    def initialize(self, url, _cloning=False):
 
789
        """Format 6 dirs always have working tree, branch and repository.
 
790
        
 
791
        Except when they are being cloned.
 
792
        """
 
793
        from bzrlib.branch import BzrBranchFormat4
 
794
        from bzrlib.repository import RepositoryFormat6
 
795
        from bzrlib.workingtree import WorkingTreeFormat2
 
796
        result = super(BzrDirFormat6, self).initialize(url)
 
797
        RepositoryFormat6().initialize(result, _internal=True)
 
798
        if not _cloning:
 
799
            BzrBranchFormat4().initialize(result)
 
800
            try:
 
801
                WorkingTreeFormat2().initialize(result)
 
802
            except errors.NotLocalUrl:
 
803
                # emulate pre-check behaviour for working tree and silently 
 
804
                # fail.
 
805
                pass
 
806
        return result
 
807
 
644
808
    def _open(self, transport):
645
809
        """See BzrDirFormat._open."""
646
810
        return BzrDir6(transport, self)
652
816
    This is the first format with split out working tree, branch and repository
653
817
    disk storage.
654
818
    It has:
655
 
     - Format 3 working trees
656
 
     - Format 5 branches
657
 
     - Format 7 repositories
 
819
     - Format 3 working trees [optional]
 
820
     - Format 5 branches [optional]
 
821
     - Format 7 repositories [optional]
658
822
    """
659
823
 
660
824
    def get_format_string(self):
729
893
            super(ScratchDir, self).__init__(transport, BzrDirFormat6())
730
894
            self.create_repository()
731
895
            self.create_branch()
732
 
            from bzrlib.workingtree import WorkingTree
733
 
            WorkingTree.create(self.open_branch(), transport.base)
 
896
            self.create_workingtree()
734
897
        else:
735
898
            super(ScratchDir, self).__init__(transport, BzrDirFormat6())
736
899