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