~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/workingtree_implementations/test_move.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Tests for interface conformance of 'WorkingTree.move'"""
 
18
 
 
19
import os
 
20
 
 
21
from bzrlib import (
 
22
    errors,
 
23
    osutils,
 
24
    )
 
25
 
 
26
from bzrlib.workingtree_4 import WorkingTreeFormat4
 
27
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
 
28
 
 
29
 
 
30
class TestMove(TestCaseWithWorkingTree):
 
31
 
 
32
    def get_tree_layout(self, tree):
 
33
        """Get the (path, file_id) pairs for the current tree."""
 
34
        tree.lock_read()
 
35
        try:
 
36
            return [(path, ie.file_id) for path, ie
 
37
                    in tree.iter_entries_by_dir()]
 
38
        finally:
 
39
            tree.unlock()
 
40
 
 
41
    def assertTreeLayout(self, expected, tree):
 
42
        """Check that the tree has the correct layout."""
 
43
        actual = self.get_tree_layout(tree)
 
44
        self.assertEqual(expected, actual)
 
45
 
 
46
    def test_move_correct_call_named(self):
 
47
        """tree.move has the deprecated parameter 'to_name'.
 
48
        It has been replaced by 'to_dir' for consistency.
 
49
        Test the new API using named parameter
 
50
        """
 
51
        self.build_tree(['a1', 'sub1/'])
 
52
        tree = self.make_branch_and_tree('.')
 
53
        tree.add(['a1', 'sub1'])
 
54
        tree.commit('initial commit')
 
55
        self.assertEqual([('a1', 'sub1/a1')],
 
56
            tree.move(['a1'], to_dir='sub1', after=False))
 
57
        tree._validate()
 
58
 
 
59
    def test_move_correct_call_unnamed(self):
 
60
        """tree.move has the deprecated parameter 'to_name'.
 
61
        It has been replaced by 'to_dir' for consistency.
 
62
        Test the new API using unnamed parameter
 
63
        """
 
64
        self.build_tree(['a1', 'sub1/'])
 
65
        tree = self.make_branch_and_tree('.')
 
66
        tree.add(['a1', 'sub1'])
 
67
        tree.commit('initial commit')
 
68
        self.assertEqual([('a1', 'sub1/a1')],
 
69
            tree.move(['a1'], 'sub1', after=False))
 
70
        tree._validate()
 
71
 
 
72
    def test_move_deprecated_wrong_call(self):
 
73
        """tree.move has the deprecated parameter 'to_name'.
 
74
        It has been replaced by 'to_dir' for consistency.
 
75
        Test the new API using wrong parameter
 
76
        """
 
77
        self.build_tree(['a1', 'sub1/'])
 
78
        tree = self.make_branch_and_tree('.')
 
79
        tree.add(['a1', 'sub1'])
 
80
        tree.commit('initial commit')
 
81
        self.assertRaises(TypeError, tree.move, ['a1'],
 
82
                          to_this_parameter_does_not_exist='sub1',
 
83
                          after=False)
 
84
        tree._validate()
 
85
 
 
86
    def test_move_deprecated_call(self):
 
87
        """tree.move has the deprecated parameter 'to_name'.
 
88
        It has been replaced by 'to_dir' for consistency.
 
89
        Test the new API using deprecated parameter
 
90
        """
 
91
        self.build_tree(['a1', 'sub1/'])
 
92
        tree = self.make_branch_and_tree('.')
 
93
        tree.add(['a1', 'sub1'])
 
94
        tree.commit('initial commit')
 
95
 
 
96
        try:
 
97
            self.callDeprecated(['The parameter to_name was deprecated'
 
98
                                 ' in version 0.13. Use to_dir instead'],
 
99
                                tree.move, ['a1'], to_name='sub1',
 
100
                                after=False)
 
101
        except TypeError:
 
102
            # WorkingTreeFormat4 doesn't have to maintain api compatibility
 
103
            # since it was deprecated before the class was introduced.
 
104
            if not isinstance(self.workingtree_format, WorkingTreeFormat4):
 
105
                raise
 
106
        tree._validate()
 
107
 
 
108
    def test_move_target_not_dir(self):
 
109
        tree = self.make_branch_and_tree('.')
 
110
        self.build_tree(['a'])
 
111
        tree.add(['a'])
 
112
        tree.commit('initial', rev_id='rev-1')
 
113
 
 
114
        self.assertRaises(errors.BzrMoveFailedError,
 
115
                          tree.move, ['a'], 'not-a-dir')
 
116
        tree._validate()
 
117
 
 
118
    def test_move_non_existent(self):
 
119
        tree = self.make_branch_and_tree('.')
 
120
        self.build_tree(['a/'])
 
121
        tree.add(['a'])
 
122
        tree.commit('initial', rev_id='rev-1')
 
123
        self.assertRaises(errors.BzrMoveFailedError,
 
124
                          tree.move, ['not-a-file'], 'a')
 
125
        self.assertRaises(errors.BzrMoveFailedError,
 
126
                          tree.move, ['not-a-file'], '')
 
127
        tree._validate()
 
128
 
 
129
    def test_move_target_not_versioned(self):
 
130
        tree = self.make_branch_and_tree('.')
 
131
        self.build_tree(['a/', 'b'])
 
132
        tree.add(['b'])
 
133
        tree.commit('initial', rev_id='rev-1')
 
134
        self.assertRaises(errors.BzrMoveFailedError,
 
135
                          tree.move, ['b'], 'a')
 
136
        tree._validate()
 
137
 
 
138
    def test_move_unversioned(self):
 
139
        tree = self.make_branch_and_tree('.')
 
140
        self.build_tree(['a/', 'b'])
 
141
        tree.add(['a'])
 
142
        tree.commit('initial', rev_id='rev-1')
 
143
        self.assertRaises(errors.BzrMoveFailedError,
 
144
                          tree.move, ['b'], 'a')
 
145
        tree._validate()
 
146
 
 
147
    def test_move_multi_unversioned(self):
 
148
        tree = self.make_branch_and_tree('.')
 
149
        self.build_tree(['a/', 'b', 'c', 'd'])
 
150
        tree.add(['a', 'c', 'd'], ['a-id', 'c-id', 'd-id'])
 
151
        tree.commit('initial', rev_id='rev-1')
 
152
        root_id = tree.get_root_id()
 
153
        self.assertRaises(errors.BzrMoveFailedError,
 
154
                          tree.move, ['c', 'b', 'd'], 'a')
 
155
        self.assertRaises(errors.BzrMoveFailedError,
 
156
                          tree.move, ['b', 'c', 'd'], 'a')
 
157
        self.assertRaises(errors.BzrMoveFailedError,
 
158
                          tree.move, ['d', 'c', 'b'], 'a')
 
159
        if osutils.lexists('a/c'):
 
160
            # If 'c' was actually moved, then 'd' should have also been moved
 
161
            self.assertTreeLayout([('', root_id), ('a', 'a-id'),
 
162
                                   ('a/c', 'c-id'),  ('a/d', 'd-id')], tree)
 
163
        else:
 
164
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
165
                                   ('d', 'd-id')], tree)
 
166
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
167
                               ('d', 'd-id')], tree.basis_tree())
 
168
        tree._validate()
 
169
 
 
170
    def test_move_subdir(self):
 
171
        tree = self.make_branch_and_tree('.')
 
172
        self.build_tree(['a', 'b/', 'b/c'])
 
173
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
 
174
        tree.commit('initial', rev_id='rev-1')
 
175
        root_id = tree.get_root_id()
 
176
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
177
                               ('b/c', 'c-id')], tree)
 
178
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
179
                               ('b/c', 'c-id')], tree.basis_tree())
 
180
        a_contents = tree.get_file_text('a-id')
 
181
        self.assertEqual([('a', 'b/a')],
 
182
            tree.move(['a'], 'b'))
 
183
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id'),
 
184
                               ('b/c', 'c-id')], tree)
 
185
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
186
                               ('b/c', 'c-id')], tree.basis_tree())
 
187
        self.failIfExists('a')
 
188
        self.assertFileEqual(a_contents, 'b/a')
 
189
        tree._validate()
 
190
 
 
191
    def test_move_parent_dir(self):
 
192
        tree = self.make_branch_and_tree('.')
 
193
        self.build_tree(['a', 'b/', 'b/c'])
 
194
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
 
195
        tree.commit('initial', rev_id='rev-1')
 
196
        root_id = tree.get_root_id()
 
197
        c_contents = tree.get_file_text('c-id')
 
198
        self.assertEqual([('b/c', 'c')],
 
199
            tree.move(['b/c'], ''))
 
200
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
201
                               ('c', 'c-id')], tree)
 
202
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
203
                               ('b/c', 'c-id')], tree.basis_tree())
 
204
        self.failIfExists('b/c')
 
205
        self.assertFileEqual(c_contents, 'c')
 
206
        tree._validate()
 
207
 
 
208
    def test_move_fail_consistent(self):
 
209
        tree = self.make_branch_and_tree('.')
 
210
        self.build_tree(['a', 'b/', 'b/a', 'c'])
 
211
        tree.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
 
212
        tree.commit('initial', rev_id='rev-1')
 
213
        root_id = tree.get_root_id()
 
214
        # Target already exists
 
215
        self.assertRaises(errors.RenameFailedFilesExist,
 
216
                          tree.move, ['c', 'a'], 'b')
 
217
        # 'c' may or may not have been moved, but either way the tree should
 
218
        # maintain a consistent state.
 
219
        if osutils.lexists('c'):
 
220
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
221
                                   ('c', 'c-id')], tree)
 
222
        else:
 
223
            self.failUnlessExists('b/c')
 
224
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
225
                                   ('b/c', 'c-id')], tree)
 
226
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
227
                               ('c', 'c-id')], tree.basis_tree())
 
228
        tree._validate()
 
229
 
 
230
    def test_move_onto_self(self):
 
231
        tree = self.make_branch_and_tree('.')
 
232
        self.build_tree(['b/', 'b/a'])
 
233
        tree.add(['b', 'b/a'], ['b-id', 'a-id'])
 
234
        tree.commit('initial', rev_id='rev-1')
 
235
 
 
236
        self.assertRaises(errors.BzrMoveFailedError,
 
237
                          tree.move, ['b/a'], 'b')
 
238
        tree._validate()
 
239
 
 
240
    def test_move_onto_self_root(self):
 
241
        tree = self.make_branch_and_tree('.')
 
242
        self.build_tree(['a'])
 
243
        tree.add(['a'], ['a-id'])
 
244
        tree.commit('initial', rev_id='rev-1')
 
245
 
 
246
        self.assertRaises(errors.BzrMoveFailedError,
 
247
                          tree.move, ['a'], 'a')
 
248
        tree._validate()
 
249
 
 
250
    def test_move_after(self):
 
251
        tree = self.make_branch_and_tree('.')
 
252
        self.build_tree(['a', 'b/'])
 
253
        tree.add(['a', 'b'], ['a-id', 'b-id'])
 
254
        tree.commit('initial', rev_id='rev-1')
 
255
        root_id = tree.get_root_id()
 
256
        os.rename('a', 'b/a')
 
257
 
 
258
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
259
                              tree)
 
260
        # We don't need after=True as long as source is missing and target
 
261
        # exists.
 
262
        self.assertEqual([('a', 'b/a')],
 
263
            tree.move(['a'], 'b'))
 
264
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
 
265
                              tree)
 
266
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
267
                              tree.basis_tree())
 
268
        tree._validate()
 
269
 
 
270
    def test_move_after_with_after(self):
 
271
        tree = self.make_branch_and_tree('.')
 
272
        self.build_tree(['a', 'b/'])
 
273
        tree.add(['a', 'b'], ['a-id', 'b-id'])
 
274
        tree.commit('initial', rev_id='rev-1')
 
275
        root_id = tree.get_root_id()
 
276
        os.rename('a', 'b/a')
 
277
 
 
278
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
279
                              tree)
 
280
        # Passing after=True should work as well
 
281
        self.assertEqual([('a', 'b/a')],
 
282
            tree.move(['a'], 'b', after=True))
 
283
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
 
284
                              tree)
 
285
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
286
                              tree.basis_tree())
 
287
        tree._validate()
 
288
 
 
289
    def test_move_after_no_target(self):
 
290
        tree = self.make_branch_and_tree('.')
 
291
        self.build_tree(['a', 'b/'])
 
292
        tree.add(['a', 'b'], ['a-id', 'b-id'])
 
293
        tree.commit('initial', rev_id='rev-1')
 
294
        root_id = tree.get_root_id()
 
295
 
 
296
        # Passing after when the file hasn't been move raises an exception
 
297
        self.assertRaises(errors.BzrMoveFailedError,
 
298
                          tree.move, ['a'], 'b', after=True)
 
299
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
300
                              tree.basis_tree())
 
301
        tree._validate()
 
302
 
 
303
    def test_move_after_source_and_dest(self):
 
304
        tree = self.make_branch_and_tree('.')
 
305
        self.build_tree(['a', 'b/', 'b/a'])
 
306
        tree.add(['a', 'b'], ['a-id', 'b-id'])
 
307
        tree.commit('initial', rev_id='rev-1')
 
308
        root_id = tree.get_root_id()
 
309
 
 
310
        # TODO: jam 20070225 I would usually use 'rb', but assertFileEqual
 
311
        #       uses 'r'.
 
312
        a_file = open('a', 'r')
 
313
        try:
 
314
            a_text = a_file.read()
 
315
        finally:
 
316
            a_file.close()
 
317
        ba_file = open('b/a', 'r')
 
318
        try:
 
319
            ba_text = ba_file.read()
 
320
        finally:
 
321
            ba_file.close()
 
322
 
 
323
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
324
                              tree)
 
325
        self.assertRaises(errors.RenameFailedFilesExist,
 
326
                          tree.move, ['a'], 'b', after=False)
 
327
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
328
                              tree)
 
329
        self.assertFileEqual(a_text, 'a')
 
330
        self.assertFileEqual(ba_text, 'b/a')
 
331
        # But you can pass after=True
 
332
        self.assertEqual([('a', 'b/a')],
 
333
            tree.move(['a'], 'b', after=True))
 
334
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
 
335
                              tree)
 
336
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
337
                              tree.basis_tree())
 
338
        # But it shouldn't actually move anything
 
339
        self.assertFileEqual(a_text, 'a')
 
340
        self.assertFileEqual(ba_text, 'b/a')
 
341
        tree._validate()
 
342
 
 
343
    def test_move_directory(self):
 
344
        tree = self.make_branch_and_tree('.')
 
345
        self.build_tree(['a/', 'a/b', 'a/c/', 'a/c/d', 'e/'])
 
346
        tree.add(['a', 'a/b', 'a/c', 'a/c/d', 'e'],
 
347
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
 
348
        tree.commit('initial', rev_id='rev-1')
 
349
        root_id = tree.get_root_id()
 
350
 
 
351
        self.assertEqual([('a', 'e/a')],
 
352
            tree.move(['a'], 'e'))
 
353
        self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/a', 'a-id'),
 
354
                               ('e/a/b', 'b-id'), ('e/a/c', 'c-id'),
 
355
                               ('e/a/c/d', 'd-id')], tree)
 
356
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
 
357
                               ('a/b', 'b-id'), ('a/c', 'c-id'),
 
358
                               ('a/c/d', 'd-id')], tree.basis_tree())
 
359
        tree._validate()
 
360
 
 
361
    def test_move_directory_into_parent(self):
 
362
        tree = self.make_branch_and_tree('.')
 
363
        self.build_tree(['c/', 'c/b/', 'c/b/d/'])
 
364
        tree.add(['c', 'c/b', 'c/b/d'],
 
365
                 ['c-id', 'b-id', 'd-id'])
 
366
        tree.commit('initial', rev_id='rev-1')
 
367
        root_id = tree.get_root_id()
 
368
 
 
369
        self.assertEqual([('c/b', 'b')],
 
370
                         tree.move(['c/b'], ''))
 
371
        self.assertTreeLayout([('', root_id),
 
372
                               ('b', 'b-id'),
 
373
                               ('c', 'c-id'),
 
374
                               ('b/d', 'd-id'),
 
375
                              ], tree)
 
376
        tree._validate()
 
377
 
 
378
    def test_move_directory_with_children_in_subdir(self):
 
379
        tree = self.make_branch_and_tree('.')
 
380
        self.build_tree(['a/', 'a/b', 'a/c/', 'd/'])
 
381
        tree.add(['a', 'a/b', 'a/c', 'd'],
 
382
                 ['a-id', 'b-id', 'c-id', 'd-id'])
 
383
        tree.commit('initial', rev_id='rev-1')
 
384
        root_id = tree.get_root_id()
 
385
 
 
386
 
 
387
        tree.rename_one('a/b', 'a/c/b')
 
388
        self.assertTreeLayout([('', root_id),
 
389
                               ('a', 'a-id'),
 
390
                               ('d', 'd-id'),
 
391
                               ('a/c', 'c-id'),
 
392
                               ('a/c/b', 'b-id'),
 
393
                              ], tree)
 
394
        self.assertEqual([('a', 'd/a')],
 
395
                         tree.move(['a'], 'd'))
 
396
        self.assertTreeLayout([('', root_id),
 
397
                               ('d', 'd-id'),
 
398
                               ('d/a', 'a-id'),
 
399
                               ('d/a/c', 'c-id'),
 
400
                               ('d/a/c/b', 'b-id'),
 
401
                              ], tree)
 
402
        tree._validate()
 
403
 
 
404
    def test_move_directory_with_deleted_children(self):
 
405
        tree = self.make_branch_and_tree('.')
 
406
        self.build_tree(['a/', 'a/b', 'a/c', 'a/d', 'b/'])
 
407
        tree.add(['a', 'b', 'a/b', 'a/c', 'a/d'],
 
408
                 ['a-id', 'b-id', 'ab-id', 'ac-id', 'ad-id'])
 
409
        tree.commit('initial', rev_id='rev-1')
 
410
        root_id = tree.get_root_id()
 
411
 
 
412
        tree.remove(['a/b', 'a/d'])
 
413
 
 
414
        self.assertEqual([('a', 'b/a')],
 
415
                         tree.move(['a'], 'b'))
 
416
        self.assertTreeLayout([('', root_id),
 
417
                               ('b', 'b-id'),
 
418
                               ('b/a', 'a-id'),
 
419
                               ('b/a/c', 'ac-id'),
 
420
                              ], tree)
 
421
        tree._validate()
 
422
 
 
423
    def test_move_directory_with_new_children(self):
 
424
        tree = self.make_branch_and_tree('.')
 
425
        self.build_tree(['a/', 'a/c', 'b/'])
 
426
        tree.add(['a', 'b', 'a/c'], ['a-id', 'b-id', 'ac-id'])
 
427
        tree.commit('initial', rev_id='rev-1')
 
428
        root_id = tree.get_root_id()
 
429
 
 
430
        self.build_tree(['a/b', 'a/d'])
 
431
        tree.add(['a/b', 'a/d'], ['ab-id', 'ad-id'])
 
432
 
 
433
        self.assertEqual([('a', 'b/a')],
 
434
                         tree.move(['a'], 'b'))
 
435
        self.assertTreeLayout([('', root_id),
 
436
                               ('b', 'b-id'),
 
437
                               ('b/a', 'a-id'),
 
438
                               ('b/a/b', 'ab-id'),
 
439
                               ('b/a/c', 'ac-id'),
 
440
                               ('b/a/d', 'ad-id'),
 
441
                              ], tree)
 
442
        tree._validate()
 
443
 
 
444
    def test_move_directory_with_moved_children(self):
 
445
        tree = self.make_branch_and_tree('.')
 
446
        self.build_tree(['a/', 'a/b', 'a/c', 'd', 'e/'])
 
447
        tree.add(['a', 'a/b', 'a/c', 'd', 'e'],
 
448
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
 
449
        tree.commit('initial', rev_id='rev-1')
 
450
        root_id = tree.get_root_id()
 
451
 
 
452
        self.assertEqual([('a/b', 'b')],
 
453
                         tree.move(['a/b'], ''))
 
454
        self.assertTreeLayout([('', root_id),
 
455
                               ('a', 'a-id'),
 
456
                               ('b', 'b-id'),
 
457
                               ('d', 'd-id'),
 
458
                               ('e', 'e-id'),
 
459
                               ('a/c', 'c-id'),
 
460
                              ], tree)
 
461
        self.assertEqual([('d', 'a/d')],
 
462
                         tree.move(['d'], 'a'))
 
463
        self.assertTreeLayout([('', root_id),
 
464
                               ('a', 'a-id'),
 
465
                               ('b', 'b-id'),
 
466
                               ('e', 'e-id'),
 
467
                               ('a/c', 'c-id'),
 
468
                               ('a/d', 'd-id'),
 
469
                              ], tree)
 
470
        self.assertEqual([('a', 'e/a')],
 
471
                         tree.move(['a'], 'e'))
 
472
        self.assertTreeLayout([('', root_id),
 
473
                               ('b', 'b-id'),
 
474
                               ('e', 'e-id'),
 
475
                               ('e/a', 'a-id'),
 
476
                               ('e/a/c', 'c-id'),
 
477
                               ('e/a/d', 'd-id'),
 
478
                              ], tree)
 
479
        tree._validate()
 
480
 
 
481
    def test_move_directory_with_renamed_child(self):
 
482
        tree = self.make_branch_and_tree('.')
 
483
        self.build_tree(['a/', 'a/b', 'a/c', 'd/'])
 
484
        tree.add(['a', 'a/b', 'a/c', 'd'],
 
485
                 ['a-id', 'b-id', 'c-id', 'd-id'])
 
486
        tree.commit('initial', rev_id='rev-1')
 
487
        root_id = tree.get_root_id()
 
488
 
 
489
        tree.rename_one('a/b', 'a/d')
 
490
        self.assertTreeLayout([('', root_id),
 
491
                               ('a', 'a-id'),
 
492
                               ('d', 'd-id'),
 
493
                               ('a/c', 'c-id'),
 
494
                               ('a/d', 'b-id'),
 
495
                              ], tree)
 
496
        self.assertEqual([('a', 'd/a')],
 
497
                         tree.move(['a'], 'd'))
 
498
        self.assertTreeLayout([('', root_id),
 
499
                               ('d', 'd-id'),
 
500
                               ('d/a', 'a-id'),
 
501
                               ('d/a/c', 'c-id'),
 
502
                               ('d/a/d', 'b-id'),
 
503
                              ], tree)
 
504
        tree._validate()
 
505
 
 
506
    def test_move_directory_with_swapped_children(self):
 
507
        tree = self.make_branch_and_tree('.')
 
508
        self.build_tree(['a/', 'a/b', 'a/c', 'a/d', 'e/'])
 
509
        tree.add(['a', 'a/b', 'a/c', 'a/d', 'e'],
 
510
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
 
511
        tree.commit('initial', rev_id='rev-1')
 
512
        root_id = tree.get_root_id()
 
513
 
 
514
        tree.rename_one('a/b', 'a/bb')
 
515
        tree.rename_one('a/d', 'a/b')
 
516
        tree.rename_one('a/bb', 'a/d')
 
517
        self.assertTreeLayout([('', root_id),
 
518
                               ('a', 'a-id'),
 
519
                               ('e', 'e-id'),
 
520
                               ('a/b', 'd-id'),
 
521
                               ('a/c', 'c-id'),
 
522
                               ('a/d', 'b-id'),
 
523
                              ], tree)
 
524
        self.assertEqual([('a', 'e/a')],
 
525
                         tree.move(['a'], 'e'))
 
526
        self.assertTreeLayout([('', root_id),
 
527
                               ('e', 'e-id'),
 
528
                               ('e/a', 'a-id'),
 
529
                               ('e/a/b', 'd-id'),
 
530
                               ('e/a/c', 'c-id'),
 
531
                               ('e/a/d', 'b-id'),
 
532
                              ], tree)
 
533
        tree._validate()
 
534
 
 
535
    def test_move_moved(self):
 
536
        """Moving a moved entry works as expected."""
 
537
        tree = self.make_branch_and_tree('.')
 
538
        self.build_tree(['a/', 'a/b', 'c/'])
 
539
        tree.add(['a', 'a/b', 'c'], ['a-id', 'b-id', 'c-id'])
 
540
        tree.commit('initial', rev_id='rev-1')
 
541
        root_id = tree.get_root_id()
 
542
 
 
543
        self.assertEqual([('a/b', 'c/b')],
 
544
            tree.move(['a/b'], 'c'))
 
545
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
546
                               ('c/b', 'b-id')], tree)
 
547
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
548
                               ('a/b', 'b-id')], tree.basis_tree())
 
549
 
 
550
        self.assertEqual([('c/b', 'b')],
 
551
            tree.move(['c/b'], ''))
 
552
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
553
                               ('c', 'c-id')], tree)
 
554
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
555
                               ('a/b', 'b-id')], tree.basis_tree())
 
556
        tree._validate()