Rev 3364: Deprecate VersionedFile.join. in http://people.ubuntu.com/~robertc/baz2.0/versioned_files

Robert Collins robertc at robertcollins.net
Tue Apr 29 06:27:13 BST 2008


At http://people.ubuntu.com/~robertc/baz2.0/versioned_files

------------------------------------------------------------
revno: 3364
revision-id: robertc at robertcollins.net-20080429052708-ep87a2mxn2d7i8lr
parent: robertc at robertcollins.net-20080429001045-a2zfomf1iy12eu3k
committer: Robert Collins <robertc at robertcollins.net>
branch nick: data_stream_revamp
timestamp: Tue 2008-04-29 15:27:08 +1000
message:
  Deprecate VersionedFile.join.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/symbol_versioning.py    symbol_versioning.py-20060105104851-9ecf8af605d15a80
  bzrlib/tests/interversionedfile_implementations/test_join.py test_join.py-20060302012326-9b5e9b0f0a03fedc
  bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
  bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
  bzrlib/tests/test_weave.py     testknit.py-20050627023648-9833cc5562ffb785
  bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
=== modified file 'NEWS'
--- a/NEWS	2008-04-28 05:54:46 +0000
+++ b/NEWS	2008-04-29 05:27:08 +0000
@@ -66,6 +66,12 @@
       Repository.item_keys_introduced_by() no longer take read locks.
       (Aaron Bentley)
 
+    * ``VersionedFile.join`` is deprecated. This method required local
+      instances of both versioned file objects and was thus hostile to being
+      used for streaming from a smart server. The new get_record_stream and
+      insert_record_stream are meant to efficiently replace this method.
+      (Robert Collins)
+
 
 bzr 1.4rc2 2008-04-21
 ---------------------

=== modified file 'bzrlib/symbol_versioning.py'
--- a/bzrlib/symbol_versioning.py	2008-03-20 00:43:25 +0000
+++ b/bzrlib/symbol_versioning.py	2008-04-29 05:27:08 +0000
@@ -46,6 +46,7 @@
            'one_two',
            'one_three',
            'one_four',
+           'one_five',
            ]
 
 from warnings import warn
@@ -73,6 +74,7 @@
 one_two = "%s was deprecated in version 1.2."
 one_three = "%s was deprecated in version 1.3."
 one_four = "%s was deprecated in version 1.4."
+one_five = "%s was deprecated in version 1.5."
 
 def set_warning_method(method):
     """Set the warning method to be used by this module.

=== modified file 'bzrlib/tests/interversionedfile_implementations/test_join.py'
--- a/bzrlib/tests/interversionedfile_implementations/test_join.py	2008-03-27 04:54:12 +0000
+++ b/bzrlib/tests/interversionedfile_implementations/test_join.py	2008-04-29 05:27:08 +0000
@@ -18,6 +18,7 @@
 
 
 import bzrlib.errors as errors
+from bzrlib.symbol_versioning import one_five
 from bzrlib.tests import TestCaseWithTransport
 from bzrlib.transport import get_transport
 import bzrlib.versionedfile as versionedfile
@@ -44,7 +45,7 @@
         f1.add_lines('r0', [], ['a\n', 'b\n'])
         f1.add_lines('r1', ['r0'], ['c\n', 'b\n'])
         f2 = self.get_target()
-        f2.join(f1, None)
+        self.applyDeprecated(one_five, f2.join, f1, None)
         def verify_file(f):
             self.assertTrue(f.has_version('r0'))
             self.assertTrue(f.has_version('r1'))
@@ -52,7 +53,7 @@
         verify_file(self.get_target())
 
         self.assertRaises(errors.RevisionNotPresent,
-            f2.join, f1, version_ids=['r3'])
+            self.applyDeprecated, one_five, f2.join, f1, version_ids=['r3'])
 
     def test_gets_expected_inter_worker(self):
         source = self.get_source()
@@ -72,7 +73,8 @@
         source.add_lines('ancestorright', ['base'], [])
         source.add_lines('namedleft', ['ancestorleft'], [])
         source.add_lines('namedright', ['ancestorright'], [])
-        target.join(source, version_ids=['namedleft', 'namedright'])
+        self.applyDeprecated(one_five, target.join, source,
+            version_ids=['namedleft', 'namedright'])
         self.assertFalse(target.has_version('sibling'))
         self.assertTrue(target.has_version('ancestorleft'))
         self.assertTrue(target.has_version('ancestorright'))
@@ -88,7 +90,7 @@
         w1.add_lines('v-3', ['v-1'], ['line 1\n'])
         w2.add_lines('v-3', ['v-2'], ['line 1\n'])
         try:
-            w1.join(w2)
+            self.applyDeprecated(one_five, w1.join, w2)
         except errors.WeaveParentMismatch:
             # Acceptable behaviour:
             return
@@ -115,7 +117,7 @@
         """Reweave adding empty weave"""
         wb = self.get_target()
         w1 = self.build_weave1()
-        w1.join(wb)
+        self.applyDeprecated(one_five, w1.join, wb)
         self.verify_weave1(w1)
 
     def verify_weave1(self, w1):
@@ -136,7 +138,7 @@
         t = self.get_target()
         t.add_lines('base', [], [])
         t.add_lines('text', ['base'], [])
-        t.join(s)
+        self.applyDeprecated(one_five, t.join, s)
         self.assertEqual({'text':('base',)}, t.get_parent_map(['text']))
 
     def test_join_with_ghosts(self):
@@ -159,7 +161,7 @@
         wb.add_lines('v1', [], ['hello\n'])
         wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
         try:
-            w1.join(wb)
+            self.applyDeprecated(one_five, w1.join, wb)
         except errors.WeaveParentMismatch:
             # Acceptable behaviour:
             return
@@ -176,7 +178,8 @@
         wb.add_lines('x1', [], ['line from x1\n'])
         wb.add_lines('v1', [], ['hello\n'])
         wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
-        w1.join(wb, version_ids=['x1', 'z1'], ignore_missing=True)
+        self.applyDeprecated(one_five, w1.join, wb, version_ids=['x1', 'z1'],
+            ignore_missing=True)
         eq = self.assertEquals
         eq(sorted(w1.versions()), ['v1', 'v2', 'v3', 'x1'])
         eq(w1.get_text('x1'), 'line from x1\n')
@@ -213,7 +216,7 @@
             # The target does not support ghosts; the test is irrelevant.
             return
         try:
-            source.join(target)
+            self.applyDeprecated(one_five, source.join, target)
         except errors.RevisionNotPresent:
             return
         # legacy apis should behave
@@ -228,7 +231,7 @@
         # if we add something that is fills out what is a ghost, then 
         # when joining into a ghost aware join it should flesh out the ghosts.
         source.add_lines('base', [], [])
-        target.join(source, version_ids=['base'])
+        self.applyDeprecated(one_five, target.join, source, version_ids=['base'])
         self.assertEqual(['base', 'notbase'], target.get_ancestry(['notbase']))
         self.assertEqual({'base':(),
                           'notbase':('base', ),
@@ -251,7 +254,7 @@
         source.add_lines('inherit_me', [], ['b\n'])
         source.add_lines('select_me', ['inherit_me'], ['b\n'])
         target = self.get_target()
-        target.join(source, version_ids=['select_me'])
+        self.applyDeprecated(one_five, target.join, source, version_ids=['select_me'])
         self.assertEqual(['inherit_me', 'select_me'], target.versions())
 
     def test_join_odd_records(self):
@@ -267,7 +270,7 @@
         source.add_lines('4', ['2'], ['1st\n'])
         source.add_lines('5', ['3'], ['1st\n', '2nd\n', '3rd\n'])
         target = self.get_target()
-        target.join(source, version_ids=['1', '3', '5'])
+        self.applyDeprecated(one_five, target.join, source, version_ids=['1', '3', '5'])
         target = self.get_target(create=False)
         self.assertEqual(set(['1', '3', '5']), set(target.versions()))
         self.assertEqual(3, len(target.versions()))

=== modified file 'bzrlib/tests/test_knit.py'
--- a/bzrlib/tests/test_knit.py	2008-04-29 00:10:45 +0000
+++ b/bzrlib/tests/test_knit.py	2008-04-29 05:27:08 +0000
@@ -1293,39 +1293,6 @@
         self.assertEquals(origins[1], ('text-1', 'b\n'))
         self.assertEquals(origins[2], ('text-1', 'c\n'))
 
-    def _test_join_with_factories(self, k1_factory, k2_factory):
-        k1 = make_file_knit('test1', get_transport('.'), factory=k1_factory, create=True)
-        k1.add_lines('text-a', [], ['a1\n', 'a2\n', 'a3\n'])
-        k1.add_lines('text-b', ['text-a'], ['a1\n', 'b2\n', 'a3\n'])
-        k1.add_lines('text-c', [], ['c1\n', 'c2\n', 'c3\n'])
-        k1.add_lines('text-d', ['text-c'], ['c1\n', 'd2\n', 'd3\n'])
-        k1.add_lines('text-m', ['text-b', 'text-d'], ['a1\n', 'b2\n', 'd3\n'])
-        k2 = make_file_knit('test2', get_transport('.'), factory=k2_factory, create=True)
-        count = k2.join(k1, version_ids=['text-m'])
-        self.assertEquals(count, 5)
-        self.assertTrue(k2.has_version('text-a'))
-        self.assertTrue(k2.has_version('text-c'))
-        origins = k2.annotate('text-m')
-        self.assertEquals(origins[0], ('text-a', 'a1\n'))
-        self.assertEquals(origins[1], ('text-b', 'b2\n'))
-        self.assertEquals(origins[2], ('text-d', 'd3\n'))
-
-    def test_knit_join_plain_to_plain(self):
-        """Test joining a plain knit with a plain knit."""
-        self._test_join_with_factories(KnitPlainFactory(), KnitPlainFactory())
-
-    def test_knit_join_anno_to_anno(self):
-        """Test joining an annotated knit with an annotated knit."""
-        self._test_join_with_factories(None, None)
-
-    def test_knit_join_anno_to_plain(self):
-        """Test joining an annotated knit with a plain knit."""
-        self._test_join_with_factories(None, KnitPlainFactory())
-
-    def test_knit_join_plain_to_anno(self):
-        """Test joining a plain knit with an annotated knit."""
-        self._test_join_with_factories(KnitPlainFactory(), None)
-
     def test_reannotate(self):
         k1 = make_file_knit('knit1', get_transport('.'),
                                factory=KnitAnnotateFactory(), create=True)
@@ -1336,7 +1303,8 @@
 
         k2 = make_file_knit('test2', get_transport('.'),
                                factory=KnitAnnotateFactory(), create=True)
-        k2.join(k1, version_ids=['text-b'])
+        k2.insert_record_stream(k1.get_record_stream(k1.versions(),
+            'unordered', False))
 
         # 2
         k1.add_lines('text-X', ['text-b'], ['a\n', 'b\n'])
@@ -1346,7 +1314,8 @@
         k2.add_lines('text-Y', ['text-b'], ['b\n', 'c\n'])
 
         # test-c will have index 3
-        k1.join(k2, version_ids=['text-c'])
+        k1.insert_record_stream(k2.get_record_stream(['text-c'],
+            'unordered', False))
 
         lines = k1.get_lines('text-c')
         self.assertEquals(lines, ['z\n', 'c\n'])
@@ -2817,7 +2786,8 @@
         target_knit = self.make_test_knit(name='annotated', annotate=True)
         source_knit.add_lines("A", [], ["Foo\n"])
         # Give the target A, so we can try to thunk across to it.
-        target_knit.join(source_knit)
+        target_knit.insert_record_stream(source_knit.get_record_stream(['A'],
+            'unordered', False))
         index, access = self.get_index_access(target_knit,
             source_knit.get_data_stream([]))
         raw_data = list(access.get_raw_records([(True, "A", None, None)]))[0]

=== modified file 'bzrlib/tests/test_versionedfile.py'
--- a/bzrlib/tests/test_versionedfile.py	2008-04-24 07:28:18 +0000
+++ b/bzrlib/tests/test_versionedfile.py	2008-04-29 05:27:08 +0000
@@ -40,7 +40,7 @@
     KnitAnnotateFactory,
     KnitPlainFactory,
     )
-from bzrlib.symbol_versioning import one_four
+from bzrlib.symbol_versioning import one_four, one_five
 from bzrlib.tests import TestCaseWithMemoryTransport, TestSkipped
 from bzrlib.tests.http_utils import TestCaseWithWebserver
 from bzrlib.trace import mutter
@@ -226,6 +226,16 @@
             set([('base',), ('left',), ('right',), ('merged',), ('or',)]),
             seen)
 
+    def test_filter_absent_records(self):
+        """Requested missing records can be filter trivially."""
+        f, parents = get_diamond_vf(self.get_file())
+        entries = f.get_record_stream(['merged', 'left', 'right', 'extra', 'base'],
+            'unordered', False)
+        seen = set()
+        self.capture_stream(f, versionedfile.filter_absent(entries), seen.add,
+            parents)
+        self.assertEqual(set([('base',), ('left',), ('right',), ('merged',)]),
+            seen)
 
     def test_insert_record_stream_empty(self):
         """Inserting an empty record stream should work."""
@@ -591,7 +601,8 @@
         self._transaction = 'after'
         self.assertRaises(errors.OutSideTransaction, f.add_lines, '', [], [])
         self.assertRaises(errors.OutSideTransaction, f.add_lines_with_ghosts, '', [], [])
-        self.assertRaises(errors.OutSideTransaction, f.join, '')
+        self.assertRaises(errors.OutSideTransaction, self.applyDeprecated,
+            one_five, f.join, '')
         
     def test_clone_text(self):
         f = self.get_file()
@@ -926,7 +937,8 @@
                           'base',
                           [],
                           [])
-        self.assertRaises(errors.ReadOnlyError, vf.join, 'base')
+        self.assertRaises(errors.ReadOnlyError, self.applyDeprecated, one_five,
+            vf.join, 'base')
     
     def test_get_sha1s(self):
         # check the sha1 data is available

=== modified file 'bzrlib/tests/test_weave.py'
--- a/bzrlib/tests/test_weave.py	2008-04-08 03:39:43 +0000
+++ b/bzrlib/tests/test_weave.py	2008-04-29 05:27:08 +0000
@@ -657,66 +657,6 @@
         self.weave1.add_lines('v1', [], self.lines1)
         self.weave1.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
         self.weave1.add_lines('v3', ['v2'], self.lines3)
-        
-    def test_join_empty(self):
-        """Join two empty weaves."""
-        eq = self.assertEqual
-        w1 = Weave()
-        w2 = Weave()
-        w1.join(w2)
-        eq(len(w1), 0)
-        
-    def test_join_empty_to_nonempty(self):
-        """Join empty weave onto nonempty."""
-        self.weave1.join(Weave())
-        self.assertEqual(len(self.weave1), 3)
-
-    def test_join_unrelated(self):
-        """Join two weaves with no history in common."""
-        wb = Weave()
-        wb.add_lines('b1', [], ['line from b\n'])
-        w1 = self.weave1
-        w1.join(wb)
-        eq = self.assertEqual
-        eq(len(w1), 4)
-        eq(sorted(w1.versions()),
-           ['b1', 'v1', 'v2', 'v3'])
-
-    def test_join_related(self):
-        wa = self.weave1.copy()
-        wb = self.weave1.copy()
-        wa.add_lines('a1', ['v3'], ['hello\n', 'sweet\n', 'world\n'])
-        wb.add_lines('b1', ['v3'], ['hello\n', 'pale blue\n', 'world\n'])
-        eq = self.assertEquals
-        eq(len(wa), 4)
-        eq(len(wb), 4)
-        wa.join(wb)
-        eq(len(wa), 5)
-        eq(wa.get_lines('b1'),
-           ['hello\n', 'pale blue\n', 'world\n'])
-
-    def test_join_text_disagreement(self):
-        """Cannot join weaves with different texts for a version."""
-        wa = Weave()
-        wb = Weave()
-        wa.add_lines('v1', [], ['hello\n'])
-        wb.add_lines('v1', [], ['not\n', 'hello\n'])
-        self.assertRaises(WeaveError,
-                          wa.join, wb)
-
-    def test_join_unordered(self):
-        """Join weaves where indexes differ.
-        
-        The source weave contains a different version at index 0."""
-        wa = self.weave1.copy()
-        wb = Weave()
-        wb.add_lines('x1', [], ['line from x1\n'])
-        wb.add_lines('v1', [], ['hello\n'])
-        wb.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
-        wa.join(wb)
-        eq = self.assertEquals
-        eq(sorted(wa.versions()), ['v1', 'v2', 'v3', 'x1',])
-        eq(wa.get_text('x1'), 'line from x1\n')
 
     def test_written_detection(self):
         # Test detection of weave file corruption.
@@ -779,57 +719,6 @@
         return Weave._extract(self, versions)
 
 
-class JoinOptimization(TestCase):
-    """Test that Weave.join() doesn't extract all texts, only what must be done."""
-
-    def test_join(self):
-        w1 = InstrumentedWeave()
-        w2 = InstrumentedWeave()
-
-        txt0 = ['a\n']
-        txt1 = ['a\n', 'b\n']
-        txt2 = ['a\n', 'c\n']
-        txt3 = ['a\n', 'b\n', 'c\n']
-
-        w1.add_lines('txt0', [], txt0) # extract 1a
-        w2.add_lines('txt0', [], txt0) # extract 1b
-        w1.add_lines('txt1', ['txt0'], txt1)# extract 2a
-        w2.add_lines('txt2', ['txt0'], txt2)# extract 2b
-        w1.join(w2) # extract 3a to add txt2 
-        w2.join(w1) # extract 3b to add txt1 
-
-        w1.add_lines('txt3', ['txt1', 'txt2'], txt3) # extract 4a 
-        w2.add_lines('txt3', ['txt2', 'txt1'], txt3) # extract 4b
-        # These secretly have inverted parents
-
-        # This should not have to do any extractions
-        w1.join(w2) # NO extract, texts already present with same parents
-        w2.join(w1) # NO extract, texts already present with same parents
-
-        self.assertEqual(4, w1._extract_count)
-        self.assertEqual(4, w2._extract_count)
-
-    def test_double_parent(self):
-        # It should not be considered illegal to add
-        # a revision with the same parent twice
-        w1 = InstrumentedWeave()
-        w2 = InstrumentedWeave()
-
-        txt0 = ['a\n']
-        txt1 = ['a\n', 'b\n']
-        txt2 = ['a\n', 'c\n']
-        txt3 = ['a\n', 'b\n', 'c\n']
-
-        w1.add_lines('txt0', [], txt0)
-        w2.add_lines('txt0', [], txt0)
-        w1.add_lines('txt1', ['txt0'], txt1)
-        w2.add_lines('txt1', ['txt0', 'txt0'], txt1)
-        # Same text, effectively the same, because the
-        # parent is only repeated
-        w1.join(w2) # extract 3a to add txt2 
-        w2.join(w1) # extract 3b to add txt1 
-
-
 class TestNeedsReweave(TestCase):
     """Internal corner cases for when reweave is needed."""
 

=== modified file 'bzrlib/versionedfile.py'
--- a/bzrlib/versionedfile.py	2008-04-24 07:28:18 +0000
+++ b/bzrlib/versionedfile.py	2008-04-29 05:27:08 +0000
@@ -98,6 +98,13 @@
         self.parents = None
 
 
+def filter_absent(record_stream):
+    """Adapt a record stream to remove absent records."""
+    for record in record_stream:
+        if record.storage_kind != 'absent':
+            yield record
+
+
 class VersionedFile(object):
     """Versioned text file storage.
     
@@ -517,6 +524,7 @@
         """
         raise NotImplementedError(self.annotate)
 
+    @deprecated_method(one_five)
     def join(self, other, pb=None, msg=None, version_ids=None,
              ignore_missing=False):
         """Integrate versions from other into this versioned file.




More information about the bazaar-commits mailing list