989
1001
return self._get_revision_vf().get_parents(revision_id)
1004
class KnitRepository2(KnitRepository):
1006
def __init__(self, _format, a_bzrdir, control_files, _revision_store,
1007
control_store, text_store):
1008
KnitRepository.__init__(self, _format, a_bzrdir, control_files,
1009
_revision_store, control_store, text_store)
1010
self._serializer = xml6.serializer_v6
1012
def deserialise_inventory(self, revision_id, xml):
1013
"""Transform the xml into an inventory object.
1015
:param revision_id: The expected revision id of the inventory.
1016
:param xml: A serialised inventory.
1018
result = self._serializer.read_inventory_from_string(xml)
1019
assert result.root.revision is not None
1022
def serialise_inventory(self, inv):
1023
"""Transform the inventory object into XML text.
1025
:param revision_id: The expected revision id of the inventory.
1026
:param xml: A serialised inventory.
1028
assert inv.revision_id is not None
1029
assert inv.root.revision is not None
1030
return KnitRepository.serialise_inventory(self, inv)
1032
def get_commit_builder(self, branch, parents, config, timestamp=None,
1033
timezone=None, committer=None, revprops=None,
1035
"""Obtain a CommitBuilder for this repository.
1037
:param branch: Branch to commit to.
1038
:param parents: Revision ids of the parents of the new revision.
1039
:param config: Configuration to use.
1040
:param timestamp: Optional timestamp recorded for commit.
1041
:param timezone: Optional timezone for timestamp.
1042
:param committer: Optional committer to set for commit.
1043
:param revprops: Optional dictionary of revision properties.
1044
:param revision_id: Optional revision id.
1046
return RootCommitBuilder(self, parents, config, timestamp, timezone,
1047
committer, revprops, revision_id)
992
1050
class RepositoryFormat(object):
993
1051
"""A repository format.
1473
1544
versionedfile_kwargs={'factory':KnitPlainFactory()},
1476
def get_format_string(self):
1477
"""See RepositoryFormat.get_format_string()."""
1478
return "Bazaar-NG Knit Repository Format 1"
1480
def get_format_description(self):
1481
"""See RepositoryFormat.get_format_description()."""
1482
return "Knit repository format 1"
1484
1547
def _get_revision_store(self, repo_transport, control_files):
1485
1548
"""See RepositoryFormat._get_revision_store()."""
1486
1549
from bzrlib.store.revision.knit import KnitRevisionStore
1554
1622
text_store=text_store)
1625
class RepositoryFormatKnit1(RepositoryFormatKnit):
1626
"""Bzr repository knit format 1.
1628
This repository format has:
1629
- knits for file texts and inventory
1630
- hash subdirectory based stores.
1631
- knits for revisions and signatures
1632
- TextStores for revisions and signatures.
1633
- a format marker of its own
1634
- an optional 'shared-storage' flag
1635
- an optional 'no-working-trees' flag
1638
This format was introduced in bzr 0.8.
1640
def get_format_string(self):
1641
"""See RepositoryFormat.get_format_string()."""
1642
return "Bazaar-NG Knit Repository Format 1"
1644
def get_format_description(self):
1645
"""See RepositoryFormat.get_format_description()."""
1646
return "Knit repository format 1"
1648
def check_conversion_target(self, target_format):
1652
class RepositoryFormatKnit2(RepositoryFormatKnit):
1653
"""Bzr repository knit format 2.
1655
THIS FORMAT IS EXPERIMENTAL
1656
This repository format has:
1657
- knits for file texts and inventory
1658
- hash subdirectory based stores.
1659
- knits for revisions and signatures
1660
- TextStores for revisions and signatures.
1661
- a format marker of its own
1662
- an optional 'shared-storage' flag
1663
- an optional 'no-working-trees' flag
1665
- Support for recording full info about the tree root
1669
rich_root_data = True
1671
def get_format_string(self):
1672
"""See RepositoryFormat.get_format_string()."""
1673
return "Bazaar Knit Repository Format 2\n"
1675
def get_format_description(self):
1676
"""See RepositoryFormat.get_format_description()."""
1677
return "Knit repository format 2"
1679
def check_conversion_target(self, target_format):
1680
if not target_format.rich_root_data:
1681
raise errors.BadConversionTarget(
1682
'Does not support rich root data.', target_format)
1684
def open(self, a_bzrdir, _found=False, _override_transport=None):
1685
"""See RepositoryFormat.open().
1687
:param _override_transport: INTERNAL USE ONLY. Allows opening the
1688
repository at a slightly different url
1689
than normal. I.e. during 'upgrade'.
1692
format = RepositoryFormat.find_format(a_bzrdir)
1693
assert format.__class__ == self.__class__
1694
if _override_transport is not None:
1695
repo_transport = _override_transport
1697
repo_transport = a_bzrdir.get_repository_transport(None)
1698
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1699
text_store = self._get_text_store(repo_transport, control_files)
1700
control_store = self._get_control_store(repo_transport, control_files)
1701
_revision_store = self._get_revision_store(repo_transport, control_files)
1702
return KnitRepository2(_format=self,
1704
control_files=control_files,
1705
_revision_store=_revision_store,
1706
control_store=control_store,
1707
text_store=text_store)
1557
1711
# formats which have no format string are not discoverable
1558
1712
# and not independently creatable, so are not registered.
1559
1713
RepositoryFormat.register_format(RepositoryFormat7())
1560
1714
_default_format = RepositoryFormatKnit1()
1561
1715
RepositoryFormat.register_format(_default_format)
1716
RepositoryFormat.register_format(RepositoryFormatKnit2())
1562
1717
RepositoryFormat.set_default_format(_default_format)
1563
1718
_legacy_formats = [RepositoryFormat4(),
1564
1719
RepositoryFormat5(),
1577
1732
InterRepository.get(other).method_name(parameters).
1581
1736
"""The available optimised InterRepository types."""
1584
1738
def copy_content(self, revision_id=None, basis=None):
1585
"""Make a complete copy of the content in self into destination.
1587
This is a destructive operation! Do not use it on existing
1590
:param revision_id: Only copy the content needed to construct
1591
revision_id and its parents.
1592
:param basis: Copy the needed data preferentially from basis.
1595
self.target.set_make_working_trees(self.source.make_working_trees())
1596
except NotImplementedError:
1598
# grab the basis available data
1599
if basis is not None:
1600
self.target.fetch(basis, revision_id=revision_id)
1601
# but don't bother fetching if we have the needed data now.
1602
if (revision_id not in (None, NULL_REVISION) and
1603
self.target.has_revision(revision_id)):
1605
self.target.fetch(self.source, revision_id=revision_id)
1739
raise NotImplementedError(self.copy_content)
1608
1741
def fetch(self, revision_id=None, pb=None):
1609
1742
"""Fetch the content required to construct revision_id.
1611
The content is copied from source to target.
1744
The content is copied from self.source to self.target.
1613
1746
:param revision_id: if None all content is copied, if NULL_REVISION no
1614
1747
content is copied.
1618
1751
Returns the copied revision count and the failed revisions in a tuple:
1619
1752
(copied, failures).
1621
from bzrlib.fetch import GenericRepoFetcher
1622
mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1623
self.source, self.source._format, self.target, self.target._format)
1624
f = GenericRepoFetcher(to_repository=self.target,
1625
from_repository=self.source,
1626
last_revision=revision_id,
1628
return f.count_copied, f.failed_revisions
1754
raise NotImplementedError(self.fetch)
1630
1756
@needs_read_lock
1631
1757
def missing_revision_ids(self, revision_id=None):
1632
1758
"""Return the revision ids that source has that target does not.
1651
1777
return [rev_id for rev_id in source_ids if rev_id in result_set]
1654
class InterWeaveRepo(InterRepository):
1780
class InterSameDataRepository(InterRepository):
1781
"""Code for converting between repositories that represent the same data.
1783
Data format and model must match for this to work.
1786
_matching_repo_format = RepositoryFormat4()
1787
"""Repository format for testing with."""
1790
def is_compatible(source, target):
1791
if not isinstance(source, Repository):
1793
if not isinstance(target, Repository):
1795
if source._format.rich_root_data == target._format.rich_root_data:
1801
def copy_content(self, revision_id=None, basis=None):
1802
"""Make a complete copy of the content in self into destination.
1804
This is a destructive operation! Do not use it on existing
1807
:param revision_id: Only copy the content needed to construct
1808
revision_id and its parents.
1809
:param basis: Copy the needed data preferentially from basis.
1812
self.target.set_make_working_trees(self.source.make_working_trees())
1813
except NotImplementedError:
1815
# grab the basis available data
1816
if basis is not None:
1817
self.target.fetch(basis, revision_id=revision_id)
1818
# but don't bother fetching if we have the needed data now.
1819
if (revision_id not in (None, NULL_REVISION) and
1820
self.target.has_revision(revision_id)):
1822
self.target.fetch(self.source, revision_id=revision_id)
1825
def fetch(self, revision_id=None, pb=None):
1826
"""See InterRepository.fetch()."""
1827
from bzrlib.fetch import GenericRepoFetcher
1828
mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1829
self.source, self.source._format, self.target,
1830
self.target._format)
1831
f = GenericRepoFetcher(to_repository=self.target,
1832
from_repository=self.source,
1833
last_revision=revision_id,
1835
return f.count_copied, f.failed_revisions
1838
class InterWeaveRepo(InterSameDataRepository):
1655
1839
"""Optimised code paths between Weave based repositories."""
1657
1841
_matching_repo_format = RepositoryFormat7()
1831
2015
# that against the revision records.
1832
2016
return self.source._eliminate_revisions_not_present(required_topo_revisions)
2019
class InterModel1and2(InterRepository):
2021
_matching_repo_format = None
2024
def is_compatible(source, target):
2025
if not isinstance(source, Repository):
2027
if not isinstance(target, Repository):
2029
if not source._format.rich_root_data and target._format.rich_root_data:
2035
def fetch(self, revision_id=None, pb=None):
2036
"""See InterRepository.fetch()."""
2037
from bzrlib.fetch import Model1toKnit2Fetcher
2038
f = Model1toKnit2Fetcher(to_repository=self.target,
2039
from_repository=self.source,
2040
last_revision=revision_id,
2042
return f.count_copied, f.failed_revisions
2045
def copy_content(self, revision_id=None, basis=None):
2046
"""Make a complete copy of the content in self into destination.
2048
This is a destructive operation! Do not use it on existing
2051
:param revision_id: Only copy the content needed to construct
2052
revision_id and its parents.
2053
:param basis: Copy the needed data preferentially from basis.
2056
self.target.set_make_working_trees(self.source.make_working_trees())
2057
except NotImplementedError:
2059
# grab the basis available data
2060
if basis is not None:
2061
self.target.fetch(basis, revision_id=revision_id)
2062
# but don't bother fetching if we have the needed data now.
2063
if (revision_id not in (None, NULL_REVISION) and
2064
self.target.has_revision(revision_id)):
2066
self.target.fetch(self.source, revision_id=revision_id)
2069
class InterKnit1and2(InterKnitRepo):
2071
_matching_repo_format = None
2074
def is_compatible(source, target):
2075
"""Be compatible with Knit1 source and Knit2 target"""
2077
return (isinstance(source._format, (RepositoryFormatKnit1)) and
2078
isinstance(target._format, (RepositoryFormatKnit2)))
2079
except AttributeError:
2083
def fetch(self, revision_id=None, pb=None):
2084
"""See InterRepository.fetch()."""
2085
from bzrlib.fetch import Knit1to2Fetcher
2086
mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
2087
self.source, self.source._format, self.target,
2088
self.target._format)
2089
f = Knit1to2Fetcher(to_repository=self.target,
2090
from_repository=self.source,
2091
last_revision=revision_id,
2093
return f.count_copied, f.failed_revisions
2096
InterRepository.register_optimiser(InterSameDataRepository)
1834
2097
InterRepository.register_optimiser(InterWeaveRepo)
1835
2098
InterRepository.register_optimiser(InterKnitRepo)
2099
InterRepository.register_optimiser(InterModel1and2)
2100
InterRepository.register_optimiser(InterKnit1and2)
1838
2103
class RepositoryTestProviderAdapter(object):
1903
2168
# default format.
1904
2169
# XXX: robertc 20060220 reinstate this when there are two supported
1905
2170
# formats which do not have an optimal code path between them.
1906
result.append((InterRepository,
1907
RepositoryFormat6(),
1908
RepositoryFormatKnit1()))
2171
#result.append((InterRepository,
2172
# RepositoryFormat6(),
2173
# RepositoryFormatKnit1()))
1909
2174
for optimiser in InterRepository._optimisers:
1910
result.append((optimiser,
1911
optimiser._matching_repo_format,
1912
optimiser._matching_repo_format
2175
if optimiser._matching_repo_format is not None:
2176
result.append((optimiser,
2177
optimiser._matching_repo_format,
2178
optimiser._matching_repo_format
1914
2180
# if there are specific combinations we want to use, we can add them
2182
result.append((InterModel1and2, RepositoryFormat5(),
2183
RepositoryFormatKnit2()))
2184
result.append((InterKnit1and2, RepositoryFormatKnit1(),
2185
RepositoryFormatKnit2()))
2175
2446
record_root_entry = True
2449
class RootCommitBuilder(CommitBuilder):
2450
"""This commitbuilder actually records the root id"""
2452
record_root_entry = True
2454
def record_entry_contents(self, ie, parent_invs, path, tree):
2455
"""Record the content of ie from tree into the commit if needed.
2457
Side effect: sets ie.revision when unchanged
2459
:param ie: An inventory entry present in the commit.
2460
:param parent_invs: The inventories of the parent revisions of the
2462
:param path: The path the entry is at in the tree.
2463
:param tree: The tree which contains this entry and should be used to
2466
assert self.new_inventory.root is not None or ie.parent_id is None
2467
self.new_inventory.add(ie)
2469
# ie.revision is always None if the InventoryEntry is considered
2470
# for committing. ie.snapshot will record the correct revision
2471
# which may be the sole parent if it is untouched.
2472
if ie.revision is not None:
2475
previous_entries = ie.find_previous_heads(
2477
self.repository.weave_store,
2478
self.repository.get_transaction())
2479
# we are creating a new revision for ie in the history store
2481
ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
2178
2484
_unescape_map = {