~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Aaron Bentley
  • Date: 2006-09-29 00:04:13 UTC
  • mto: (1731.2.8 nested-trees)
  • mto: This revision was merged to the branch mainline in revision 2078.
  • Revision ID: aaron.bentley@utoronto.ca-20060929000413-bb6d513b7171b59f
fix version_info stuff to deliberately include root

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
 
25
31
from copy import deepcopy
26
32
from cStringIO import StringIO
27
33
import os
39
45
                            sha_strings,
40
46
                            sha_string,
41
47
                            )
 
48
import bzrlib.revision
42
49
from bzrlib.store.revision.text import TextRevisionStore
43
50
from bzrlib.store.text import TextStore
44
51
from bzrlib.store.versioned import WeaveStore
86
93
        """Return true if this bzrdir is one whose format we can convert from."""
87
94
        return True
88
95
 
 
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
 
89
101
    @staticmethod
90
102
    def _check_supported(format, allow_unsupported):
91
103
        """Check whether format is a supported format.
292
304
        This will use the current default BzrDirFormat, and use whatever 
293
305
        repository format that that uses for bzrdirformat.create_repository.
294
306
 
295
 
        ;param shared: Create a shared repository rather than a standalone
 
307
        :param shared: Create a shared repository rather than a standalone
296
308
                       repository.
297
309
        The Repository object is returned.
298
310
 
313
325
        repository format that that uses for bzrdirformat.create_workingtree,
314
326
        create_branch and create_repository.
315
327
 
316
 
        The WorkingTree object is returned.
 
328
        :return: The WorkingTree object.
317
329
        """
318
330
        t = get_transport(safe_unicode(base))
319
331
        if not isinstance(t, LocalTransport):
460
472
        _unsupported is a private parameter to the BzrDir class.
461
473
        """
462
474
        t = get_transport(base)
463
 
        mutter("trying to open %r with transport %r", base, t)
464
 
        format = BzrDirFormat.find_format(t)
 
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)
465
485
        BzrDir._check_supported(format, _unsupported)
466
 
        return format.open(t, _found=True)
 
486
        return format.open(transport, _found=True)
467
487
 
468
488
    def open_branch(self, unsupported=False):
469
489
        """Open the branch object at this BzrDir if one is present.
503
523
        url = a_transport.base
504
524
        while True:
505
525
            try:
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))
 
526
                result = BzrDir.open_from_transport(a_transport)
 
527
                return result, urlutils.unescape(a_transport.relpath(url))
509
528
            except errors.NotBranchError, e:
510
 
                ## mutter('not a branch in: %r %s', a_transport.base, e)
511
529
                pass
512
530
            new_t = a_transport.clone('..')
513
531
            if new_t.base == a_transport.base:
563
581
        except errors.NoWorkingTree:
564
582
            return False
565
583
 
 
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
 
566
606
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
567
607
        """Create a copy of this bzrdir prepared for use as a new line of
568
608
        development.
578
618
            itself to download less data.
579
619
        """
580
620
        self._make_tail(url)
581
 
        result = self._format.initialize(url)
 
621
        cloning_format = self.cloning_metadir(basis)
 
622
        result = cloning_format.initialize(url)
582
623
        basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
583
624
        try:
584
625
            source_branch = self.open_branch()
615
656
                # XXX FIXME RBC 20060214 need tests for this when the basis
616
657
                # is incomplete
617
658
                result_repo.fetch(basis_repo, revision_id=revision_id)
618
 
            result_repo.fetch(source_repository, revision_id=revision_id)
 
659
            if source_repository is not None:
 
660
                result_repo.fetch(source_repository, revision_id=revision_id)
619
661
        if source_branch is not None:
620
662
            source_branch.sprout(result, revision_id=revision_id)
621
663
        else:
623
665
        # TODO: jam 20060426 we probably need a test in here in the
624
666
        #       case that the newly sprouted branch is a remote one
625
667
        if result_repo is None or result_repo.make_working_trees():
626
 
            result.create_workingtree()
 
668
            wt = result.create_workingtree()
 
669
            if wt.inventory.root is None:
 
670
                try:
 
671
                    wt.set_root_id(self.open_workingtree.get_root_id())
 
672
                except errors.NoWorkingTree:
 
673
                    pass
627
674
        return result
628
675
 
629
676
 
685
732
        # done on this format anyway. So - acceptable wart.
686
733
        result = self.open_workingtree()
687
734
        if revision_id is not None:
688
 
            result.set_last_revision(revision_id)
 
735
            if revision_id == bzrlib.revision.NULL_REVISION:
 
736
                result.set_parent_ids([])
 
737
            else:
 
738
                result.set_parent_ids([revision_id])
689
739
        return result
690
740
 
691
741
    def get_branch_transport(self, branch_format):
733
783
        self._check_supported(format, unsupported)
734
784
        return format.open(self, _found=True)
735
785
 
736
 
    def sprout(self, url, revision_id=None, basis=None):
 
786
    def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
737
787
        """See BzrDir.sprout()."""
738
788
        from bzrlib.workingtree import WorkingTreeFormat2
739
789
        self._make_tail(url)
1052
1102
        """
1053
1103
        return True
1054
1104
 
 
1105
    def same_model(self, target_format):
 
1106
        return (self.repository_format.rich_root_data == 
 
1107
            target_format.rich_root_data)
 
1108
 
1055
1109
    @classmethod
1056
1110
    def known_formats(klass):
1057
1111
        """Return all the known formats.
1173
1227
    def __return_repository_format(self):
1174
1228
        """Circular import protection."""
1175
1229
        from bzrlib.repository import RepositoryFormat4
1176
 
        return RepositoryFormat4(self)
 
1230
        return RepositoryFormat4()
1177
1231
    repository_format = property(__return_repository_format)
1178
1232
 
1179
1233
 
1217
1271
        result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1218
1272
        RepositoryFormat5().initialize(result, _internal=True)
1219
1273
        if not _cloning:
1220
 
            BzrBranchFormat4().initialize(result)
1221
 
            WorkingTreeFormat2().initialize(result)
 
1274
            branch = BzrBranchFormat4().initialize(result)
 
1275
            try:
 
1276
                WorkingTreeFormat2().initialize(result)
 
1277
            except errors.NotLocalUrl:
 
1278
                # Even though we can't access the working tree, we need to
 
1279
                # create its control files.
 
1280
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1222
1281
        return result
1223
1282
 
1224
1283
    def _open(self, transport):
1228
1287
    def __return_repository_format(self):
1229
1288
        """Circular import protection."""
1230
1289
        from bzrlib.repository import RepositoryFormat5
1231
 
        return RepositoryFormat5(self)
 
1290
        return RepositoryFormat5()
1232
1291
    repository_format = property(__return_repository_format)
1233
1292
 
1234
1293
 
1271
1330
        result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1272
1331
        RepositoryFormat6().initialize(result, _internal=True)
1273
1332
        if not _cloning:
1274
 
            BzrBranchFormat4().initialize(result)
 
1333
            branch = BzrBranchFormat4().initialize(result)
1275
1334
            try:
1276
1335
                WorkingTreeFormat2().initialize(result)
1277
1336
            except errors.NotLocalUrl:
1278
 
                # emulate pre-check behaviour for working tree and silently 
1279
 
                # fail.
1280
 
                pass
 
1337
                # Even though we can't access the working tree, we need to
 
1338
                # create its control files.
 
1339
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1281
1340
        return result
1282
1341
 
1283
1342
    def _open(self, transport):
1287
1346
    def __return_repository_format(self):
1288
1347
        """Circular import protection."""
1289
1348
        from bzrlib.repository import RepositoryFormat6
1290
 
        return RepositoryFormat6(self)
 
1349
        return RepositoryFormat6()
1291
1350
    repository_format = property(__return_repository_format)
1292
1351
 
1293
1352
 
1469
1528
        inv = serializer_v4.read_inventory(self.branch.control_files.get('inventory'))
1470
1529
        new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1471
1530
        # FIXME inventory is a working tree change.
1472
 
        self.branch.control_files.put('inventory', new_inv_xml)
 
1531
        self.branch.control_files.put('inventory', StringIO(new_inv_xml))
1473
1532
 
1474
1533
    def _write_all_weaves(self):
1475
1534
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
1532
1591
        assert rev_id not in self.converted_revs
1533
1592
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1534
1593
        inv = serializer_v4.read_inventory_from_string(old_inv_xml)
 
1594
        inv.revision_id = rev_id
1535
1595
        rev = self.revisions[rev_id]
1536
1596
        if rev.inventory_sha1:
1537
1597
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
1560
1620
            entries = inv.iter_entries()
1561
1621
            entries.next()
1562
1622
            for path, ie in entries:
1563
 
                assert hasattr(ie, 'revision'), \
 
1623
                if inv.is_root(ie.file_id):
 
1624
                    continue
 
1625
                assert getattr(ie, 'revision', None) is not None, \
1564
1626
                    'no revision on {%s} in {%s}' % \
1565
1627
                    (file_id, rev.revision_id)
1566
1628
        new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1578
1640
        mutter('converting texts of revision {%s}',
1579
1641
               rev_id)
1580
1642
        parent_invs = map(self._load_updated_inventory, present_parents)
1581
 
        entries = inv.iter_entries()
1582
 
        entries.next()
1583
 
        for path, ie in entries:
 
1643
        for file_id in inv:
 
1644
            if inv.is_root(file_id):
 
1645
                continue
 
1646
            ie = inv[file_id]
1584
1647
            self._convert_file_version(rev, ie, parent_invs)
1585
1648
 
1586
1649
    def _convert_file_version(self, rev, ie, parent_invs):
1602
1665
                                                  entry_vf=w)
1603
1666
        for old_revision in previous_entries:
1604
1667
                # if this fails, its a ghost ?
1605
 
                assert old_revision in self.converted_revs 
 
1668
                assert old_revision in self.converted_revs, \
 
1669
                    "Revision {%s} not in converted_revs" % old_revision
1606
1670
        self.snapshot_ie(previous_entries, ie, w, rev_id)
1607
1671
        del ie.text_id
1608
1672
        assert getattr(ie, 'revision', None) is not None
1743
1807
        for entry in branch_files:
1744
1808
            self.move_entry('branch', entry)
1745
1809
 
1746
 
        self.step('Upgrading working tree')
1747
 
        self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1748
 
        self.make_lock('checkout')
1749
 
        self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1750
 
        self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1751
1810
        checkout_files = [('pending-merges', True),
1752
1811
                          ('inventory', True),
1753
1812
                          ('stat-cache', False)]
1754
 
        for entry in checkout_files:
1755
 
            self.move_entry('checkout', entry)
1756
 
        if last_revision is not None:
1757
 
            self.bzrdir._control_files.put_utf8('checkout/last-revision',
1758
 
                                                last_revision)
1759
 
        self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
 
1813
        # If a mandatory checkout file is not present, the branch does not have
 
1814
        # a functional checkout. Do not create a checkout in the converted
 
1815
        # branch.
 
1816
        for name, mandatory in checkout_files:
 
1817
            if mandatory and name not in bzrcontents:
 
1818
                has_checkout = False
 
1819
                break
 
1820
        else:
 
1821
            has_checkout = True
 
1822
        if not has_checkout:
 
1823
            self.pb.note('No working tree.')
 
1824
            # If some checkout files are there, we may as well get rid of them.
 
1825
            for name, mandatory in checkout_files:
 
1826
                if name in bzrcontents:
 
1827
                    self.bzrdir.transport.delete(name)
 
1828
        else:
 
1829
            self.step('Upgrading working tree')
 
1830
            self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
 
1831
            self.make_lock('checkout')
 
1832
            self.put_format(
 
1833
                'checkout', bzrlib.workingtree.WorkingTreeFormat3())
 
1834
            self.bzrdir.transport.delete_multi(
 
1835
                self.garbage_inventories, self.pb)
 
1836
            for entry in checkout_files:
 
1837
                self.move_entry('checkout', entry)
 
1838
            if last_revision is not None:
 
1839
                self.bzrdir._control_files.put_utf8(
 
1840
                    'checkout/last-revision', last_revision)
 
1841
        self.bzrdir._control_files.put_utf8(
 
1842
            'branch-format', BzrDirMetaFormat1().get_format_string())
1760
1843
        return BzrDir.open(self.bzrdir.root_transport.base)
1761
1844
 
1762
1845
    def make_lock(self, name):