~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2006-2009, 2011 Canonical Ltd
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
16
17
"""Tests for Tree and InterTree."""
18
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
19
from bzrlib import (
20
    errors,
21
    revision,
22
    tree as _mod_tree,
23
    )
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
24
from bzrlib.tests import TestCaseWithTransport
25
from bzrlib.tree import InterTree
26
27
28
class TestInterTree(TestCaseWithTransport):
29
30
    def test_revision_tree_revision_tree(self):
31
        # we should have an InterTree registered for RevisionTree to
32
        # RevisionTree.
33
        tree = self.make_branch_and_tree('.')
34
        rev_id = tree.commit('first post')
35
        rev_id2 = tree.commit('second post', allow_pointless=True)
36
        rev_tree = tree.branch.repository.revision_tree(rev_id)
37
        rev_tree2 = tree.branch.repository.revision_tree(rev_id2)
38
        optimiser = InterTree.get(rev_tree, rev_tree2)
39
        self.assertIsInstance(optimiser, InterTree)
40
        optimiser = InterTree.get(rev_tree2, rev_tree)
41
        self.assertIsInstance(optimiser, InterTree)
42
43
    def test_working_tree_revision_tree(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
44
        # we should have an InterTree available for WorkingTree to
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
45
        # RevisionTree.
46
        tree = self.make_branch_and_tree('.')
47
        rev_id = tree.commit('first post')
48
        rev_tree = tree.branch.repository.revision_tree(rev_id)
49
        optimiser = InterTree.get(rev_tree, tree)
50
        self.assertIsInstance(optimiser, InterTree)
51
        optimiser = InterTree.get(tree, rev_tree)
52
        self.assertIsInstance(optimiser, InterTree)
53
54
    def test_working_tree_working_tree(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
55
        # we should have an InterTree available for WorkingTree to
1852.8.2 by Robert Collins
Add InterTree class to represent InterTree operations.
56
        # WorkingTree.
57
        tree = self.make_branch_and_tree('1')
58
        tree2 = self.make_branch_and_tree('2')
59
        optimiser = InterTree.get(tree, tree2)
60
        self.assertIsInstance(optimiser, InterTree)
61
        optimiser = InterTree.get(tree2, tree)
62
        self.assertIsInstance(optimiser, InterTree)
1852.8.4 by Robert Collins
Hook InterTree into Tree.
63
64
65
class RecordingOptimiser(InterTree):
66
67
    calls = []
68
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
69
    def compare(self, want_unchanged=False, specific_files=None,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
70
        extra_trees=None, require_versioned=False, include_root=False,
71
        want_unversioned=False):
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
72
        self.calls.append(
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
73
            ('compare', self.source, self.target, want_unchanged,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
74
             specific_files, extra_trees, require_versioned,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
75
             include_root, want_unversioned)
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
76
            )
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
77
1852.8.4 by Robert Collins
Hook InterTree into Tree.
78
    @classmethod
79
    def is_compatible(klass, source, target):
80
        return True
81
82
83
class TestTree(TestCaseWithTransport):
84
85
    def test_compare_calls_InterTree_compare(self):
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
86
        """This test tests the way Tree.compare() uses InterTree."""
1852.8.4 by Robert Collins
Hook InterTree into Tree.
87
        old_optimisers = InterTree._optimisers
88
        try:
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
89
            InterTree._optimisers = []
1852.8.4 by Robert Collins
Hook InterTree into Tree.
90
            RecordingOptimiser.calls = []
91
            InterTree.register_optimiser(RecordingOptimiser)
92
            tree = self.make_branch_and_tree('1')
93
            tree2 = self.make_branch_and_tree('2')
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
94
            # do a series of calls:
95
            # trivial usage
1852.8.8 by Robert Collins
change Tree.compare to Tree.changes_from - its better for the common case.
96
            tree.changes_from(tree2)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
97
            # pass in all optional arguments by position
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
98
            tree.changes_from(tree2, 'unchanged', 'specific', 'extra',
1910.2.57 by Aaron Bentley
Got 0.9 bundles working, with root included by changes_from
99
                              'require', True)
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
100
            # pass in all optional arguments by keyword
1852.9.6 by Robert Collins
Merge the change from Tree.compare to Tree.changes_from.
101
            tree.changes_from(tree2,
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
102
                specific_files='specific',
103
                want_unchanged='unchanged',
104
                extra_trees='extra',
1852.9.5 by Robert Collins
Add tests for require_versioned to the InterTree.compare() test suite.
105
                require_versioned='require',
1910.2.57 by Aaron Bentley
Got 0.9 bundles working, with root included by changes_from
106
                include_root=True,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
107
                want_unversioned=True,
1852.9.4 by Robert Collins
Add minimal test for Tree.compare(extra_trees=...).
108
                )
1852.8.4 by Robert Collins
Hook InterTree into Tree.
109
        finally:
110
            InterTree._optimisers = old_optimisers
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
111
        self.assertEqual(
112
            [
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
113
             ('compare', tree2, tree, False, None, None, False, False, False),
114
             ('compare', tree2, tree, 'unchanged', 'specific', 'extra',
115
              'require', True, False),
116
             ('compare', tree2, tree, 'unchanged', 'specific', 'extra',
117
              'require', True, True),
1852.9.3 by Robert Collins
Convert the test_delta tests to intertree_implementation and workingtree_implementation tests as appropriate.
118
            ], RecordingOptimiser.calls)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
119
120
    def test_changes_from_with_root(self):
121
        """Ensure the include_root option does what's expected."""
122
        wt = self.make_branch_and_tree('.')
123
        delta = wt.changes_from(wt.basis_tree())
124
        self.assertEqual(len(delta.added), 0)
4570.2.7 by Robert Collins
Fix misuse of tree.compare API in test_tree.py
125
        delta = wt.changes_from(wt.basis_tree(), include_root=True)
1731.1.33 by Aaron Bentley
Revert no-special-root changes
126
        self.assertEqual(len(delta.added), 1)
127
        self.assertEqual(delta.added[0][0], '')
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
128
129
    def test_changes_from_with_require_versioned(self):
130
        """Ensure the require_versioned option does what's expected."""
131
        wt = self.make_branch_and_tree('.')
132
        self.build_tree(['known_file', 'unknown_file'])
133
        wt.add('known_file')
134
2655.2.2 by Marius Kruger
Rather use assertRaises in test_changes_from_with_require_versioned
135
        self.assertRaises(errors.PathsNotVersionedError,
136
            wt.changes_from, wt.basis_tree(), wt, specific_files=['known_file',
137
            'unknown_file'], require_versioned=True)
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
138
139
        # we need to pass a known file with an unknown file to get this to
140
        # fail when expected.
4570.2.7 by Robert Collins
Fix misuse of tree.compare API in test_tree.py
141
        delta = wt.changes_from(wt.basis_tree(),
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
142
            specific_files=['known_file', 'unknown_file'] ,
143
            require_versioned=False)
144
        self.assertEqual(len(delta.added), 1)
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
145
146
147
class TestMultiWalker(TestCaseWithTransport):
148
149
    def assertStepOne(self, has_more, path, file_id, iterator):
150
        retval = _mod_tree.MultiWalker._step_one(iterator)
151
        if not has_more:
152
            self.assertIs(None, path)
153
            self.assertIs(None, file_id)
154
            self.assertEqual((False, None, None), retval)
155
        else:
156
            self.assertEqual((has_more, path, file_id),
157
                             (retval[0], retval[1], retval[2].file_id))
158
159
    def test__step_one_empty(self):
160
        tree = self.make_branch_and_tree('empty')
161
        repo = tree.branch.repository
162
        empty_tree = repo.revision_tree(revision.NULL_REVISION)
163
164
        iterator = empty_tree.iter_entries_by_dir()
165
        self.assertStepOne(False, None, None, iterator)
166
        self.assertStepOne(False, None, None, iterator)
167
168
    def test__step_one(self):
169
        tree = self.make_branch_and_tree('tree')
170
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
171
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
172
173
        iterator = tree.iter_entries_by_dir()
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
174
        tree.lock_read()
175
        self.addCleanup(tree.unlock)
176
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
177
        root_id = tree.path2id('')
178
        self.assertStepOne(True, '', root_id, iterator)
179
        self.assertStepOne(True, 'a', 'a-id', iterator)
180
        self.assertStepOne(True, 'b', 'b-id', iterator)
181
        self.assertStepOne(True, 'b/c', 'c-id', iterator)
182
        self.assertStepOne(False, None, None, iterator)
183
        self.assertStepOne(False, None, None, iterator)
184
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
185
    def assertWalkerNext(self, exp_path, exp_file_id, master_has_node,
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
186
                         exp_other_paths, iterator):
187
        """Check what happens when we step the iterator.
188
189
        :param path: The path for this entry
190
        :param file_id: The file_id for this entry
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
191
        :param master_has_node: Does the master tree have this entry?
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
192
        :param exp_other_paths: A list of other_path values.
193
        :param iterator: The iterator to step
194
        """
195
        path, file_id, master_ie, other_values = iterator.next()
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
196
        self.assertEqual((exp_path, exp_file_id), (path, file_id),
197
                         'Master entry did not match')
198
        if master_has_node:
199
            self.assertIsNot(None, master_ie, 'master should have an entry')
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
200
        else:
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
201
            self.assertIs(None, master_ie, 'master should not have an entry')
202
        self.assertEqual(len(exp_other_paths), len(other_values),
203
                            'Wrong number of other entries')
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
204
        other_paths = []
205
        other_file_ids = []
206
        for path, ie in other_values:
207
            other_paths.append(path)
208
            if ie is None:
209
                other_file_ids.append(None)
210
            else:
211
                other_file_ids.append(ie.file_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
212
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
213
        exp_file_ids = []
214
        for path in exp_other_paths:
215
            if path is None:
216
                exp_file_ids.append(None)
217
            else:
218
                exp_file_ids.append(file_id)
219
        self.assertEqual(exp_other_paths, other_paths, "Other paths incorrect")
220
        self.assertEqual(exp_file_ids, other_file_ids,
221
                         "Other file_ids incorrect")
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
222
223
    def lock_and_get_basis_and_root_id(self, tree):
224
        tree.lock_read()
225
        self.addCleanup(tree.unlock)
226
        basis_tree = tree.basis_tree()
227
        basis_tree.lock_read()
228
        self.addCleanup(basis_tree.unlock)
229
        root_id = tree.path2id('')
230
        return basis_tree, root_id
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
231
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
232
    def test_simple_stepping(self):
233
        tree = self.make_branch_and_tree('tree')
234
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
235
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
236
237
        tree.commit('first', rev_id='first-rev-id')
238
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
239
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
240
241
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
242
        iterator = walker.iter_all()
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
243
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
244
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
245
        self.assertWalkerNext(u'b', 'b-id', True, [u'b'], iterator)
246
        self.assertWalkerNext(u'b/c', 'c-id', True, [u'b/c'], iterator)
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
247
        self.assertRaises(StopIteration, iterator.next)
248
249
    def test_master_has_extra(self):
250
        tree = self.make_branch_and_tree('tree')
251
        self.build_tree(['tree/a', 'tree/b/', 'tree/c', 'tree/d'])
252
        tree.add(['a', 'b', 'd'], ['a-id', 'b-id', 'd-id'])
253
254
        tree.commit('first', rev_id='first-rev-id')
255
256
        tree.add(['c'], ['c-id'])
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
257
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
258
259
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
260
        iterator = walker.iter_all()
261
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
262
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
263
        self.assertWalkerNext(u'b', 'b-id', True, [u'b'], iterator)
264
        self.assertWalkerNext(u'c', 'c-id', True, [None], iterator)
265
        self.assertWalkerNext(u'd', 'd-id', True, [u'd'], iterator)
266
        self.assertRaises(StopIteration, iterator.next)
267
268
    def test_master_renamed_to_earlier(self):
269
        """The record is still present, it just shows up early."""
270
        tree = self.make_branch_and_tree('tree')
271
        self.build_tree(['tree/a', 'tree/c', 'tree/d'])
272
        tree.add(['a', 'c', 'd'], ['a-id', 'c-id', 'd-id'])
273
        tree.commit('first', rev_id='first-rev-id')
274
        tree.rename_one('d', 'b')
275
276
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
277
278
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
279
        iterator = walker.iter_all()
280
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
281
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
282
        self.assertWalkerNext(u'b', 'd-id', True, [u'd'], iterator)
283
        self.assertWalkerNext(u'c', 'c-id', True, [u'c'], iterator)
284
        self.assertRaises(StopIteration, iterator.next)
285
286
    def test_master_renamed_to_later(self):
287
        tree = self.make_branch_and_tree('tree')
288
        self.build_tree(['tree/a', 'tree/b', 'tree/d'])
289
        tree.add(['a', 'b', 'd'], ['a-id', 'b-id', 'd-id'])
290
        tree.commit('first', rev_id='first-rev-id')
291
        tree.rename_one('b', 'e')
292
293
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
294
295
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
296
        iterator = walker.iter_all()
297
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
298
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
299
        self.assertWalkerNext(u'd', 'd-id', True, [u'd'], iterator)
300
        self.assertWalkerNext(u'e', 'b-id', True, [u'b'], iterator)
301
        self.assertRaises(StopIteration, iterator.next)
302
3514.3.4 by John Arbash Meinel
Handle more cases when the other tree has extra nodes.
303
    def test_other_extra_in_middle(self):
3514.3.3 by John Arbash Meinel
Handle when the other tree has extra nodes, and we need to yield them.
304
        tree = self.make_branch_and_tree('tree')
305
        self.build_tree(['tree/a', 'tree/b', 'tree/d'])
306
        tree.add(['a', 'b', 'd'], ['a-id', 'b-id', 'd-id'])
307
        tree.commit('first', rev_id='first-rev-id')
308
        tree.remove(['b'])
309
310
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
311
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
312
        iterator = walker.iter_all()
313
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
314
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
315
        self.assertWalkerNext(u'd', 'd-id', True, [u'd'], iterator)
3514.3.2 by John Arbash Meinel
Handle the case when a record is missing in base
316
        self.assertWalkerNext(u'b', 'b-id', False, [u'b'], iterator)
3514.3.1 by John Arbash Meinel
Start working on a special walker that can iterate several trees at once.
317
        self.assertRaises(StopIteration, iterator.next)
3514.3.4 by John Arbash Meinel
Handle more cases when the other tree has extra nodes.
318
319
    def test_other_extra_at_end(self):
320
        tree = self.make_branch_and_tree('tree')
321
        self.build_tree(['tree/a', 'tree/b', 'tree/d'])
322
        tree.add(['a', 'b', 'd'], ['a-id', 'b-id', 'd-id'])
323
        tree.commit('first', rev_id='first-rev-id')
324
        tree.remove(['d'])
325
326
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
327
        walker = _mod_tree.MultiWalker(tree, [basis_tree])
328
        iterator = walker.iter_all()
329
        self.assertWalkerNext(u'', root_id, True, [u''], iterator)
330
        self.assertWalkerNext(u'a', 'a-id', True, [u'a'], iterator)
331
        self.assertWalkerNext(u'b', 'b-id', True, [u'b'], iterator)
332
        self.assertWalkerNext(u'd', 'd-id', False, [u'd'], iterator)
333
        self.assertRaises(StopIteration, iterator.next)
334
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
335
    def test_others_extra_at_end(self):
336
        tree = self.make_branch_and_tree('tree')
3514.3.6 by John Arbash Meinel
check when there are 3 other trees, rather than just 2
337
        self.build_tree(['tree/a', 'tree/b', 'tree/c', 'tree/d', 'tree/e'])
338
        tree.add(['a', 'b', 'c', 'd', 'e'],
339
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
340
        tree.commit('first', rev_id='first-rev-id')
3514.3.6 by John Arbash Meinel
check when there are 3 other trees, rather than just 2
341
        tree.remove(['e'])
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
342
        tree.commit('second', rev_id='second-rev-id')
3514.3.6 by John Arbash Meinel
check when there are 3 other trees, rather than just 2
343
        tree.remove(['d'])
344
        tree.commit('third', rev_id='third-rev-id')
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
345
        tree.remove(['c'])
346
347
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
348
        first_tree = tree.branch.repository.revision_tree('first-rev-id')
3514.3.6 by John Arbash Meinel
check when there are 3 other trees, rather than just 2
349
        second_tree = tree.branch.repository.revision_tree('second-rev-id')
350
        walker = _mod_tree.MultiWalker(tree, [basis_tree, first_tree,
351
                                              second_tree])
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
352
        iterator = walker.iter_all()
3514.3.6 by John Arbash Meinel
check when there are 3 other trees, rather than just 2
353
        self.assertWalkerNext(u'', root_id, True, [u'', u'', u''], iterator)
354
        self.assertWalkerNext(u'a', 'a-id', True, [u'a', u'a', u'a'], iterator)
355
        self.assertWalkerNext(u'b', 'b-id', True, [u'b', u'b', u'b'], iterator)
356
        self.assertWalkerNext(u'c', 'c-id', False, [u'c', u'c', u'c'], iterator)
357
        self.assertWalkerNext(u'd', 'd-id', False, [None, u'd', u'd'], iterator)
358
        self.assertWalkerNext(u'e', 'e-id', False, [None, u'e', None], iterator)
3514.3.5 by John Arbash Meinel
Handle some edge cases when we have multiple other trees.
359
        self.assertRaises(StopIteration, iterator.next)
3514.3.10 by John Arbash Meinel
A mix-matched commit with things moving in each tree.
360
361
    def test_different_file_id_in_others(self):
362
        tree = self.make_branch_and_tree('tree')
363
        self.build_tree(['tree/a', 'tree/b', 'tree/c/'])
364
        tree.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
365
        tree.commit('first', rev_id='first-rev-id')
366
367
        tree.rename_one('b', 'c/d')
368
        self.build_tree(['tree/b'])
369
        tree.add(['b'], ['b2-id'])
370
        tree.commit('second', rev_id='second-rev-id')
371
372
        tree.rename_one('a', 'c/e')
373
        self.build_tree(['tree/a'])
374
        tree.add(['a'], ['a2-id'])
375
376
        basis_tree, root_id = self.lock_and_get_basis_and_root_id(tree)
377
        first_tree = tree.branch.repository.revision_tree('first-rev-id')
378
        walker = _mod_tree.MultiWalker(tree, [basis_tree, first_tree])
379
380
        iterator = walker.iter_all()
381
        self.assertWalkerNext(u'', root_id, True, [u'', u''], iterator)
382
        self.assertWalkerNext(u'a', 'a2-id', True, [None, None], iterator)
383
        self.assertWalkerNext(u'b', 'b2-id', True, [u'b', None], iterator)
384
        self.assertWalkerNext(u'c', 'c-id', True, [u'c', u'c'], iterator)
385
        self.assertWalkerNext(u'c/d', 'b-id', True, [u'c/d', u'b'], iterator)
386
        self.assertWalkerNext(u'c/e', 'a-id', True, [u'a', u'a'], iterator)
387
        self.assertRaises(StopIteration, iterator.next)
3514.3.12 by John Arbash Meinel
Found some problems in _path_key, and made sure to have proper testing of _cmp_paths_by_dirblock
388
389
    def assertCmpByDirblock(self, cmp_val, path1, path2):
390
        self.assertEqual(cmp_val,
391
            _mod_tree.MultiWalker._cmp_path_by_dirblock(path1, path2))
392
393
    def test__cmp_path_by_dirblock(self):
394
        # We only support Unicode strings at this point
395
        self.assertRaises(TypeError,
396
            _mod_tree.MultiWalker._cmp_path_by_dirblock, '', 'b')
397
        self.assertCmpByDirblock(0, u'', u'')
398
        self.assertCmpByDirblock(0, u'a', u'a')
399
        self.assertCmpByDirblock(0, u'a/b', u'a/b')
400
        self.assertCmpByDirblock(0, u'a/b/c', u'a/b/c')
401
        self.assertCmpByDirblock(1, u'a-a', u'a')
402
        self.assertCmpByDirblock(-1, u'a-a', u'a/a')
403
        self.assertCmpByDirblock(-1, u'a=a', u'a/a')
404
        self.assertCmpByDirblock(1, u'a-a/a', u'a/a')
405
        self.assertCmpByDirblock(1, u'a=a/a', u'a/a')
406
        self.assertCmpByDirblock(1, u'a-a/a', u'a/a/a')
407
        self.assertCmpByDirblock(1, u'a=a/a', u'a/a/a')
408
        self.assertCmpByDirblock(1, u'a-a/a/a', u'a/a/a')
409
        self.assertCmpByDirblock(1, u'a=a/a/a', u'a/a/a')
410
3514.3.13 by John Arbash Meinel
One code path was using a tuple, another a plain path
411
    def assertPathToKey(self, expected, path):
412
        self.assertEqual(expected, _mod_tree.MultiWalker._path_to_key(path))
3514.3.12 by John Arbash Meinel
Found some problems in _path_key, and made sure to have proper testing of _cmp_paths_by_dirblock
413
3514.3.13 by John Arbash Meinel
One code path was using a tuple, another a plain path
414
    def test__path_to_key(self):
415
        self.assertPathToKey(([u''], u''), u'')
416
        self.assertPathToKey(([u''], u'a'), u'a')
417
        self.assertPathToKey(([u'a'], u'b'), u'a/b')
418
        self.assertPathToKey(([u'a', u'b'], u'c'), u'a/b/c')