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.
1475
1544
versionedfile_kwargs={'factory':KnitPlainFactory()},
1478
def get_format_string(self):
1479
"""See RepositoryFormat.get_format_string()."""
1480
return "Bazaar-NG Knit Repository Format 1"
1482
def get_format_description(self):
1483
"""See RepositoryFormat.get_format_description()."""
1484
return "Knit repository format 1"
1486
1547
def _get_revision_store(self, repo_transport, control_files):
1487
1548
"""See RepositoryFormat._get_revision_store()."""
1488
1549
from bzrlib.store.revision.knit import KnitRevisionStore
1561
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)
1564
1711
# formats which have no format string are not discoverable
1565
1712
# and not independently creatable, so are not registered.
1566
1713
RepositoryFormat.register_format(RepositoryFormat7())
1567
1714
_default_format = RepositoryFormatKnit1()
1568
1715
RepositoryFormat.register_format(_default_format)
1716
RepositoryFormat.register_format(RepositoryFormatKnit2())
1569
1717
RepositoryFormat.set_default_format(_default_format)
1570
1718
_legacy_formats = [RepositoryFormat4(),
1571
1719
RepositoryFormat5(),
1584
1732
InterRepository.get(other).method_name(parameters).
1588
1736
"""The available optimised InterRepository types."""
1591
1738
def copy_content(self, revision_id=None, basis=None):
1592
"""Make a complete copy of the content in self into destination.
1594
This is a destructive operation! Do not use it on existing
1597
:param revision_id: Only copy the content needed to construct
1598
revision_id and its parents.
1599
:param basis: Copy the needed data preferentially from basis.
1602
self.target.set_make_working_trees(self.source.make_working_trees())
1603
except NotImplementedError:
1605
# grab the basis available data
1606
if basis is not None:
1607
self.target.fetch(basis, revision_id=revision_id)
1608
# but don't bother fetching if we have the needed data now.
1609
if (revision_id not in (None, NULL_REVISION) and
1610
self.target.has_revision(revision_id)):
1612
self.target.fetch(self.source, revision_id=revision_id)
1739
raise NotImplementedError(self.copy_content)
1615
1741
def fetch(self, revision_id=None, pb=None):
1616
1742
"""Fetch the content required to construct revision_id.
1625
1751
Returns the copied revision count and the failed revisions in a tuple:
1626
1752
(copied, failures).
1628
from bzrlib.fetch import GenericRepoFetcher
1629
mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1630
self.source, self.source._format, self.target, self.target._format)
1631
f = GenericRepoFetcher(to_repository=self.target,
1632
from_repository=self.source,
1633
last_revision=revision_id,
1635
return f.count_copied, f.failed_revisions
1754
raise NotImplementedError(self.fetch)
1637
1756
@needs_read_lock
1638
1757
def missing_revision_ids(self, revision_id=None):
1639
1758
"""Return the revision ids that source has that target does not.
1658
1777
return [rev_id for rev_id in source_ids if rev_id in result_set]
1661
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):
1662
1839
"""Optimised code paths between Weave based repositories."""
1664
1841
_matching_repo_format = RepositoryFormat7()
1838
2015
# that against the revision records.
1839
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)
1841
2097
InterRepository.register_optimiser(InterWeaveRepo)
1842
2098
InterRepository.register_optimiser(InterKnitRepo)
2099
InterRepository.register_optimiser(InterModel1and2)
2100
InterRepository.register_optimiser(InterKnit1and2)
1845
2103
class RepositoryTestProviderAdapter(object):
1910
2168
# default format.
1911
2169
# XXX: robertc 20060220 reinstate this when there are two supported
1912
2170
# formats which do not have an optimal code path between them.
1913
result.append((InterRepository,
1914
RepositoryFormat6(),
1915
RepositoryFormatKnit1()))
2171
#result.append((InterRepository,
2172
# RepositoryFormat6(),
2173
# RepositoryFormatKnit1()))
1916
2174
for optimiser in InterRepository._optimisers:
1917
result.append((optimiser,
1918
optimiser._matching_repo_format,
1919
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
1921
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()))
2182
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)
2185
2484
_unescape_map = {