Rev 4038: Add helper class versionedfile.VersionedFilesDecorator for use with RemoteRepository in future. in http://people.ubuntu.com/~robertc/baz2.0/versioned_files.decorator
Robert Collins
robertc at robertcollins.net
Tue Feb 24 10:57:53 GMT 2009
At http://people.ubuntu.com/~robertc/baz2.0/versioned_files.decorator
------------------------------------------------------------
revno: 4038
revision-id: robertc at robertcollins.net-20090224105745-84xd70xemb7h3jnx
parent: pqm at pqm.ubuntu.com-20090224073648-8cdhj9m2zsab8hx8
committer: Robert Collins <robertc at robertcollins.net>
branch nick: versioned_files.decorator
timestamp: Tue 2009-02-24 21:57:45 +1100
message:
Add helper class versionedfile.VersionedFilesDecorator for use with RemoteRepository in future.
=== modified file 'NEWS'
--- a/NEWS 2009-02-24 07:36:48 +0000
+++ b/NEWS 2009-02-24 10:57:45 +0000
@@ -95,6 +95,10 @@
* Creating a repository on a bzr+ssh:// server will now make a single
call rather than many VFS calls. (Robert Collins)
+ * New helper class ``versionedfile.VersionedFilesDecorator`` provides
+ a generic way to decorate a ``VersionedFiles`` instance.
+ (Robert Collins)
+
* New hook Commands['extend_command'] to allow plugins to access a
command object before the command is run (or help generated from
it), without overriding the command. (Robert Collins)
=== modified file 'bzrlib/tests/test_versionedfile.py'
--- a/bzrlib/tests/test_versionedfile.py 2009-02-23 15:42:47 +0000
+++ b/bzrlib/tests/test_versionedfile.py 2009-02-24 10:57:45 +0000
@@ -65,7 +65,10 @@
ConstantMapper,
HashEscapedPrefixMapper,
PrefixMapper,
+ VersionedFilesDecorator,
VirtualVersionedFiles,
+ make_decorator_cleanup,
+ make_decorator_factory,
make_versioned_files_factory,
)
from bzrlib.weave import WeaveFile
@@ -149,6 +152,13 @@
'key_length':2,
'support_partial_insertion': True,
}),
+ ('decorated', {
+ 'cleanup':make_decorator_cleanup(cleanup_pack_knit),
+ 'factory':make_decorator_factory(make_pack_factory(True, True, 2)),
+ 'graph':True,
+ 'key_length':2,
+ 'support_partial_insertion': True,
+ })
]
for test in iter_suite_tests(to_adapt):
result.addTests(len_one_adapter.adapt(test))
@@ -2511,3 +2521,16 @@
# And the request recorded
self.assertEqual([('get_record_stream', request_keys, 'unordered',
False)], vf.calls)
+
+
+class TestVersionedFilesDecorator(TestCaseWithMemoryTransport):
+ """Specific behaviour tests for VersionedFilesDecorator."""
+
+ def test_factory_works(self):
+ """The test helper make_decorator_factory returns a working object."""
+ transport = self.get_transport('.')
+ factory = make_decorator_factory(make_pack_factory(False, False, 1))
+ files = factory(transport)
+ self.assertIsInstance(files, VersionedFilesDecorator)
+ cleanup = make_decorator_cleanup(cleanup_pack_knit)
+ cleanup(files)
=== modified file 'bzrlib/versionedfile.py'
--- a/bzrlib/versionedfile.py 2009-02-23 15:29:35 +0000
+++ b/bzrlib/versionedfile.py 2009-02-24 10:57:45 +0000
@@ -552,14 +552,85 @@
return PlanWeaveMerge(plan, a_marker, b_marker).merge_lines()[0]
-class RecordingVersionedFilesDecorator(object):
+class VersionedFilesDecorator(object):
+ """A VersionedFiles that decorates a backing versioned files."""
+
+ def __init__(self, hook_call):
+ """Create a VersionedFilesDecorator.
+
+ :param hook_call: A callback invoked on every method call to the
+ decorator. This call should ensure that the _backing_vf attribute
+ is correctly populated and may do any other housekeeping needed.
+ After the call is made, the invoked method is dispatched through
+ the _backing_vf and the result returned to the caller.
+ hook_call should take (self, method_name, *args) and return None.
+ """
+ self._hook_call = hook_call
+ self._backing_vf = None
+
+ def add_lines(self, key, parents, lines, parent_texts=None,
+ left_matching_blocks=None, nostore_sha=None, random_id=False,
+ check_content=True):
+ self._hook_call(self, "add_lines", key, parents, lines, parent_texts,
+ left_matching_blocks, nostore_sha, random_id, check_content)
+ return self._backing_vf.add_lines(key, parents, lines, parent_texts,
+ left_matching_blocks, nostore_sha, random_id, check_content)
+
+ def add_mpdiffs(self, records):
+ self._hook_call(self, "add_mpdiffs", records)
+ return self._backing_vf.add_mpdiffs(records)
+
+ def annotate(self, key):
+ self._hook_call(self, "annotate", key)
+ return self._backing_vf.annotate(key)
+
+ def check(self):
+ self._hook_call(self, "check")
+ return self._backing_vf.check()
+
+ def get_missing_compression_parent_keys(self):
+ self._hook_call(self, "get_missing_compression_parent_keys")
+ return self._backing_vf.get_missing_compression_parent_keys()
+
+ def get_parent_map(self, keys):
+ self._hook_call(self, "get_parent_map", keys)
+ return self._backing_vf.get_parent_map(keys)
+
+ def get_record_stream(self, keys, sort_order, include_delta_closure):
+ self._hook_call(self, "get_record_stream", keys, sort_order,
+ include_delta_closure)
+ return self._backing_vf.get_record_stream(keys, sort_order,
+ include_delta_closure)
+
+ def get_sha1s(self, keys):
+ self._hook_call(self, "get_sha1s", keys)
+ return self._backing_vf.get_sha1s(keys)
+
+ def insert_record_stream(self, stream):
+ self._hook_call(self, "insert_record_stream", stream)
+ return self._backing_vf.insert_record_stream(stream)
+
+ def iter_lines_added_or_present_in_keys(self, keys, pb=None):
+ self._hook_call(self, "iter_lines_added_or_present_in_keys", keys, pb)
+ return self._backing_vf.iter_lines_added_or_present_in_keys(keys, pb=pb)
+
+ def keys(self):
+ self._hook_call(self, "keys")
+ return self._backing_vf.keys()
+
+ def make_mpdiffs(self, keys):
+ self._hook_call(self, "make_mpdiffs", keys)
+ return self._backing_vf.make_mpdiffs(keys)
+
+
+class RecordingVersionedFilesDecorator(VersionedFilesDecorator):
"""A minimal versioned files that records calls made on it.
- Only enough methods have been added to support tests using it to date.
-
:ivar calls: A list of the calls made; can be reset at any time by
assigning [] to it.
"""
+ # Note that some methods are overridden to ensure that iterable parameters
+ # are not consumed in _hook_call.
def __init__(self, backing_vf):
"""Create a RecordingVersionedFilesDecorator decorating backing_vf.
@@ -569,16 +640,8 @@
self._backing_vf = backing_vf
self.calls = []
- def add_lines(self, key, parents, lines, parent_texts=None,
- left_matching_blocks=None, nostore_sha=None, random_id=False,
- check_content=True):
- self.calls.append(("add_lines", key, parents, lines, parent_texts,
- left_matching_blocks, nostore_sha, random_id, check_content))
- return self._backing_vf.add_lines(key, parents, lines, parent_texts,
- left_matching_blocks, nostore_sha, random_id, check_content)
-
- def check(self):
- self._backing_vf.check()
+ def _hook_call(_self, self, method_name, *args):
+ self.calls.append((method_name,) + args)
def get_parent_map(self, keys):
self.calls.append(("get_parent_map", copy(keys)))
@@ -598,10 +661,6 @@
self.calls.append(("iter_lines_added_or_present_in_keys", copy(keys)))
return self._backing_vf.iter_lines_added_or_present_in_keys(keys, pb=pb)
- def keys(self):
- self.calls.append(("keys",))
- return self._backing_vf.keys()
-
class OrderingVersionedFilesDecorator(RecordingVersionedFilesDecorator):
"""A VF that records calls, and returns keys in specific order.
@@ -757,6 +816,34 @@
return urllib.unquote(basename)
+def make_decorator_cleanup(versioned_files_cleanup):
+ """Create a VersionedFilesDecorator cleanup helper.
+
+ :param versioned_files_cleanup: The cleanup to call
+ to cleanup the backing vf for a VersionedFilesDecorator.
+ """
+ def cleanup(files):
+ if files._backing_vf is not None:
+ versioned_files_cleanup(files._backing_vf)
+ return cleanup
+
+
+def make_decorator_factory(versioned_files_factory):
+ """Create VersionedFilesDecorator factory.
+
+ The factory will return a callable which when called returns a
+ VersionedFilesDecorator. The decorator is configured to invoke the
+ original versioned_files_factory when a backing_vf is required.
+ """
+ def factory(transport):
+ def _ensure_backing_vf(self, method_name, *args):
+ """Ensure there is a backing vf set."""
+ if self._backing_vf is None:
+ self._backing_vf = versioned_files_factory(transport)
+ return VersionedFilesDecorator(_ensure_backing_vf)
+ return factory
+
+
def make_versioned_files_factory(versioned_file_factory, mapper):
"""Create a ThunkedVersionedFiles factory.
More information about the bazaar-commits
mailing list