/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
1
# Copyright (C) 2006 by Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for join between versioned files."""
18
19
1563.2.13 by Robert Collins
InterVersionedFile implemented.
20
import bzrlib.errors as errors
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
21
from bzrlib.tests import TestCaseWithTransport
22
from bzrlib.transport import get_transport
1563.2.13 by Robert Collins
InterVersionedFile implemented.
23
import bzrlib.versionedfile as versionedfile
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
24
25
26
class TestJoin(TestCaseWithTransport):
27
    #Tests have self.versionedfile_factory and self.versionedfile_factory_to
28
    #available to create source and target versioned files respectively.
29
30
    def get_source(self, name='source'):
31
        """Get a versioned file we will be joining from."""
32
        return self.versionedfile_factory(name,
1563.2.25 by Robert Collins
Merge in upstream.
33
                                          get_transport(self.get_url()),
34
                                          create=True)
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
35
1563.2.13 by Robert Collins
InterVersionedFile implemented.
36
    def get_target(self, name='target'):
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
37
        """"Get an empty versioned file to join into."""
38
        return self.versionedfile_factory_to(name,
1563.2.25 by Robert Collins
Merge in upstream.
39
                                             get_transport(self.get_url()),
40
                                             create=True)
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
41
42
    def test_join(self):
43
        f1 = self.get_source()
44
        f1.add_lines('r0', [], ['a\n', 'b\n'])
45
        f1.add_lines('r1', ['r0'], ['c\n', 'b\n'])
46
        f2 = self.get_target()
47
        f2.join(f1, None)
48
        def verify_file(f):
49
            self.assertTrue(f.has_version('r0'))
50
            self.assertTrue(f.has_version('r1'))
51
        verify_file(f2)
52
        verify_file(self.get_target())
53
1563.2.13 by Robert Collins
InterVersionedFile implemented.
54
        self.assertRaises(errors.RevisionNotPresent,
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
55
            f2.join, f1, version_ids=['r3'])
56
57
        #f3 = self.get_file('1')
58
        #f3.add_lines('r0', ['a\n', 'b\n'], [])
59
        #f3.add_lines('r1', ['c\n', 'b\n'], ['r0'])
60
        #f4 = self.get_file('2')
61
        #f4.join(f3, ['r0'])
62
        #self.assertTrue(f4.has_version('r0'))
63
        #self.assertFalse(f4.has_version('r1'))
64
1563.2.13 by Robert Collins
InterVersionedFile implemented.
65
    def test_gets_expected_inter_worker(self):
66
        source = self.get_source()
67
        target = self.get_target()
68
        inter = versionedfile.InterVersionedFile.get(source, target)
69
        self.assertTrue(isinstance(inter, self.interversionedfile_class))
70
        
71
    def test_join_add_parents(self):
72
        """Join inserting new parents into existing versions
73
        
74
        The new version must have the right parent list and must identify
75
        lines originating in another parent.
76
        """
77
        w1 = self.get_target('w1')
78
        w2 = self.get_source('w2')
79
        w1.add_lines('v-1', [], ['line 1\n'])
80
        w2.add_lines('v-2', [], ['line 2\n'])
81
        w1.add_lines('v-3', ['v-1'], ['line 1\n'])
82
        w2.add_lines('v-3', ['v-2'], ['line 1\n'])
83
        w1.join(w2)
84
        self.assertEqual(sorted(w1.versions()),
85
                         'v-1 v-2 v-3'.split())
86
        self.assertEqualDiff(w1.get_text('v-3'),
87
                'line 1\n')
88
        self.assertEqual(sorted(w1.get_parents('v-3')),
89
                ['v-1', 'v-2'])
90
        ann = list(w1.annotate('v-3'))
91
        self.assertEqual(len(ann), 1)
92
        self.assertEqual(ann[0][0], 'v-1')
93
        self.assertEqual(ann[0][1], 'line 1\n')
94
        
95
    def build_weave1(self):
96
        weave1 = self.get_source()
97
        self.lines1 = ['hello\n']
98
        self.lines3 = ['hello\n', 'cruel\n', 'world\n']
99
        weave1.add_lines('v1', [], self.lines1)
100
        weave1.add_lines('v2', ['v1'], ['hello\n', 'world\n'])
101
        weave1.add_lines('v3', ['v2'], self.lines3)
102
        return weave1
103
        
104
    def test_join_with_empty(self):
105
        """Reweave adding empty weave"""
106
        wb = self.get_target()
107
        w1 = self.build_weave1()
108
        w1.join(wb)
109
        self.verify_weave1(w1)
110
111
    def verify_weave1(self, w1):
112
        self.assertEqual(sorted(w1.versions()), ['v1', 'v2', 'v3'])
113
        self.assertEqual(w1.get_lines('v1'), ['hello\n'])
114
        self.assertEqual([], w1.get_parents('v1'))
115
        self.assertEqual(w1.get_lines('v2'), ['hello\n', 'world\n'])
116
        self.assertEqual(['v1'], w1.get_parents('v2'))
117
        self.assertEqual(w1.get_lines('v3'), ['hello\n', 'cruel\n', 'world\n'])
118
        self.assertEqual(['v2'], w1.get_parents('v3'))
119
120
    def test_join_with_ghosts_merges_parents(self):
121
        """Join combined parent lists"""
122
        wa = self.build_weave1()
123
        wb = self.get_target()
124
        wb.add_lines('x1', [], ['line from x1\n'])
125
        wb.add_lines('v1', [], ['hello\n'])
126
        wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
127
        wa.join(wb)
128
        self.assertEqual(['v1','x1'], wa.get_parents('v2'))
129
130
    def test_join_with_ghosts(self):
131
        """Join that inserts parents of an existing revision.
132
133
        This can happen when merging from another branch who
134
        knows about revisions the destination does not.  In 
135
        this test the second weave knows of an additional parent of 
136
        v2.  Any revisions which are in common still have to have the 
137
        same text.
138
        """
139
        w1 = self.build_weave1()
140
        wb = self.get_target()
141
        wb.add_lines('x1', [], ['line from x1\n'])
142
        wb.add_lines('v1', [], ['hello\n'])
143
        wb.add_lines('v2', ['v1', 'x1'], ['hello\n', 'world\n'])
144
        w1.join(wb)
145
        eq = self.assertEquals
146
        eq(sorted(w1.versions()), ['v1', 'v2', 'v3', 'x1',])
147
        eq(w1.get_text('x1'), 'line from x1\n')
148
        eq(w1.get_lines('v2'), ['hello\n', 'world\n'])
149
        eq(w1.get_parents('v2'), ['v1', 'x1'])
150
151
    def build_source_weave(self, name, *pattern):
152
        w = self.get_source(name)
153
        for version, parents in pattern:
154
            w.add_lines(version, parents, [])
155
        return w
156
157
    def build_target_weave(self, name, *pattern):
158
        w = self.get_target(name)
159
        for version, parents in pattern:
160
            w.add_lines(version, parents, [])
161
        return w
162
163
    def test_join_reorder(self):
164
        """Reweave requiring reordering of versions.
165
166
        Weaves must be stored such that parents come before children.  When
167
        reweaving, we may add new parents to some children, but it is required
168
        that there must be *some* valid order that can be found, otherwise the
169
        ancestries are contradictory.  (For the specific case of inserting
170
        ghost revisions there will be no disagreement, only partial knowledge
171
        of the history.)
172
173
        Note that the weaves are only partially ordered: when there are two
174
        versions where neither is an ancestor of the other the order in which
175
        they occur is unconstrained.  When we join those versions into
176
        another weave, they may become more constrained and it may be
177
        necessary to change their order.
178
179
        One simple case of this is 
180
181
        w1: (c[], a[], b[a])
182
        w2: (b[], c[b], a[])
183
        
184
        We need to recognize that the final weave must show the ordering
185
        a[], b[a], c[b].  The version that must be first in the result is 
186
        not first in either of the input weaves.
187
        """
188
        w1 = self.build_target_weave('1', ('c', []), ('a', []), ('b', ['a']))
189
        w2 = self.build_source_weave('2', ('b', []), ('c', ['b']), ('a', []))
190
        w1.join(w2)
191
        self.assertEqual([], w1.get_parents('a'))
192
        self.assertEqual(['a'], w1.get_parents('b'))
193
        self.assertEqual(['b'], w1.get_parents('c'))