/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-06 05:53:44 UTC
  • mfrom: (2063 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061006055344-e73b97b7c6ca6e72
[merge] bzr.dev 2063

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
    weave,
43
43
    weavefile,
44
44
    xml5,
 
45
    xml6,
45
46
    )
46
47
from bzrlib.osutils import (
47
48
    rand_bytes,
93
94
            "Mismatch between inventory revision" \
94
95
            " id and insertion revid (%r, %r)" % (inv.revision_id, revid)
95
96
        assert inv.root is not None
96
 
        inv_text = xml5.serializer_v5.write_inventory_to_string(inv)
 
97
        inv_text = self.serialise_inventory(inv)
97
98
        inv_sha1 = osutils.sha_string(inv_text)
98
99
        inv_vf = self.control_weaves.get_weave('inventory',
99
100
                                               self.get_transaction())
213
214
        # TODO: make sure to construct the right store classes, etc, depending
214
215
        # on whether escaping is required.
215
216
        self._warn_if_deprecated()
 
217
        self._serializer = xml5.serializer_v5
216
218
 
217
219
    def __repr__(self):
218
220
        return '%s(%r)' % (self.__class__.__name__, 
418
420
        revision_ids. Each altered file-ids has the exact revision_ids that
419
421
        altered it listed explicitly.
420
422
        """
421
 
        assert isinstance(self._format, (RepositoryFormat5,
422
 
                                         RepositoryFormat6,
423
 
                                         RepositoryFormat7,
424
 
                                         RepositoryFormatKnit1)), \
 
423
        assert self._serializer.support_altered_by_hack, \
425
424
            ("fileids_altered_by_revision_ids only supported for branches " 
426
425
             "which store inventory as unnested xml, not on %r" % self)
427
426
        selected_revision_ids = set(revision_ids)
436
435
        # revisions. We don't need to see all lines in the inventory because
437
436
        # only those added in an inventory in rev X can contain a revision=X
438
437
        # line.
439
 
        for line in w.iter_lines_added_or_present_in_versions(selected_revision_ids):
440
 
            start = line.find('file_id="')+9
441
 
            if start < 9: continue
442
 
            end = line.find('"', start)
443
 
            assert end>= 0
444
 
            file_id = _unescape_xml(line[start:end])
 
438
        pb = ui.ui_factory.nested_progress_bar()
 
439
        try:
 
440
            for line in w.iter_lines_added_or_present_in_versions(
 
441
                selected_revision_ids, pb=pb):
 
442
                start = line.find('file_id="')+9
 
443
                if start < 9: continue
 
444
                end = line.find('"', start)
 
445
                assert end>= 0
 
446
                file_id = _unescape_xml(line[start:end])
445
447
 
446
 
            start = line.find('revision="')+10
447
 
            if start < 10: continue
448
 
            end = line.find('"', start)
449
 
            assert end>= 0
450
 
            revision_id = _unescape_xml(line[start:end])
451
 
            if revision_id in selected_revision_ids:
452
 
                result.setdefault(file_id, set()).add(revision_id)
 
448
                start = line.find('revision="')+10
 
449
                if start < 10: continue
 
450
                end = line.find('"', start)
 
451
                assert end>= 0
 
452
                revision_id = _unescape_xml(line[start:end])
 
453
                if revision_id in selected_revision_ids:
 
454
                    result.setdefault(file_id, set()).add(revision_id)
 
455
        finally:
 
456
            pb.finished()
453
457
        return result
454
458
 
455
459
    @needs_read_lock
469
473
        :param revision_id: The expected revision id of the inventory.
470
474
        :param xml: A serialised inventory.
471
475
        """
472
 
        result = xml5.serializer_v5.read_inventory_from_string(xml)
 
476
        result = self._serializer.read_inventory_from_string(xml)
473
477
        result.root.revision = revision_id
474
478
        return result
475
479
 
 
480
    def serialise_inventory(self, inv):
 
481
        return self._serializer.write_inventory_to_string(inv)
 
482
 
476
483
    @needs_read_lock
477
484
    def get_inventory_xml(self, revision_id):
478
485
        """Get inventory XML as a file object."""
717
724
        warning("Format %s for %s is deprecated - please use 'bzr upgrade' to get better performance"
718
725
                % (self._format, self.bzrdir.transport.base))
719
726
 
 
727
    def supports_rich_root(self):
 
728
        return self._format.rich_root_data
 
729
 
720
730
 
721
731
class AllInOneRepository(Repository):
722
732
    """Legacy support - the repository behaviour for all-in-one branches."""
785
795
            parent_trees[p_id] = repository.revision_tree(None)
786
796
 
787
797
    inv = revision_tree.inventory
788
 
    
 
798
    entries = inv.iter_entries()
789
799
    # backwards compatability hack: skip the root id.
790
 
    entries = inv.iter_entries()
791
 
    entries.next()
 
800
    if not repository.supports_rich_root():
 
801
        path, root = entries.next()
 
802
        if root.revision != rev.revision_id:
 
803
            raise errors.IncompatibleRevision(repr(repository))
792
804
    # Add the texts that are not already present
793
805
    for path, ie in entries:
794
806
        w = repository.weave_store.get_weave_or_empty(ie.file_id,
1009
1021
        return self._get_revision_vf().get_parents(revision_id)
1010
1022
 
1011
1023
 
 
1024
class KnitRepository2(KnitRepository):
 
1025
    """"""
 
1026
    def __init__(self, _format, a_bzrdir, control_files, _revision_store,
 
1027
                 control_store, text_store):
 
1028
        KnitRepository.__init__(self, _format, a_bzrdir, control_files,
 
1029
                              _revision_store, control_store, text_store)
 
1030
        self._serializer = xml6.serializer_v6
 
1031
 
 
1032
    def deserialise_inventory(self, revision_id, xml):
 
1033
        """Transform the xml into an inventory object. 
 
1034
 
 
1035
        :param revision_id: The expected revision id of the inventory.
 
1036
        :param xml: A serialised inventory.
 
1037
        """
 
1038
        result = self._serializer.read_inventory_from_string(xml)
 
1039
        assert result.root.revision is not None
 
1040
        return result
 
1041
 
 
1042
    def serialise_inventory(self, inv):
 
1043
        """Transform the inventory object into XML text.
 
1044
 
 
1045
        :param revision_id: The expected revision id of the inventory.
 
1046
        :param xml: A serialised inventory.
 
1047
        """
 
1048
        assert inv.revision_id is not None
 
1049
        assert inv.root.revision is not None
 
1050
        return KnitRepository.serialise_inventory(self, inv)
 
1051
 
 
1052
    def get_commit_builder(self, branch, parents, config, timestamp=None, 
 
1053
                           timezone=None, committer=None, revprops=None, 
 
1054
                           revision_id=None):
 
1055
        """Obtain a CommitBuilder for this repository.
 
1056
        
 
1057
        :param branch: Branch to commit to.
 
1058
        :param parents: Revision ids of the parents of the new revision.
 
1059
        :param config: Configuration to use.
 
1060
        :param timestamp: Optional timestamp recorded for commit.
 
1061
        :param timezone: Optional timezone for timestamp.
 
1062
        :param committer: Optional committer to set for commit.
 
1063
        :param revprops: Optional dictionary of revision properties.
 
1064
        :param revision_id: Optional revision id.
 
1065
        """
 
1066
        return RootCommitBuilder(self, parents, config, timestamp, timezone,
 
1067
                                 committer, revprops, revision_id)
 
1068
 
 
1069
 
1012
1070
class RepositoryFormat(object):
1013
1071
    """A repository format.
1014
1072
 
1139
1197
        """
1140
1198
        return True
1141
1199
 
 
1200
    def check_conversion_target(self, target_format):
 
1201
        raise NotImplementedError(self.check_conversion_target)
 
1202
 
1142
1203
    def open(self, a_bzrdir, _found=False):
1143
1204
        """Return an instance of this format for the bzrdir a_bzrdir.
1144
1205
        
1163
1224
class PreSplitOutRepositoryFormat(RepositoryFormat):
1164
1225
    """Base class for the pre split out repository formats."""
1165
1226
 
 
1227
    rich_root_data = False
 
1228
 
1166
1229
    def initialize(self, a_bzrdir, shared=False, _internal=False):
1167
1230
        """Create a weave repository.
1168
1231
        
1229
1292
                                  control_store=control_store,
1230
1293
                                  text_store=text_store)
1231
1294
 
 
1295
    def check_conversion_target(self, target_format):
 
1296
        pass
 
1297
 
1232
1298
 
1233
1299
class RepositoryFormat4(PreSplitOutRepositoryFormat):
1234
1300
    """Bzr repository format 4.
1345
1411
class MetaDirRepositoryFormat(RepositoryFormat):
1346
1412
    """Common base class for the new repositories using the metadir layout."""
1347
1413
 
 
1414
    rich_root_data = False
 
1415
 
1348
1416
    def __init__(self):
1349
1417
        super(MetaDirRepositoryFormat, self).__init__()
1350
1418
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1403
1471
        """See RepositoryFormat.get_format_description()."""
1404
1472
        return "Weave repository format 7"
1405
1473
 
 
1474
    def check_conversion_target(self, target_format):
 
1475
        pass
 
1476
 
1406
1477
    def _get_revision_store(self, repo_transport, control_files):
1407
1478
        """See RepositoryFormat._get_revision_store()."""
1408
1479
        return self._get_text_rev_store(repo_transport,
1465
1536
                                 text_store=text_store)
1466
1537
 
1467
1538
 
1468
 
class RepositoryFormatKnit1(MetaDirRepositoryFormat):
1469
 
    """Bzr repository knit format 1.
 
1539
class RepositoryFormatKnit(MetaDirRepositoryFormat):
 
1540
    """Bzr repository knit format (generalized). 
1470
1541
 
1471
1542
    This repository format has:
1472
1543
     - knits for file texts and inventory
1477
1548
     - an optional 'shared-storage' flag
1478
1549
     - an optional 'no-working-trees' flag
1479
1550
     - a LockDir lock
1480
 
 
1481
 
    This format was introduced in bzr 0.8.
1482
1551
    """
1483
1552
 
1484
1553
    def _get_control_store(self, repo_transport, control_files):
1491
1560
            versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1492
1561
            )
1493
1562
 
1494
 
    def get_format_string(self):
1495
 
        """See RepositoryFormat.get_format_string()."""
1496
 
        return "Bazaar-NG Knit Repository Format 1"
1497
 
 
1498
 
    def get_format_description(self):
1499
 
        """See RepositoryFormat.get_format_description()."""
1500
 
        return "Knit repository format 1"
1501
 
 
1502
1563
    def _get_revision_store(self, repo_transport, control_files):
1503
1564
        """See RepositoryFormat._get_revision_store()."""
1504
1565
        from bzrlib.store.revision.knit import KnitRevisionStore
1581
1642
                              text_store=text_store)
1582
1643
 
1583
1644
 
 
1645
class RepositoryFormatKnit1(RepositoryFormatKnit):
 
1646
    """Bzr repository knit format 1.
 
1647
 
 
1648
    This repository format has:
 
1649
     - knits for file texts and inventory
 
1650
     - hash subdirectory based stores.
 
1651
     - knits for revisions and signatures
 
1652
     - TextStores for revisions and signatures.
 
1653
     - a format marker of its own
 
1654
     - an optional 'shared-storage' flag
 
1655
     - an optional 'no-working-trees' flag
 
1656
     - a LockDir lock
 
1657
 
 
1658
    This format was introduced in bzr 0.8.
 
1659
    """
 
1660
    def get_format_string(self):
 
1661
        """See RepositoryFormat.get_format_string()."""
 
1662
        return "Bazaar-NG Knit Repository Format 1"
 
1663
 
 
1664
    def get_format_description(self):
 
1665
        """See RepositoryFormat.get_format_description()."""
 
1666
        return "Knit repository format 1"
 
1667
 
 
1668
    def check_conversion_target(self, target_format):
 
1669
        pass
 
1670
 
 
1671
 
 
1672
class RepositoryFormatKnit2(RepositoryFormatKnit):
 
1673
    """Bzr repository knit format 2.
 
1674
 
 
1675
    THIS FORMAT IS EXPERIMENTAL
 
1676
    This repository format has:
 
1677
     - knits for file texts and inventory
 
1678
     - hash subdirectory based stores.
 
1679
     - knits for revisions and signatures
 
1680
     - TextStores for revisions and signatures.
 
1681
     - a format marker of its own
 
1682
     - an optional 'shared-storage' flag
 
1683
     - an optional 'no-working-trees' flag
 
1684
     - a LockDir lock
 
1685
     - Support for recording full info about the tree root
 
1686
 
 
1687
    """
 
1688
    
 
1689
    rich_root_data = True
 
1690
 
 
1691
    def get_format_string(self):
 
1692
        """See RepositoryFormat.get_format_string()."""
 
1693
        return "Bazaar Knit Repository Format 2\n"
 
1694
 
 
1695
    def get_format_description(self):
 
1696
        """See RepositoryFormat.get_format_description()."""
 
1697
        return "Knit repository format 2"
 
1698
 
 
1699
    def check_conversion_target(self, target_format):
 
1700
        if not target_format.rich_root_data:
 
1701
            raise errors.BadConversionTarget(
 
1702
                'Does not support rich root data.', target_format)
 
1703
 
 
1704
    def open(self, a_bzrdir, _found=False, _override_transport=None):
 
1705
        """See RepositoryFormat.open().
 
1706
        
 
1707
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
 
1708
                                    repository at a slightly different url
 
1709
                                    than normal. I.e. during 'upgrade'.
 
1710
        """
 
1711
        if not _found:
 
1712
            format = RepositoryFormat.find_format(a_bzrdir)
 
1713
            assert format.__class__ ==  self.__class__
 
1714
        if _override_transport is not None:
 
1715
            repo_transport = _override_transport
 
1716
        else:
 
1717
            repo_transport = a_bzrdir.get_repository_transport(None)
 
1718
        control_files = lockable_files.LockableFiles(repo_transport, 'lock',
 
1719
                                                     lockdir.LockDir)
 
1720
        text_store = self._get_text_store(repo_transport, control_files)
 
1721
        control_store = self._get_control_store(repo_transport, control_files)
 
1722
        _revision_store = self._get_revision_store(repo_transport, control_files)
 
1723
        return KnitRepository2(_format=self,
 
1724
                               a_bzrdir=a_bzrdir,
 
1725
                               control_files=control_files,
 
1726
                               _revision_store=_revision_store,
 
1727
                               control_store=control_store,
 
1728
                               text_store=text_store)
 
1729
 
 
1730
 
 
1731
 
1584
1732
# formats which have no format string are not discoverable
1585
1733
# and not independently creatable, so are not registered.
1586
1734
RepositoryFormat.register_format(RepositoryFormat7())
1587
1735
_default_format = RepositoryFormatKnit1()
1588
1736
RepositoryFormat.register_format(_default_format)
 
1737
RepositoryFormat.register_format(RepositoryFormatKnit2())
1589
1738
RepositoryFormat.set_default_format(_default_format)
1590
1739
_legacy_formats = [RepositoryFormat4(),
1591
1740
                   RepositoryFormat5(),
1604
1753
    InterRepository.get(other).method_name(parameters).
1605
1754
    """
1606
1755
 
1607
 
    _optimisers = set()
 
1756
    _optimisers = []
1608
1757
    """The available optimised InterRepository types."""
1609
1758
 
1610
 
    @needs_write_lock
1611
1759
    def copy_content(self, revision_id=None, basis=None):
1612
 
        """Make a complete copy of the content in self into destination.
1613
 
        
1614
 
        This is a destructive operation! Do not use it on existing 
1615
 
        repositories.
1616
 
 
1617
 
        :param revision_id: Only copy the content needed to construct
1618
 
                            revision_id and its parents.
1619
 
        :param basis: Copy the needed data preferentially from basis.
1620
 
        """
1621
 
        try:
1622
 
            self.target.set_make_working_trees(self.source.make_working_trees())
1623
 
        except NotImplementedError:
1624
 
            pass
1625
 
        # grab the basis available data
1626
 
        if basis is not None:
1627
 
            self.target.fetch(basis, revision_id=revision_id)
1628
 
        # but don't bother fetching if we have the needed data now.
1629
 
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
1630
 
            self.target.has_revision(revision_id)):
1631
 
            return
1632
 
        self.target.fetch(self.source, revision_id=revision_id)
1633
 
 
1634
 
    @needs_write_lock
 
1760
        raise NotImplementedError(self.copy_content)
 
1761
 
1635
1762
    def fetch(self, revision_id=None, pb=None):
1636
1763
        """Fetch the content required to construct revision_id.
1637
1764
 
1638
 
        The content is copied from source to target.
 
1765
        The content is copied from self.source to self.target.
1639
1766
 
1640
1767
        :param revision_id: if None all content is copied, if NULL_REVISION no
1641
1768
                            content is copied.
1645
1772
        Returns the copied revision count and the failed revisions in a tuple:
1646
1773
        (copied, failures).
1647
1774
        """
1648
 
        from bzrlib.fetch import GenericRepoFetcher
1649
 
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1650
 
               self.source, self.source._format, self.target, self.target._format)
1651
 
        f = GenericRepoFetcher(to_repository=self.target,
1652
 
                               from_repository=self.source,
1653
 
                               last_revision=revision_id,
1654
 
                               pb=pb)
1655
 
        return f.count_copied, f.failed_revisions
1656
 
 
 
1775
        raise NotImplementedError(self.fetch)
 
1776
   
1657
1777
    @needs_read_lock
1658
1778
    def missing_revision_ids(self, revision_id=None):
1659
1779
        """Return the revision ids that source has that target does not.
1678
1798
        return [rev_id for rev_id in source_ids if rev_id in result_set]
1679
1799
 
1680
1800
 
1681
 
class InterWeaveRepo(InterRepository):
 
1801
class InterSameDataRepository(InterRepository):
 
1802
    """Code for converting between repositories that represent the same data.
 
1803
    
 
1804
    Data format and model must match for this to work.
 
1805
    """
 
1806
 
 
1807
    _matching_repo_format = RepositoryFormat4()
 
1808
    """Repository format for testing with."""
 
1809
 
 
1810
    @staticmethod
 
1811
    def is_compatible(source, target):
 
1812
        if not isinstance(source, Repository):
 
1813
            return False
 
1814
        if not isinstance(target, Repository):
 
1815
            return False
 
1816
        if source._format.rich_root_data == target._format.rich_root_data:
 
1817
            return True
 
1818
        else:
 
1819
            return False
 
1820
 
 
1821
    @needs_write_lock
 
1822
    def copy_content(self, revision_id=None, basis=None):
 
1823
        """Make a complete copy of the content in self into destination.
 
1824
        
 
1825
        This is a destructive operation! Do not use it on existing 
 
1826
        repositories.
 
1827
 
 
1828
        :param revision_id: Only copy the content needed to construct
 
1829
                            revision_id and its parents.
 
1830
        :param basis: Copy the needed data preferentially from basis.
 
1831
        """
 
1832
        try:
 
1833
            self.target.set_make_working_trees(self.source.make_working_trees())
 
1834
        except NotImplementedError:
 
1835
            pass
 
1836
        # grab the basis available data
 
1837
        if basis is not None:
 
1838
            self.target.fetch(basis, revision_id=revision_id)
 
1839
        # but don't bother fetching if we have the needed data now.
 
1840
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
 
1841
            self.target.has_revision(revision_id)):
 
1842
            return
 
1843
        self.target.fetch(self.source, revision_id=revision_id)
 
1844
 
 
1845
    @needs_write_lock
 
1846
    def fetch(self, revision_id=None, pb=None):
 
1847
        """See InterRepository.fetch()."""
 
1848
        from bzrlib.fetch import GenericRepoFetcher
 
1849
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
 
1850
               self.source, self.source._format, self.target, 
 
1851
               self.target._format)
 
1852
        f = GenericRepoFetcher(to_repository=self.target,
 
1853
                               from_repository=self.source,
 
1854
                               last_revision=revision_id,
 
1855
                               pb=pb)
 
1856
        return f.count_copied, f.failed_revisions
 
1857
 
 
1858
 
 
1859
class InterWeaveRepo(InterSameDataRepository):
1682
1860
    """Optimised code paths between Weave based repositories."""
1683
1861
 
1684
1862
    _matching_repo_format = RepositoryFormat7()
1796
1974
            return self.source._eliminate_revisions_not_present(required_topo_revisions)
1797
1975
 
1798
1976
 
1799
 
class InterKnitRepo(InterRepository):
 
1977
class InterKnitRepo(InterSameDataRepository):
1800
1978
    """Optimised code paths between Knit based repositories."""
1801
1979
 
1802
1980
    _matching_repo_format = RepositoryFormatKnit1()
1858
2036
            # that against the revision records.
1859
2037
            return self.source._eliminate_revisions_not_present(required_topo_revisions)
1860
2038
 
 
2039
 
 
2040
class InterModel1and2(InterRepository):
 
2041
 
 
2042
    _matching_repo_format = None
 
2043
 
 
2044
    @staticmethod
 
2045
    def is_compatible(source, target):
 
2046
        if not isinstance(source, Repository):
 
2047
            return False
 
2048
        if not isinstance(target, Repository):
 
2049
            return False
 
2050
        if not source._format.rich_root_data and target._format.rich_root_data:
 
2051
            return True
 
2052
        else:
 
2053
            return False
 
2054
 
 
2055
    @needs_write_lock
 
2056
    def fetch(self, revision_id=None, pb=None):
 
2057
        """See InterRepository.fetch()."""
 
2058
        from bzrlib.fetch import Model1toKnit2Fetcher
 
2059
        f = Model1toKnit2Fetcher(to_repository=self.target,
 
2060
                                 from_repository=self.source,
 
2061
                                 last_revision=revision_id,
 
2062
                                 pb=pb)
 
2063
        return f.count_copied, f.failed_revisions
 
2064
 
 
2065
    @needs_write_lock
 
2066
    def copy_content(self, revision_id=None, basis=None):
 
2067
        """Make a complete copy of the content in self into destination.
 
2068
        
 
2069
        This is a destructive operation! Do not use it on existing 
 
2070
        repositories.
 
2071
 
 
2072
        :param revision_id: Only copy the content needed to construct
 
2073
                            revision_id and its parents.
 
2074
        :param basis: Copy the needed data preferentially from basis.
 
2075
        """
 
2076
        try:
 
2077
            self.target.set_make_working_trees(self.source.make_working_trees())
 
2078
        except NotImplementedError:
 
2079
            pass
 
2080
        # grab the basis available data
 
2081
        if basis is not None:
 
2082
            self.target.fetch(basis, revision_id=revision_id)
 
2083
        # but don't bother fetching if we have the needed data now.
 
2084
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
 
2085
            self.target.has_revision(revision_id)):
 
2086
            return
 
2087
        self.target.fetch(self.source, revision_id=revision_id)
 
2088
 
 
2089
 
 
2090
class InterKnit1and2(InterKnitRepo):
 
2091
 
 
2092
    _matching_repo_format = None
 
2093
 
 
2094
    @staticmethod
 
2095
    def is_compatible(source, target):
 
2096
        """Be compatible with Knit1 source and Knit2 target"""
 
2097
        try:
 
2098
            return (isinstance(source._format, (RepositoryFormatKnit1)) and
 
2099
                    isinstance(target._format, (RepositoryFormatKnit2)))
 
2100
        except AttributeError:
 
2101
            return False
 
2102
 
 
2103
    @needs_write_lock
 
2104
    def fetch(self, revision_id=None, pb=None):
 
2105
        """See InterRepository.fetch()."""
 
2106
        from bzrlib.fetch import Knit1to2Fetcher
 
2107
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
 
2108
               self.source, self.source._format, self.target, 
 
2109
               self.target._format)
 
2110
        f = Knit1to2Fetcher(to_repository=self.target,
 
2111
                            from_repository=self.source,
 
2112
                            last_revision=revision_id,
 
2113
                            pb=pb)
 
2114
        return f.count_copied, f.failed_revisions
 
2115
 
 
2116
 
 
2117
InterRepository.register_optimiser(InterSameDataRepository)
1861
2118
InterRepository.register_optimiser(InterWeaveRepo)
1862
2119
InterRepository.register_optimiser(InterKnitRepo)
 
2120
InterRepository.register_optimiser(InterModel1and2)
 
2121
InterRepository.register_optimiser(InterKnit1and2)
1863
2122
 
1864
2123
 
1865
2124
class RepositoryTestProviderAdapter(object):
1930
2189
        # default format.
1931
2190
        # XXX: robertc 20060220 reinstate this when there are two supported
1932
2191
        # formats which do not have an optimal code path between them.
1933
 
        result.append((InterRepository,
1934
 
                       RepositoryFormat6(),
1935
 
                       RepositoryFormatKnit1()))
 
2192
        #result.append((InterRepository,
 
2193
        #               RepositoryFormat6(),
 
2194
        #               RepositoryFormatKnit1()))
1936
2195
        for optimiser in InterRepository._optimisers:
1937
 
            result.append((optimiser,
1938
 
                           optimiser._matching_repo_format,
1939
 
                           optimiser._matching_repo_format
1940
 
                           ))
 
2196
            if optimiser._matching_repo_format is not None:
 
2197
                result.append((optimiser,
 
2198
                               optimiser._matching_repo_format,
 
2199
                               optimiser._matching_repo_format
 
2200
                               ))
1941
2201
        # if there are specific combinations we want to use, we can add them 
1942
2202
        # here.
 
2203
        result.append((InterModel1and2, RepositoryFormat5(),
 
2204
                       RepositoryFormatKnit2()))
 
2205
        result.append((InterKnit1and2, RepositoryFormatKnit1(),
 
2206
                       RepositoryFormatKnit2()))
1943
2207
        return result
1944
2208
 
1945
2209
 
1972
2236
        self.step('Moving repository to repository.backup')
1973
2237
        self.repo_dir.transport.move('repository', 'repository.backup')
1974
2238
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
 
2239
        repo._format.check_conversion_target(self.target_format)
1975
2240
        self.source_repo = repo._format.open(self.repo_dir,
1976
2241
            _found=True,
1977
2242
            _override_transport=backup_transport)
2063
2328
            self.new_inventory, self._config)
2064
2329
        return self._new_revision_id
2065
2330
 
 
2331
    def revision_tree(self):
 
2332
        """Return the tree that was just committed.
 
2333
 
 
2334
        After calling commit() this can be called to get a RevisionTree
 
2335
        representing the newly committed tree. This is preferred to
 
2336
        calling Repository.revision_tree() because that may require
 
2337
        deserializing the inventory, while we already have a copy in
 
2338
        memory.
 
2339
        """
 
2340
        return RevisionTree(self.repository, self.new_inventory,
 
2341
                            self._new_revision_id)
 
2342
 
2066
2343
    def finish_inventory(self):
2067
2344
        """Tell the builder that the inventory is finished."""
2068
2345
        if self.new_inventory.root is None:
2124
2401
 
2125
2402
        # In this revision format, root entries have no knit or weave
2126
2403
        if ie is self.new_inventory.root:
2127
 
            if len(parent_invs):
2128
 
                ie.revision = parent_invs[0].root.revision
2129
 
            else:
2130
 
                ie.revision = None
 
2404
            # When serializing out to disk and back in
 
2405
            # root.revision is always _new_revision_id
 
2406
            ie.revision = self._new_revision_id
2131
2407
            return
2132
2408
        previous_entries = ie.find_previous_heads(
2133
2409
            parent_invs,
2203
2479
    record_root_entry = True
2204
2480
 
2205
2481
 
 
2482
class RootCommitBuilder(CommitBuilder):
 
2483
    """This commitbuilder actually records the root id"""
 
2484
    
 
2485
    record_root_entry = True
 
2486
 
 
2487
    def record_entry_contents(self, ie, parent_invs, path, tree):
 
2488
        """Record the content of ie from tree into the commit if needed.
 
2489
 
 
2490
        Side effect: sets ie.revision when unchanged
 
2491
 
 
2492
        :param ie: An inventory entry present in the commit.
 
2493
        :param parent_invs: The inventories of the parent revisions of the
 
2494
            commit.
 
2495
        :param path: The path the entry is at in the tree.
 
2496
        :param tree: The tree which contains this entry and should be used to 
 
2497
        obtain content.
 
2498
        """
 
2499
        assert self.new_inventory.root is not None or ie.parent_id is None
 
2500
        self.new_inventory.add(ie)
 
2501
 
 
2502
        # ie.revision is always None if the InventoryEntry is considered
 
2503
        # for committing. ie.snapshot will record the correct revision 
 
2504
        # which may be the sole parent if it is untouched.
 
2505
        if ie.revision is not None:
 
2506
            return
 
2507
 
 
2508
        previous_entries = ie.find_previous_heads(
 
2509
            parent_invs,
 
2510
            self.repository.weave_store,
 
2511
            self.repository.get_transaction())
 
2512
        # we are creating a new revision for ie in the history store
 
2513
        # and inventory.
 
2514
        ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
 
2515
 
 
2516
 
2206
2517
_unescape_map = {
2207
2518
    'apos':"'",
2208
2519
    'quot':'"',