/brz/remove-bazaar

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