~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-31 16:12:57 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060731161257-91a231523255332c
new official bzr.ico

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
# TODO: remove unittest dependency; put that stuff inside the test suite
24
24
 
25
 
# TODO: The Format probe_transport seems a bit redundant with just trying to
26
 
# open the bzrdir. -- mbp
27
 
#
28
 
# TODO: Can we move specific formats into separate modules to make this file
29
 
# smaller?
30
 
 
31
25
from copy import deepcopy
32
26
from cStringIO import StringIO
33
27
import os
45
39
                            sha_strings,
46
40
                            sha_string,
47
41
                            )
48
 
import bzrlib.revision
49
42
from bzrlib.store.revision.text import TextRevisionStore
50
43
from bzrlib.store.text import TextStore
51
44
from bzrlib.store.versioned import WeaveStore
93
86
        """Return true if this bzrdir is one whose format we can convert from."""
94
87
        return True
95
88
 
96
 
    def check_conversion_target(self, target_format):
97
 
        target_repo_format = target_format.repository_format
98
 
        source_repo_format = self._format.repository_format
99
 
        source_repo_format.check_conversion_target(target_repo_format)
100
 
 
101
89
    @staticmethod
102
90
    def _check_supported(format, allow_unsupported):
103
91
        """Check whether format is a supported format.
304
292
        This will use the current default BzrDirFormat, and use whatever 
305
293
        repository format that that uses for bzrdirformat.create_repository.
306
294
 
307
 
        :param shared: Create a shared repository rather than a standalone
 
295
        ;param shared: Create a shared repository rather than a standalone
308
296
                       repository.
309
297
        The Repository object is returned.
310
298
 
325
313
        repository format that that uses for bzrdirformat.create_workingtree,
326
314
        create_branch and create_repository.
327
315
 
328
 
        :return: The WorkingTree object.
 
316
        The WorkingTree object is returned.
329
317
        """
330
318
        t = get_transport(safe_unicode(base))
331
319
        if not isinstance(t, LocalTransport):
472
460
        _unsupported is a private parameter to the BzrDir class.
473
461
        """
474
462
        t = get_transport(base)
475
 
        return BzrDir.open_from_transport(t, _unsupported=_unsupported)
476
 
 
477
 
    @staticmethod
478
 
    def open_from_transport(transport, _unsupported=False):
479
 
        """Open a bzrdir within a particular directory.
480
 
 
481
 
        :param transport: Transport containing the bzrdir.
482
 
        :param _unsupported: private.
483
 
        """
484
 
        format = BzrDirFormat.find_format(transport)
 
463
        mutter("trying to open %r with transport %r", base, t)
 
464
        format = BzrDirFormat.find_format(t)
485
465
        BzrDir._check_supported(format, _unsupported)
486
 
        return format.open(transport, _found=True)
 
466
        return format.open(t, _found=True)
487
467
 
488
468
    def open_branch(self, unsupported=False):
489
469
        """Open the branch object at this BzrDir if one is present.
523
503
        url = a_transport.base
524
504
        while True:
525
505
            try:
526
 
                result = BzrDir.open_from_transport(a_transport)
527
 
                return result, urlutils.unescape(a_transport.relpath(url))
 
506
                format = BzrDirFormat.find_format(a_transport)
 
507
                BzrDir._check_supported(format, False)
 
508
                return format.open(a_transport), urlutils.unescape(a_transport.relpath(url))
528
509
            except errors.NotBranchError, e:
 
510
                ## mutter('not a branch in: %r %s', a_transport.base, e)
529
511
                pass
530
512
            new_t = a_transport.clone('..')
531
513
            if new_t.base == a_transport.base:
581
563
        except errors.NoWorkingTree:
582
564
            return False
583
565
 
584
 
    def cloning_metadir(self, basis=None):
585
 
        """Produce a metadir suitable for cloning with"""
586
 
        def related_repository(bzrdir):
587
 
            try:
588
 
                branch = bzrdir.open_branch()
589
 
                return branch.repository
590
 
            except errors.NotBranchError:
591
 
                source_branch = None
592
 
                return bzrdir.open_repository()
593
 
        result_format = self._format.__class__()
594
 
        try:
595
 
            try:
596
 
                source_repository = related_repository(self)
597
 
            except errors.NoRepositoryPresent:
598
 
                if basis is None:
599
 
                    raise
600
 
                source_repository = related_repository(self)
601
 
            result_format.repository_format = source_repository._format
602
 
        except errors.NoRepositoryPresent:
603
 
            pass
604
 
        return result_format
605
 
 
606
566
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
607
567
        """Create a copy of this bzrdir prepared for use as a new line of
608
568
        development.
618
578
            itself to download less data.
619
579
        """
620
580
        self._make_tail(url)
621
 
        cloning_format = self.cloning_metadir(basis)
622
 
        result = cloning_format.initialize(url)
 
581
        result = self._format.initialize(url)
623
582
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
624
583
        try:
625
584
            source_branch = self.open_branch()
656
615
                # XXX FIXME RBC 20060214 need tests for this when the basis
657
616
                # is incomplete
658
617
                result_repo.fetch(basis_repo, revision_id=revision_id)
659
 
            if source_repository is not None:
660
 
                result_repo.fetch(source_repository, revision_id=revision_id)
 
618
            result_repo.fetch(source_repository, revision_id=revision_id)
661
619
        if source_branch is not None:
662
620
            source_branch.sprout(result, revision_id=revision_id)
663
621
        else:
727
685
        # done on this format anyway. So - acceptable wart.
728
686
        result = self.open_workingtree()
729
687
        if revision_id is not None:
730
 
            if revision_id == bzrlib.revision.NULL_REVISION:
731
 
                result.set_parent_ids([])
732
 
            else:
733
 
                result.set_parent_ids([revision_id])
 
688
            result.set_last_revision(revision_id)
734
689
        return result
735
690
 
736
691
    def get_branch_transport(self, branch_format):
778
733
        self._check_supported(format, unsupported)
779
734
        return format.open(self, _found=True)
780
735
 
781
 
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
 
736
    def sprout(self, url, revision_id=None, basis=None):
782
737
        """See BzrDir.sprout()."""
783
738
        from bzrlib.workingtree import WorkingTreeFormat2
784
739
        self._make_tail(url)
1097
1052
        """
1098
1053
        return True
1099
1054
 
1100
 
    def same_model(self, target_format):
1101
 
        return (self.repository_format.rich_root_data == 
1102
 
            target_format.rich_root_data)
1103
 
 
1104
1055
    @classmethod
1105
1056
    def known_formats(klass):
1106
1057
        """Return all the known formats.
1222
1173
    def __return_repository_format(self):
1223
1174
        """Circular import protection."""
1224
1175
        from bzrlib.repository import RepositoryFormat4
1225
 
        return RepositoryFormat4()
 
1176
        return RepositoryFormat4(self)
1226
1177
    repository_format = property(__return_repository_format)
1227
1178
 
1228
1179
 
1266
1217
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1267
1218
        RepositoryFormat5().initialize(result, _internal=True)
1268
1219
        if not _cloning:
1269
 
            branch = BzrBranchFormat4().initialize(result)
1270
 
            try:
1271
 
                WorkingTreeFormat2().initialize(result)
1272
 
            except errors.NotLocalUrl:
1273
 
                # Even though we can't access the working tree, we need to
1274
 
                # create its control files.
1275
 
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
 
1220
            BzrBranchFormat4().initialize(result)
 
1221
            WorkingTreeFormat2().initialize(result)
1276
1222
        return result
1277
1223
 
1278
1224
    def _open(self, transport):
1282
1228
    def __return_repository_format(self):
1283
1229
        """Circular import protection."""
1284
1230
        from bzrlib.repository import RepositoryFormat5
1285
 
        return RepositoryFormat5()
 
1231
        return RepositoryFormat5(self)
1286
1232
    repository_format = property(__return_repository_format)
1287
1233
 
1288
1234
 
1325
1271
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1326
1272
        RepositoryFormat6().initialize(result, _internal=True)
1327
1273
        if not _cloning:
1328
 
            branch = BzrBranchFormat4().initialize(result)
 
1274
            BzrBranchFormat4().initialize(result)
1329
1275
            try:
1330
1276
                WorkingTreeFormat2().initialize(result)
1331
1277
            except errors.NotLocalUrl:
1332
 
                # Even though we can't access the working tree, we need to
1333
 
                # create its control files.
1334
 
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
 
1278
                # emulate pre-check behaviour for working tree and silently 
 
1279
                # fail.
 
1280
                pass
1335
1281
        return result
1336
1282
 
1337
1283
    def _open(self, transport):
1341
1287
    def __return_repository_format(self):
1342
1288
        """Circular import protection."""
1343
1289
        from bzrlib.repository import RepositoryFormat6
1344
 
        return RepositoryFormat6()
 
1290
        return RepositoryFormat6(self)
1345
1291
    repository_format = property(__return_repository_format)
1346
1292
 
1347
1293
 
1523
1469
        inv = serializer_v4.read_inventory(self.branch.control_files.get('inventory'))
1524
1470
        new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1525
1471
        # FIXME inventory is a working tree change.
1526
 
        self.branch.control_files.put('inventory', StringIO(new_inv_xml))
 
1472
        self.branch.control_files.put('inventory', new_inv_xml)
1527
1473
 
1528
1474
    def _write_all_weaves(self):
1529
1475
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
1586
1532
        assert rev_id not in self.converted_revs
1587
1533
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1588
1534
        inv = serializer_v4.read_inventory_from_string(old_inv_xml)
1589
 
        inv.revision_id = rev_id
1590
1535
        rev = self.revisions[rev_id]
1591
1536
        if rev.inventory_sha1:
1592
1537
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
1612
1557
    def _store_new_weave(self, rev, inv, present_parents):
1613
1558
        # the XML is now updated with text versions
1614
1559
        if __debug__:
1615
 
            entries = inv.iter_entries()
1616
 
            entries.next()
1617
 
            for path, ie in entries:
1618
 
                assert getattr(ie, 'revision', None) is not None, \
 
1560
            for file_id in inv:
 
1561
                ie = inv[file_id]
 
1562
                if ie.kind == 'root_directory':
 
1563
                    continue
 
1564
                assert hasattr(ie, 'revision'), \
1619
1565
                    'no revision on {%s} in {%s}' % \
1620
1566
                    (file_id, rev.revision_id)
1621
1567
        new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1633
1579
        mutter('converting texts of revision {%s}',
1634
1580
               rev_id)
1635
1581
        parent_invs = map(self._load_updated_inventory, present_parents)
1636
 
        entries = inv.iter_entries()
1637
 
        entries.next()
1638
 
        for path, ie in entries:
 
1582
        for file_id in inv:
 
1583
            ie = inv[file_id]
1639
1584
            self._convert_file_version(rev, ie, parent_invs)
1640
1585
 
1641
1586
    def _convert_file_version(self, rev, ie, parent_invs):
1644
1589
        The file needs to be added into the weave if it is a merge
1645
1590
        of >=2 parents or if it's changed from its parent.
1646
1591
        """
 
1592
        if ie.kind == 'root_directory':
 
1593
            return
1647
1594
        file_id = ie.file_id
1648
1595
        rev_id = rev.revision_id
1649
1596
        w = self.text_weaves.get(file_id)
1798
1745
        for entry in branch_files:
1799
1746
            self.move_entry('branch', entry)
1800
1747
 
 
1748
        self.step('Upgrading working tree')
 
1749
        self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
 
1750
        self.make_lock('checkout')
 
1751
        self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
 
1752
        self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1801
1753
        checkout_files = [('pending-merges', True),
1802
1754
                          ('inventory', True),
1803
1755
                          ('stat-cache', False)]
1804
 
        # If a mandatory checkout file is not present, the branch does not have
1805
 
        # a functional checkout. Do not create a checkout in the converted
1806
 
        # branch.
1807
 
        for name, mandatory in checkout_files:
1808
 
            if mandatory and name not in bzrcontents:
1809
 
                has_checkout = False
1810
 
                break
1811
 
        else:
1812
 
            has_checkout = True
1813
 
        if not has_checkout:
1814
 
            self.pb.note('No working tree.')
1815
 
            # If some checkout files are there, we may as well get rid of them.
1816
 
            for name, mandatory in checkout_files:
1817
 
                if name in bzrcontents:
1818
 
                    self.bzrdir.transport.delete(name)
1819
 
        else:
1820
 
            self.step('Upgrading working tree')
1821
 
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1822
 
            self.make_lock('checkout')
1823
 
            self.put_format(
1824
 
                'checkout', bzrlib.workingtree.WorkingTreeFormat3())
1825
 
            self.bzrdir.transport.delete_multi(
1826
 
                self.garbage_inventories, self.pb)
1827
 
            for entry in checkout_files:
1828
 
                self.move_entry('checkout', entry)
1829
 
            if last_revision is not None:
1830
 
                self.bzrdir._control_files.put_utf8(
1831
 
                    'checkout/last-revision', last_revision)
1832
 
        self.bzrdir._control_files.put_utf8(
1833
 
            'branch-format', BzrDirMetaFormat1().get_format_string())
 
1756
        for entry in checkout_files:
 
1757
            self.move_entry('checkout', entry)
 
1758
        if last_revision is not None:
 
1759
            self.bzrdir._control_files.put_utf8('checkout/last-revision',
 
1760
                                                last_revision)
 
1761
        self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
1834
1762
        return BzrDir.open(self.bzrdir.root_transport.base)
1835
1763
 
1836
1764
    def make_lock(self, name):