Rev 6372: (jelmer) Add HPSS call for retrieving inventories. (Jelmer Vernooij) in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Dec 14 21:50:55 UTC 2011
At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 6372 [merge]
revision-id: pqm at pqm.ubuntu.com-20111214215054-kbzhlka9gtbd4zd7
parent: pqm at pqm.ubuntu.com-20111214203958-q3d07mehwgt2oeku
parent: jelmer at samba.org-20111214212407-6lj47iqhmuwrgq0y
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2011-12-14 21:50:54 +0000
message:
(jelmer) Add HPSS call for retrieving inventories. (Jelmer Vernooij)
modified:
bzrlib/remote.py remote.py-20060720103555-yeeg2x51vn0rbtdp-1
bzrlib/smart/repository.py repository.py-20061128022038-vr5wy5bubyb8xttk-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/blackbox/test_annotate.py testannotate.py-20051013044000-457f44801bfa9d39
bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
bzrlib/tests/blackbox/test_cat.py test_cat.py-20051201162916-f0937e4e19ea24b3
bzrlib/tests/blackbox/test_checkout.py test_checkout.py-20060211231752-a5cde67cf70af854
bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
bzrlib/tests/blackbox/test_ls.py test_ls.py-20060712232047-0jraqpecwngee12y-1
bzrlib/tests/blackbox/test_sign_my_commits.py test_sign_my_commits.py-20060215152957-270238a1ffacc841
bzrlib/tests/per_interbranch/test_push.py test_push.py-20090330192649-pca31sb2ubbtcs15-1
bzrlib/tests/per_repository_chk/test_supported.py test_supported.py-20080925063728-k65ry0n2rhta6t34-1
bzrlib/tests/per_repository_vf/test_add_inventory_by_delta.py test_add_inventory_d-20081013002626-rut81igtlqb4590z-1
bzrlib/tests/test_remote.py test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
bzrlib/tests/test_smart.py test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py 2011-12-14 12:33:04 +0000
+++ b/bzrlib/remote.py 2011-12-14 20:08:26 +0000
@@ -27,6 +27,7 @@
errors,
gpg,
graph,
+ inventory_delta,
lock,
lockdir,
osutils,
@@ -1830,9 +1831,125 @@
def get_inventory(self, revision_id):
return list(self.iter_inventories([revision_id]))[0]
+ def _iter_inventories_rpc(self, revision_ids, ordering):
+ if ordering is None:
+ ordering = 'unordered'
+ path = self.bzrdir._path_for_remote_call(self._client)
+ body = "\n".join(revision_ids)
+ response_tuple, response_handler = (
+ self._call_with_body_bytes_expecting_body(
+ "VersionedFileRepository.get_inventories",
+ (path, ordering), body))
+ if response_tuple[0] != "ok":
+ raise errors.UnexpectedSmartServerResponse(response_tuple)
+ deserializer = inventory_delta.InventoryDeltaDeserializer()
+ byte_stream = response_handler.read_streamed_body()
+ decoded = smart_repo._byte_stream_to_stream(byte_stream)
+ if decoded is None:
+ # no results whatsoever
+ return
+ src_format, stream = decoded
+ if src_format.network_name() != self._format.network_name():
+ raise AssertionError(
+ "Mismatched RemoteRepository and stream src %r, %r" % (
+ src_format.network_name(), self._format.network_name()))
+ # ignore the src format, it's not really relevant
+ prev_inv = Inventory(root_id=None,
+ revision_id=_mod_revision.NULL_REVISION)
+ # there should be just one substream, with inventory deltas
+ substream_kind, substream = stream.next()
+ if substream_kind != "inventory-deltas":
+ raise AssertionError(
+ "Unexpected stream %r received" % substream_kind)
+ for record in substream:
+ (parent_id, new_id, versioned_root, tree_references, invdelta) = (
+ deserializer.parse_text_bytes(record.get_bytes_as("fulltext")))
+ if parent_id != prev_inv.revision_id:
+ raise AssertionError("invalid base %r != %r" % (parent_id,
+ prev_inv.revision_id))
+ inv = prev_inv.create_by_apply_delta(invdelta, new_id)
+ yield inv, inv.revision_id
+ prev_inv = inv
+
+ def _iter_inventories_vfs(self, revision_ids, ordering=None):
+ self._ensure_real()
+ return self._real_repository._iter_inventories(revision_ids, ordering)
+
def iter_inventories(self, revision_ids, ordering=None):
- self._ensure_real()
- return self._real_repository.iter_inventories(revision_ids, ordering)
+ """Get many inventories by revision_ids.
+
+ This will buffer some or all of the texts used in constructing the
+ inventories in memory, but will only parse a single inventory at a
+ time.
+
+ :param revision_ids: The expected revision ids of the inventories.
+ :param ordering: optional ordering, e.g. 'topological'. If not
+ specified, the order of revision_ids will be preserved (by
+ buffering if necessary).
+ :return: An iterator of inventories.
+ """
+ if ((None in revision_ids)
+ or (_mod_revision.NULL_REVISION in revision_ids)):
+ raise ValueError('cannot get null revision inventory')
+ for inv, revid in self._iter_inventories(revision_ids, ordering):
+ if inv is None:
+ raise errors.NoSuchRevision(self, revid)
+ yield inv
+
+ def _iter_inventories(self, revision_ids, ordering=None):
+ if len(revision_ids) == 0:
+ return
+ missing = set(revision_ids)
+ if ordering is None:
+ order_as_requested = True
+ invs = {}
+ order = list(revision_ids)
+ order.reverse()
+ next_revid = order.pop()
+ else:
+ order_as_requested = False
+ if ordering != 'unordered' and self._fallback_repositories:
+ raise ValueError('unsupported ordering %r' % ordering)
+ iter_inv_fns = [self._iter_inventories_rpc] + [
+ fallback._iter_inventories for fallback in
+ self._fallback_repositories]
+ try:
+ for iter_inv in iter_inv_fns:
+ request = [revid for revid in revision_ids if revid in missing]
+ for inv, revid in iter_inv(request, ordering):
+ if inv is None:
+ continue
+ missing.remove(inv.revision_id)
+ if ordering != 'unordered':
+ invs[revid] = inv
+ else:
+ yield inv, revid
+ if order_as_requested:
+ # Yield as many results as we can while preserving order.
+ while next_revid in invs:
+ inv = invs.pop(next_revid)
+ yield inv, inv.revision_id
+ try:
+ next_revid = order.pop()
+ except IndexError:
+ # We still want to fully consume the stream, just
+ # in case it is not actually finished at this point
+ next_revid = None
+ break
+ except errors.UnknownSmartMethod:
+ for inv, revid in self._iter_inventories_vfs(revision_ids, ordering):
+ yield inv, revid
+ return
+ # Report missing
+ if order_as_requested:
+ if next_revid is not None:
+ yield None, next_revid
+ while order:
+ revid = order.pop()
+ yield invs.get(revid), revid
+ else:
+ while missing:
+ yield None, missing.pop()
@needs_read_lock
def get_revision(self, revision_id):
@@ -2191,6 +2308,8 @@
@needs_read_lock
def _get_inventory_xml(self, revision_id):
+ # This call is used by older working tree formats,
+ # which stored a serialized basis inventory.
self._ensure_real()
return self._real_repository._get_inventory_xml(revision_id)
@@ -2235,11 +2354,58 @@
revids.update(set(fallback.all_revision_ids()))
return list(revids)
+ def _filtered_revision_trees(self, revision_ids, file_ids):
+ """Return Tree for a revision on this branch with only some files.
+
+ :param revision_ids: a sequence of revision-ids;
+ a revision-id may not be None or 'null:'
+ :param file_ids: if not None, the result is filtered
+ so that only those file-ids, their parents and their
+ children are included.
+ """
+ inventories = self.iter_inventories(revision_ids)
+ for inv in inventories:
+ # Should we introduce a FilteredRevisionTree class rather
+ # than pre-filter the inventory here?
+ filtered_inv = inv.filter(file_ids)
+ yield InventoryRevisionTree(self, filtered_inv, filtered_inv.revision_id)
+
@needs_read_lock
def get_deltas_for_revisions(self, revisions, specific_fileids=None):
- self._ensure_real()
- return self._real_repository.get_deltas_for_revisions(revisions,
- specific_fileids=specific_fileids)
+ medium = self._client._medium
+ if medium._is_remote_before((1, 2)):
+ self._ensure_real()
+ for delta in self._real_repository.get_deltas_for_revisions(
+ revisions, specific_fileids):
+ yield delta
+ return
+ # Get the revision-ids of interest
+ required_trees = set()
+ for revision in revisions:
+ required_trees.add(revision.revision_id)
+ required_trees.update(revision.parent_ids[:1])
+
+ # Get the matching filtered trees. Note that it's more
+ # efficient to pass filtered trees to changes_from() rather
+ # than doing the filtering afterwards. changes_from() could
+ # arguably do the filtering itself but it's path-based, not
+ # file-id based, so filtering before or afterwards is
+ # currently easier.
+ if specific_fileids is None:
+ trees = dict((t.get_revision_id(), t) for
+ t in self.revision_trees(required_trees))
+ else:
+ trees = dict((t.get_revision_id(), t) for
+ t in self._filtered_revision_trees(required_trees,
+ specific_fileids))
+
+ # Calculate the deltas
+ for revision in revisions:
+ if not revision.parent_ids:
+ old_tree = self.revision_tree(_mod_revision.NULL_REVISION)
+ else:
+ old_tree = trees[revision.parent_ids[0]]
+ yield trees[revision.revision_id].changes_from(old_tree)
@needs_read_lock
def get_revision_delta(self, revision_id, specific_fileids=None):
=== modified file 'bzrlib/smart/repository.py'
--- a/bzrlib/smart/repository.py 2011-12-11 13:30:10 +0000
+++ b/bzrlib/smart/repository.py 2011-12-13 22:55:10 +0000
@@ -14,7 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-"""Server-side repository related request implmentations."""
+"""Server-side repository related request implementations."""
import bz2
import os
@@ -28,6 +28,8 @@
bencode,
errors,
estimate_compressed_size,
+ inventory as _mod_inventory,
+ inventory_delta,
osutils,
pack,
trace,
@@ -43,6 +45,7 @@
from bzrlib.repository import _strip_NULL_ghosts, network_format_registry
from bzrlib import revision as _mod_revision
from bzrlib.versionedfile import (
+ ChunkedContentFactory,
NetworkRecordStream,
record_to_fulltext_bytes,
)
@@ -1243,3 +1246,57 @@
yield zlib.compress(record.get_bytes_as('fulltext'))
finally:
self._repository.unlock()
+
+
+class SmartServerRepositoryGetInventories(SmartServerRepositoryRequest):
+ """Get the inventory deltas for a set of revision ids.
+
+ This accepts a list of revision ids, and then sends a chain
+ of deltas for the inventories of those revisions. The first
+ revision will be empty.
+
+ The server writes back zlibbed serialized inventory deltas,
+ in the ordering specified. The base for each delta is the
+ inventory generated by the previous delta.
+
+ New in 2.5.
+ """
+
+ def _inventory_delta_stream(self, repository, ordering, revids):
+ prev_inv = _mod_inventory.Inventory(root_id=None,
+ revision_id=_mod_revision.NULL_REVISION)
+ serializer = inventory_delta.InventoryDeltaSerializer(
+ repository.supports_rich_root(),
+ repository._format.supports_tree_reference)
+ repository.lock_read()
+ try:
+ for inv, revid in repository._iter_inventories(revids, ordering):
+ if inv is None:
+ continue
+ inv_delta = inv._make_delta(prev_inv)
+ lines = serializer.delta_to_lines(
+ prev_inv.revision_id, inv.revision_id, inv_delta)
+ yield ChunkedContentFactory(inv.revision_id, None, None, lines)
+ prev_inv = inv
+ finally:
+ repository.unlock()
+
+ def body_stream(self, repository, ordering, revids):
+ substream = self._inventory_delta_stream(repository,
+ ordering, revids)
+ return _stream_to_byte_stream([('inventory-deltas', substream)],
+ repository._format)
+
+ def do_body(self, body_bytes):
+ return SuccessfulSmartServerResponse(('ok', ),
+ body_stream=self.body_stream(self._repository, self._ordering,
+ body_bytes.splitlines()))
+
+ def do_repository_request(self, repository, ordering):
+ if ordering == 'unordered':
+ # inventory deltas for a topologically sorted stream
+ # are likely to be smaller
+ ordering = 'topological'
+ self._ordering = ordering
+ # Signal that we want a body
+ return None
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2011-12-14 12:20:36 +0000
+++ b/bzrlib/smart/request.py 2011-12-14 20:08:26 +0000
@@ -751,15 +751,18 @@
'Repository.check_write_group', 'bzrlib.smart.repository',
'SmartServerRepositoryCheckWriteGroup', info='read')
request_handlers.register_lazy(
- 'VersionedFileRepository.get_serializer_format', 'bzrlib.smart.repository',
- 'SmartServerRepositoryGetSerializerFormat', info='read')
-request_handlers.register_lazy(
'Repository.reconcile', 'bzrlib.smart.repository',
'SmartServerRepositoryReconcile', info='idem')
request_handlers.register_lazy(
'Repository.tarball', 'bzrlib.smart.repository',
'SmartServerRepositoryTarball', info='read')
request_handlers.register_lazy(
+ 'VersionedFileRepository.get_serializer_format', 'bzrlib.smart.repository',
+ 'SmartServerRepositoryGetSerializerFormat', info='read')
+request_handlers.register_lazy(
+ 'VersionedFileRepository.get_inventories', 'bzrlib.smart.repository',
+ 'SmartServerRepositoryGetInventories', info='read')
+request_handlers.register_lazy(
'rmdir', 'bzrlib.smart.vfs', 'RmdirRequest', info='semivfs')
request_handlers.register_lazy(
'stat', 'bzrlib.smart.vfs', 'StatRequest', info='read')
=== modified file 'bzrlib/tests/blackbox/test_annotate.py'
--- a/bzrlib/tests/blackbox/test_annotate.py 2011-12-14 12:15:44 +0000
+++ b/bzrlib/tests/blackbox/test_annotate.py 2011-12-14 20:08:26 +0000
@@ -326,6 +326,6 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(19, self.hpss_calls)
+ self.assertLength(15, self.hpss_calls)
self.expectFailure("annotate accesses inventories, which require VFS access",
self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py 2011-12-14 18:17:43 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py 2011-12-14 20:08:26 +0000
@@ -483,7 +483,7 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(40, self.hpss_calls)
+ self.assertLength(33, self.hpss_calls)
self.expectFailure("branching to the same branch requires VFS access",
self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
@@ -521,8 +521,8 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
self.assertLength(15, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
def test_branch_from_branch_with_tags(self):
self.setup_smart_server_with_call_log()
@@ -539,8 +539,8 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
+ self.assertLength(10, self.hpss_calls)
self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
- self.assertLength(10, self.hpss_calls)
def test_branch_to_stacked_from_trivial_branch_streaming_acceptance(self):
self.setup_smart_server_with_call_log()
=== modified file 'bzrlib/tests/blackbox/test_cat.py'
--- a/bzrlib/tests/blackbox/test_cat.py 2011-12-14 12:15:44 +0000
+++ b/bzrlib/tests/blackbox/test_cat.py 2011-12-14 20:08:26 +0000
@@ -239,6 +239,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(16, self.hpss_calls)
- self.expectFailure("cat still uses VFS calls",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(9, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_checkout.py'
--- a/bzrlib/tests/blackbox/test_checkout.py 2011-12-14 18:17:43 +0000
+++ b/bzrlib/tests/blackbox/test_checkout.py 2011-12-14 20:08:26 +0000
@@ -179,8 +179,7 @@
for count in range(9):
t.commit(message='commit %d' % count)
self.reset_smart_call_log()
- out, err = self.run_bzr(['checkout', self.get_url('from'),
- 'target'])
+ out, err = self.run_bzr(['checkout', self.get_url('from'), 'target'])
# This figure represent the amount of work to perform this use case. It
# is entirely ok to reduce this number if a test fails due to rpc_count
# being too low. If rpc_count increases, more network roundtrips have
@@ -202,9 +201,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- if len(self.hpss_calls) < 28 or len(self.hpss_calls) > 40:
- self.fail(
- "Incorrect length: wanted between 28 and 40, got %d for %r" % (
- len(self.hpss_calls), self.hpss_calls))
- self.expectFailure("lightweight checkouts require VFS calls",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(15, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_export.py'
--- a/bzrlib/tests/blackbox/test_export.py 2011-12-14 12:15:44 +0000
+++ b/bzrlib/tests/blackbox/test_export.py 2011-12-14 20:08:26 +0000
@@ -448,6 +448,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(16, self.hpss_calls)
- self.expectFailure("export requires inventory access which requires VFS",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(7, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_log.py'
--- a/bzrlib/tests/blackbox/test_log.py 2011-12-14 12:15:44 +0000
+++ b/bzrlib/tests/blackbox/test_log.py 2011-12-14 20:08:26 +0000
@@ -1086,9 +1086,8 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(19, self.hpss_calls)
- self.expectFailure("verbose log accesses inventories, which require VFS",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(11, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
def test_per_file(self):
self.setup_smart_server_with_call_log()
@@ -1103,6 +1102,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(21, self.hpss_calls)
- self.expectFailure("per-file graph access requires VFS",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(15, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_ls.py'
--- a/bzrlib/tests/blackbox/test_ls.py 2011-12-14 12:15:44 +0000
+++ b/bzrlib/tests/blackbox/test_ls.py 2011-12-14 20:08:26 +0000
@@ -262,6 +262,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(15, self.hpss_calls)
- self.expectFailure("inventories can only be accessed over VFS",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(6, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/blackbox/test_sign_my_commits.py'
--- a/bzrlib/tests/blackbox/test_sign_my_commits.py 2011-12-14 18:17:43 +0000
+++ b/bzrlib/tests/blackbox/test_sign_my_commits.py 2011-12-14 20:08:26 +0000
@@ -165,9 +165,8 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
- self.assertLength(51, self.hpss_calls)
- self.expectFailure("signing commits requires VFS access",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(15, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
def test_verify_commits(self):
self.setup_smart_server_with_call_log()
@@ -185,12 +184,5 @@
# being too low. If rpc_count increases, more network roundtrips have
# become necessary for this use case. Please do not adjust this number
# upwards without agreement from bzr's network support maintainers.
-
- # The number of readv requests seems to vary depending on the generated
- # repository and how well it compresses, so allow for a bit of
- # variation:
- if len(self.hpss_calls) not in (18, 19):
- self.fail("Incorrect length: wanted 18 or 19, got %d for %r" % (
- len(self.hpss_calls), self.hpss_calls))
- self.expectFailure("verifying commits requires VFS access",
- self.assertThat, self.hpss_calls, ContainsNoVfsCalls)
+ self.assertLength(10, self.hpss_calls)
+ self.assertThat(self.hpss_calls, ContainsNoVfsCalls)
=== modified file 'bzrlib/tests/per_interbranch/test_push.py'
--- a/bzrlib/tests/per_interbranch/test_push.py 2011-10-15 01:09:01 +0000
+++ b/bzrlib/tests/per_interbranch/test_push.py 2011-12-11 15:42:02 +0000
@@ -279,10 +279,10 @@
# remote graph any further.
bzr_core_trace = Equals(
['Repository.insert_stream_1.19', 'Repository.insert_stream_1.19',
- 'get', 'Branch.set_last_revision_info', 'Branch.unlock'])
+ 'Branch.set_last_revision_info', 'Branch.unlock'])
bzr_loom_trace = Equals(
['Repository.insert_stream_1.19', 'Repository.insert_stream_1.19',
- 'get', 'Branch.set_last_revision_info', 'get', 'Branch.unlock'])
+ 'Branch.set_last_revision_info', 'get', 'Branch.unlock'])
self.assertThat(calls_after_insert_stream,
MatchesAny(bzr_core_trace, bzr_loom_trace))
=== modified file 'bzrlib/tests/per_repository_chk/test_supported.py'
--- a/bzrlib/tests/per_repository_chk/test_supported.py 2009-09-09 18:52:56 +0000
+++ b/bzrlib/tests/per_repository_chk/test_supported.py 2011-12-13 22:41:31 +0000
@@ -22,7 +22,9 @@
osutils,
repository,
)
+from bzrlib.remote import RemoteRepository
from bzrlib.versionedfile import VersionedFiles
+from bzrlib.tests import TestNotApplicable
from bzrlib.tests.per_repository_chk import TestCaseWithRepositoryCHK
@@ -221,7 +223,9 @@
# check our setup: B-id and C-id should have identical chk root keys.
inv_b = b.repository.get_inventory('B-id')
inv_c = b.repository.get_inventory('C-id')
- self.assertEqual(inv_b.id_to_entry.key(), inv_c.id_to_entry.key())
+ if not isinstance(repo, RemoteRepository):
+ # Remote repositories always return plain inventories
+ self.assertEqual(inv_b.id_to_entry.key(), inv_c.id_to_entry.key())
# Now, manually insert objects for a stacked repo with only revision
# C-id:
# We need ('revisions', 'C-id'), ('inventories', 'C-id'),
@@ -250,6 +254,9 @@
for a parent inventory of a new revision is missing.
"""
repo = self.make_repository('damaged-repo')
+ if isinstance(repo, RemoteRepository):
+ raise TestNotApplicable(
+ "Unable to obtain CHKInventory from remote repo")
b = self.make_branch_with_multiple_chk_nodes()
src_repo = b.repository
src_repo.lock_read()
@@ -293,6 +300,9 @@
for a parent inventory of a new revision is missing.
"""
repo = self.make_repository('damaged-repo')
+ if isinstance(repo, RemoteRepository):
+ raise TestNotApplicable(
+ "Unable to obtain CHKInventory from remote repo")
b = self.make_branch_with_multiple_chk_nodes()
b.lock_read()
self.addCleanup(b.unlock)
=== modified file 'bzrlib/tests/per_repository_vf/test_add_inventory_by_delta.py'
--- a/bzrlib/tests/per_repository_vf/test_add_inventory_by_delta.py 2011-05-02 22:39:15 +0000
+++ b/bzrlib/tests/per_repository_vf/test_add_inventory_by_delta.py 2011-12-13 22:41:31 +0000
@@ -109,4 +109,4 @@
else:
repo_delta.commit_write_group()
self.assertEqual(add_validator, delta_validator)
- self.assertEqual(new_inv, inv)
+ self.assertEqual(list(new_inv.iter_entries()), list(inv.iter_entries()))
=== modified file 'bzrlib/tests/test_remote.py'
--- a/bzrlib/tests/test_remote.py 2011-12-14 12:20:36 +0000
+++ b/bzrlib/tests/test_remote.py 2011-12-14 21:24:07 +0000
@@ -69,6 +69,7 @@
from bzrlib.smart.repository import (
SmartServerRepositoryGetParentMap,
SmartServerRepositoryGetStream_1_19,
+ _stream_to_byte_stream,
)
from bzrlib.symbol_versioning import deprecated_in
from bzrlib.tests import (
@@ -4233,3 +4234,43 @@
'Repository.unlock', ('quack/', 'token', 'False'),
'success', ('ok', ))
repo.pack(['hinta', 'hintb'])
+
+
+class TestRepositoryIterInventories(TestRemoteRepository):
+ """Test Repository.iter_inventories."""
+
+ def _serialize_inv_delta(self, old_name, new_name, delta):
+ serializer = inventory_delta.InventoryDeltaSerializer(True, False)
+ return "".join(serializer.delta_to_lines(old_name, new_name, delta))
+
+ def test_single_empty(self):
+ transport_path = 'quack'
+ repo, client = self.setup_fake_client_and_repository(transport_path)
+ fmt = bzrdir.format_registry.get('2a')().repository_format
+ repo._format = fmt
+ stream = [('inventory-deltas', [
+ versionedfile.FulltextContentFactory('somerevid', None, None,
+ self._serialize_inv_delta('null:', 'somerevid', []))])]
+ client.add_expected_call(
+ 'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
+ 'success', ('ok', ),
+ _stream_to_byte_stream(stream, fmt))
+ ret = list(repo.iter_inventories(["somerevid"]))
+ self.assertLength(1, ret)
+ inv = ret[0]
+ self.assertEquals("somerevid", inv.revision_id)
+
+ def test_empty(self):
+ transport_path = 'quack'
+ repo, client = self.setup_fake_client_and_repository(transport_path)
+ ret = list(repo.iter_inventories([]))
+ self.assertEquals(ret, [])
+
+ def test_missing(self):
+ transport_path = 'quack'
+ repo, client = self.setup_fake_client_and_repository(transport_path)
+ client.add_expected_call(
+ 'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
+ 'success', ('ok', ), iter([]))
+ self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
+ ["somerevid"]))
=== modified file 'bzrlib/tests/test_smart.py'
--- a/bzrlib/tests/test_smart.py 2011-12-14 12:20:36 +0000
+++ b/bzrlib/tests/test_smart.py 2011-12-14 21:24:07 +0000
@@ -32,6 +32,7 @@
bzrdir,
errors,
gpg,
+ inventory_delta,
tests,
transport,
urlutils,
@@ -2565,6 +2566,8 @@
smart_repo.SmartServerRepositoryAbortWriteGroup)
self.assertHandlerEqual('VersionedFileRepository.get_serializer_format',
smart_repo.SmartServerRepositoryGetSerializerFormat)
+ self.assertHandlerEqual('VersionedFileRepository.get_inventories',
+ smart_repo.SmartServerRepositoryGetInventories)
self.assertHandlerEqual('Transport.is_readonly',
smart_req.SmartServerIsReadonly)
@@ -2630,3 +2633,48 @@
smart_req.SuccessfulSmartServerResponse(('ok', ), ),
request.do_body(''))
+
+class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
+
+ def _get_serialized_inventory_delta(self, repository, base_revid, revid):
+ base_inv = repository.revision_tree(base_revid).inventory
+ inv = repository.revision_tree(revid).inventory
+ inv_delta = inv._make_delta(base_inv)
+ serializer = inventory_delta.InventoryDeltaSerializer(True, False)
+ return "".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
+
+ def test_single(self):
+ backing = self.get_transport()
+ request = smart_repo.SmartServerRepositoryGetInventories(backing)
+ t = self.make_branch_and_tree('.', format='2a')
+ self.addCleanup(t.lock_write().unlock)
+ self.build_tree_contents([("file", "somecontents")])
+ t.add(["file"], ["thefileid"])
+ t.commit(rev_id='somerev', message="add file")
+ self.assertIs(None, request.execute('', 'unordered'))
+ response = request.do_body("somerev\n")
+ self.assertTrue(response.is_successful())
+ self.assertEquals(response.args, ("ok", ))
+ stream = [('inventory-deltas', [
+ versionedfile.FulltextContentFactory('somerev', None, None,
+ self._get_serialized_inventory_delta(
+ t.branch.repository, 'null:', 'somerev'))])]
+ fmt = bzrdir.format_registry.get('2a')().repository_format
+ self.assertEquals(
+ "".join(response.body_stream),
+ "".join(smart_repo._stream_to_byte_stream(stream, fmt)))
+
+ def test_empty(self):
+ backing = self.get_transport()
+ request = smart_repo.SmartServerRepositoryGetInventories(backing)
+ t = self.make_branch_and_tree('.', format='2a')
+ self.addCleanup(t.lock_write().unlock)
+ self.build_tree_contents([("file", "somecontents")])
+ t.add(["file"], ["thefileid"])
+ t.commit(rev_id='somerev', message="add file")
+ self.assertIs(None, request.execute('', 'unordered'))
+ response = request.do_body("")
+ self.assertTrue(response.is_successful())
+ self.assertEquals(response.args, ("ok", ))
+ self.assertEquals("".join(response.body_stream),
+ "Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt 2011-12-14 20:39:58 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt 2011-12-14 21:50:54 +0000
@@ -95,6 +95,10 @@
* New HPSS call ``BzrDir.checkout_metadir``. (Jelmer Vernooij, #894459)
+* New HPSS call ``VersionedFileRepository.get_inventories``,
+ speeding up various commands including ``bzr export``,
+ ``bzr checkout`` and ``bzr cat``. (Jelmer Vernooij, #608640)
+
Testing
*******
@@ -156,6 +160,9 @@
* Plugins can now register additional "location aliases".
(Jelmer Vernooij)
+* ``bzr status`` no longer shows shelves if files are specified.
+ (Francis Devereux)
+
* Revision specifiers will now only browse as much history as they
need to, rather than grabbing the whole history unnecessarily in some
cases. (Jelmer Vernooij)
@@ -281,8 +288,14 @@
``Repository.get_revision_signature_text``.
(Jelmer Vernooij)
+* Add HPSS call for ``Branch.get_checkout_format``. (Jelmer Vernooij, #894459)
+
* Add HPSS call for ``Repository.pack``. (Jelmer Vernooij, #894461)
+* Add HPSS calls for ``Repository.iter_files_bytes``, speeding up
+ several commands including ``bzr export`` and ``bzr co --lightweight``.
+ (Jelmer Vernooij, #608640)
+
* Custom HPSS error handlers can now be installed in the smart server client
using the ``error_translators`` and ``no_context_error_translators``
registries. (Jelmer Vernooij)
More information about the bazaar-commits
mailing list