~bzr-pqm/bzr/bzr.dev

2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
1
# Copyright (C) 2006, 2007 Canonical Ltd
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
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
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
16
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
17
"""Tests for interface conformance of 'WorkingTree.move'"""
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
18
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
19
import os
20
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
21
from bzrlib import (
22
    errors,
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
23
    osutils,
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
24
    )
25
3907.2.3 by Ian Clatworthy
DirStateWorkingTree and DirStateWorkingTreeFormat base classes introduced
26
from bzrlib.workingtree_4 import DirStateWorkingTreeFormat
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
27
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
28
29
30
class TestMove(TestCaseWithWorkingTree):
31
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
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
3923.2.1 by Charles Duffy
Fix bug #314251 (dirstate crash on rename via delete+add)
46
    def test_move_via_rm_and_add(self):
47
        """Move by remove and add-with-id"""
48
        self.build_tree(['a1', 'b1'])
49
        tree = self.make_branch_and_tree('.')
50
        tree.add(['a1'], ids=['a1-id'])
51
        tree.commit('initial commit')
52
        tree.remove('a1', force=True, keep_files=False)
53
        tree.add(['b1'], ids=['a1-id'])
54
        tree._validate()
55
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
56
    def test_move_correct_call_named(self):
57
        """tree.move has the deprecated parameter 'to_name'.
58
        It has been replaced by 'to_dir' for consistency.
59
        Test the new API using named parameter
60
        """
61
        self.build_tree(['a1', 'sub1/'])
62
        tree = self.make_branch_and_tree('.')
63
        tree.add(['a1', 'sub1'])
64
        tree.commit('initial commit')
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
65
        self.assertEqual([('a1', 'sub1/a1')],
66
            tree.move(['a1'], to_dir='sub1', after=False))
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
67
        tree._validate()
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
68
69
    def test_move_correct_call_unnamed(self):
70
        """tree.move has the deprecated parameter 'to_name'.
71
        It has been replaced by 'to_dir' for consistency.
72
        Test the new API using unnamed parameter
73
        """
74
        self.build_tree(['a1', 'sub1/'])
75
        tree = self.make_branch_and_tree('.')
76
        tree.add(['a1', 'sub1'])
77
        tree.commit('initial commit')
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
78
        self.assertEqual([('a1', 'sub1/a1')],
79
            tree.move(['a1'], 'sub1', after=False))
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
80
        tree._validate()
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
81
82
    def test_move_deprecated_wrong_call(self):
83
        """tree.move has the deprecated parameter 'to_name'.
84
        It has been replaced by 'to_dir' for consistency.
85
        Test the new API using wrong parameter
86
        """
87
        self.build_tree(['a1', 'sub1/'])
88
        tree = self.make_branch_and_tree('.')
89
        tree.add(['a1', 'sub1'])
90
        tree.commit('initial commit')
91
        self.assertRaises(TypeError, tree.move, ['a1'],
92
                          to_this_parameter_does_not_exist='sub1',
93
                          after=False)
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
94
        tree._validate()
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
95
96
    def test_move_deprecated_call(self):
97
        """tree.move has the deprecated parameter 'to_name'.
98
        It has been replaced by 'to_dir' for consistency.
99
        Test the new API using deprecated parameter
100
        """
101
        self.build_tree(['a1', 'sub1/'])
102
        tree = self.make_branch_and_tree('.')
103
        tree.add(['a1', 'sub1'])
104
        tree.commit('initial commit')
105
106
        try:
107
            self.callDeprecated(['The parameter to_name was deprecated'
108
                                 ' in version 0.13. Use to_dir instead'],
109
                                tree.move, ['a1'], to_name='sub1',
110
                                after=False)
111
        except TypeError:
3907.2.3 by Ian Clatworthy
DirStateWorkingTree and DirStateWorkingTreeFormat base classes introduced
112
            # WorkingTreeFormat4 and later don't have to maintain api
113
            # compatibility since it was deprecated before they were introduced.
114
            if not isinstance(self.workingtree_format,
115
                DirStateWorkingTreeFormat):
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
116
                raise
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
117
        tree._validate()
2255.2.137 by John Arbash Meinel
Move the WorkingTree.move() tests into their own module
118
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
119
    def test_move_target_not_dir(self):
120
        tree = self.make_branch_and_tree('.')
121
        self.build_tree(['a'])
122
        tree.add(['a'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
123
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
124
125
        self.assertRaises(errors.BzrMoveFailedError,
126
                          tree.move, ['a'], 'not-a-dir')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
127
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
128
129
    def test_move_non_existent(self):
130
        tree = self.make_branch_and_tree('.')
131
        self.build_tree(['a/'])
132
        tree.add(['a'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
133
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
134
        self.assertRaises(errors.BzrMoveFailedError,
135
                          tree.move, ['not-a-file'], 'a')
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
136
        self.assertRaises(errors.BzrMoveFailedError,
137
                          tree.move, ['not-a-file'], '')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
138
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
139
140
    def test_move_target_not_versioned(self):
141
        tree = self.make_branch_and_tree('.')
142
        self.build_tree(['a/', 'b'])
143
        tree.add(['b'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
144
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
145
        self.assertRaises(errors.BzrMoveFailedError,
146
                          tree.move, ['b'], 'a')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
147
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
148
149
    def test_move_unversioned(self):
150
        tree = self.make_branch_and_tree('.')
151
        self.build_tree(['a/', 'b'])
152
        tree.add(['a'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
153
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
154
        self.assertRaises(errors.BzrMoveFailedError,
155
                          tree.move, ['b'], 'a')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
156
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
157
158
    def test_move_multi_unversioned(self):
159
        tree = self.make_branch_and_tree('.')
160
        self.build_tree(['a/', 'b', 'c', 'd'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
161
        tree.add(['a', 'c', 'd'], ['a-id', 'c-id', 'd-id'])
162
        tree.commit('initial', rev_id='rev-1')
163
        root_id = tree.get_root_id()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
164
        self.assertRaises(errors.BzrMoveFailedError,
165
                          tree.move, ['c', 'b', 'd'], 'a')
166
        self.assertRaises(errors.BzrMoveFailedError,
167
                          tree.move, ['b', 'c', 'd'], 'a')
168
        self.assertRaises(errors.BzrMoveFailedError,
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
169
                          tree.move, ['d', 'c', 'b'], 'a')
170
        if osutils.lexists('a/c'):
171
            # If 'c' was actually moved, then 'd' should have also been moved
172
            self.assertTreeLayout([('', root_id), ('a', 'a-id'),
173
                                   ('a/c', 'c-id'),  ('a/d', 'd-id')], tree)
174
        else:
175
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
176
                                   ('d', 'd-id')], tree)
177
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
178
                               ('d', 'd-id')], tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
179
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
180
2456.2.1 by John Arbash Meinel
(broken) Add a (failing) test that _iter_changes works correctly
181
    def test_move_over_deleted(self):
182
        tree = self.make_branch_and_tree('.')
183
        self.build_tree(['a/', 'a/b', 'b'])
184
        tree.add(['a', 'a/b', 'b'], ['a-id', 'ab-id', 'b-id'])
185
        tree.commit('initial', rev_id='rev-1')
186
187
        root_id = tree.get_root_id()
188
        tree.remove(['a/b'], keep_files=False)
189
        self.assertEqual([('b', 'a/b')], tree.move(['b'], 'a'))
190
        self.assertTreeLayout([('', root_id),
191
                               ('a', 'a-id'),
192
                               ('a/b', 'b-id'),
193
                              ], tree)
194
        tree._validate()
195
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
196
    def test_move_subdir(self):
197
        tree = self.make_branch_and_tree('.')
198
        self.build_tree(['a', 'b/', 'b/c'])
199
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
200
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
201
        root_id = tree.get_root_id()
202
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
203
                               ('b/c', 'c-id')], tree)
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
204
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
205
                               ('b/c', 'c-id')], tree.basis_tree())
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
206
        a_contents = tree.get_file_text('a-id')
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
207
        self.assertEqual([('a', 'b/a')],
208
            tree.move(['a'], 'b'))
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
209
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id'),
210
                               ('b/c', 'c-id')], tree)
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
211
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
212
                               ('b/c', 'c-id')], tree.basis_tree())
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
213
        self.failIfExists('a')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
214
        self.assertFileEqual(a_contents, 'b/a')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
215
        tree._validate()
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
216
217
    def test_move_parent_dir(self):
218
        tree = self.make_branch_and_tree('.')
219
        self.build_tree(['a', 'b/', 'b/c'])
220
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
221
        tree.commit('initial', rev_id='rev-1')
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
222
        root_id = tree.get_root_id()
223
        c_contents = tree.get_file_text('c-id')
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
224
        self.assertEqual([('b/c', 'c')],
225
            tree.move(['b/c'], ''))
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
226
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
227
                               ('c', 'c-id')], tree)
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
228
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
229
                               ('b/c', 'c-id')], tree.basis_tree())
2255.2.138 by John Arbash Meinel
implement several new WorkingTree.move() tests
230
        self.failIfExists('b/c')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
231
        self.assertFileEqual(c_contents, 'c')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
232
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
233
234
    def test_move_fail_consistent(self):
235
        tree = self.make_branch_and_tree('.')
236
        self.build_tree(['a', 'b/', 'b/a', 'c'])
237
        tree.add(['a', 'b', 'c'], ['a-id', 'b-id', 'c-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
238
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
239
        root_id = tree.get_root_id()
240
        # Target already exists
241
        self.assertRaises(errors.RenameFailedFilesExist,
242
                          tree.move, ['c', 'a'], 'b')
243
        # 'c' may or may not have been moved, but either way the tree should
244
        # maintain a consistent state.
245
        if osutils.lexists('c'):
246
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
247
                                   ('c', 'c-id')], tree)
248
        else:
249
            self.failUnlessExists('b/c')
250
            self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
251
                                   ('b/c', 'c-id')], tree)
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
252
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
253
                               ('c', 'c-id')], tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
254
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
255
256
    def test_move_onto_self(self):
257
        tree = self.make_branch_and_tree('.')
258
        self.build_tree(['b/', 'b/a'])
259
        tree.add(['b', 'b/a'], ['b-id', 'a-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
260
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
261
262
        self.assertRaises(errors.BzrMoveFailedError,
263
                          tree.move, ['b/a'], 'b')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
264
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
265
266
    def test_move_onto_self_root(self):
267
        tree = self.make_branch_and_tree('.')
268
        self.build_tree(['a'])
269
        tree.add(['a'], ['a-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
270
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
271
272
        self.assertRaises(errors.BzrMoveFailedError,
273
                          tree.move, ['a'], 'a')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
274
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
275
276
    def test_move_after(self):
277
        tree = self.make_branch_and_tree('.')
278
        self.build_tree(['a', 'b/'])
279
        tree.add(['a', 'b'], ['a-id', 'b-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
280
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
281
        root_id = tree.get_root_id()
282
        os.rename('a', 'b/a')
283
284
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
285
                              tree)
286
        # We don't need after=True as long as source is missing and target
287
        # exists.
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
288
        self.assertEqual([('a', 'b/a')],
289
            tree.move(['a'], 'b'))
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
290
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
291
                              tree)
2255.2.141 by John Arbash Meinel
Some small changes to move tests.
292
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
293
                              tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
294
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
295
296
    def test_move_after_with_after(self):
297
        tree = self.make_branch_and_tree('.')
298
        self.build_tree(['a', 'b/'])
299
        tree.add(['a', 'b'], ['a-id', 'b-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
300
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
301
        root_id = tree.get_root_id()
302
        os.rename('a', 'b/a')
303
304
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
305
                              tree)
306
        # Passing after=True should work as well
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
307
        self.assertEqual([('a', 'b/a')],
308
            tree.move(['a'], 'b', after=True))
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
309
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
310
                              tree)
2255.2.141 by John Arbash Meinel
Some small changes to move tests.
311
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
312
                              tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
313
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
314
315
    def test_move_after_no_target(self):
316
        tree = self.make_branch_and_tree('.')
317
        self.build_tree(['a', 'b/'])
318
        tree.add(['a', 'b'], ['a-id', 'b-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
319
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
320
        root_id = tree.get_root_id()
321
322
        # Passing after when the file hasn't been move raises an exception
323
        self.assertRaises(errors.BzrMoveFailedError,
324
                          tree.move, ['a'], 'b', after=True)
2255.2.141 by John Arbash Meinel
Some small changes to move tests.
325
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
326
                              tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
327
        tree._validate()
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
328
329
    def test_move_after_source_and_dest(self):
330
        tree = self.make_branch_and_tree('.')
331
        self.build_tree(['a', 'b/', 'b/a'])
332
        tree.add(['a', 'b'], ['a-id', 'b-id'])
2255.2.140 by John Arbash Meinel
Update tests to ensure basis tree is not modified
333
        tree.commit('initial', rev_id='rev-1')
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
334
        root_id = tree.get_root_id()
335
336
        # TODO: jam 20070225 I would usually use 'rb', but assertFileEqual
337
        #       uses 'r'.
338
        a_file = open('a', 'r')
339
        try:
340
            a_text = a_file.read()
341
        finally:
342
            a_file.close()
343
        ba_file = open('b/a', 'r')
344
        try:
345
            ba_text = ba_file.read()
346
        finally:
347
            ba_file.close()
348
349
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
350
                              tree)
351
        self.assertRaises(errors.RenameFailedFilesExist,
352
                          tree.move, ['a'], 'b', after=False)
353
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
354
                              tree)
355
        self.assertFileEqual(a_text, 'a')
356
        self.assertFileEqual(ba_text, 'b/a')
357
        # But you can pass after=True
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
358
        self.assertEqual([('a', 'b/a')],
359
            tree.move(['a'], 'b', after=True))
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
360
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
361
                              tree)
2255.2.141 by John Arbash Meinel
Some small changes to move tests.
362
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
363
                              tree.basis_tree())
2255.2.139 by John Arbash Meinel
test cases for moving after a file has already been moved.
364
        # But it shouldn't actually move anything
365
        self.assertFileEqual(a_text, 'a')
366
        self.assertFileEqual(ba_text, 'b/a')
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
367
        tree._validate()
2255.2.146 by John Arbash Meinel
Implement move_directory by factoring out move_one
368
369
    def test_move_directory(self):
370
        tree = self.make_branch_and_tree('.')
371
        self.build_tree(['a/', 'a/b', 'a/c/', 'a/c/d', 'e/'])
372
        tree.add(['a', 'a/b', 'a/c', 'a/c/d', 'e'],
373
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
374
        tree.commit('initial', rev_id='rev-1')
375
        root_id = tree.get_root_id()
376
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
377
        self.assertEqual([('a', 'e/a')],
378
            tree.move(['a'], 'e'))
2255.2.146 by John Arbash Meinel
Implement move_directory by factoring out move_one
379
        self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/a', 'a-id'),
380
                               ('e/a/b', 'b-id'), ('e/a/c', 'c-id'),
381
                               ('e/a/c/d', 'd-id')], tree)
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
382
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
383
                               ('a/b', 'b-id'), ('a/c', 'c-id'),
384
                               ('a/c/d', 'd-id')], tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
385
        tree._validate()
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
386
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
387
    def test_move_directory_into_parent(self):
388
        tree = self.make_branch_and_tree('.')
389
        self.build_tree(['c/', 'c/b/', 'c/b/d/'])
390
        tree.add(['c', 'c/b', 'c/b/d'],
391
                 ['c-id', 'b-id', 'd-id'])
392
        tree.commit('initial', rev_id='rev-1')
393
        root_id = tree.get_root_id()
394
395
        self.assertEqual([('c/b', 'b')],
396
                         tree.move(['c/b'], ''))
397
        self.assertTreeLayout([('', root_id),
398
                               ('b', 'b-id'),
399
                               ('c', 'c-id'),
400
                               ('b/d', 'd-id'),
401
                              ], tree)
402
        tree._validate()
403
2438.1.13 by John Arbash Meinel
Add a test for moving a directory where a child has been moved into a subdir.
404
    def test_move_directory_with_children_in_subdir(self):
405
        tree = self.make_branch_and_tree('.')
406
        self.build_tree(['a/', 'a/b', 'a/c/', 'd/'])
407
        tree.add(['a', 'a/b', 'a/c', 'd'],
408
                 ['a-id', 'b-id', 'c-id', 'd-id'])
409
        tree.commit('initial', rev_id='rev-1')
410
        root_id = tree.get_root_id()
411
412
413
        tree.rename_one('a/b', 'a/c/b')
414
        self.assertTreeLayout([('', root_id),
415
                               ('a', 'a-id'),
416
                               ('d', 'd-id'),
417
                               ('a/c', 'c-id'),
418
                               ('a/c/b', 'b-id'),
419
                              ], tree)
420
        self.assertEqual([('a', 'd/a')],
421
                         tree.move(['a'], 'd'))
422
        self.assertTreeLayout([('', root_id),
423
                               ('d', 'd-id'),
424
                               ('d/a', 'a-id'),
425
                               ('d/a/c', 'c-id'),
426
                               ('d/a/c/b', 'b-id'),
427
                              ], tree)
428
        tree._validate()
429
2438.1.7 by John Arbash Meinel
While in this area, add a test for renaming a directory with removed children.
430
    def test_move_directory_with_deleted_children(self):
431
        tree = self.make_branch_and_tree('.')
432
        self.build_tree(['a/', 'a/b', 'a/c', 'a/d', 'b/'])
433
        tree.add(['a', 'b', 'a/b', 'a/c', 'a/d'],
434
                 ['a-id', 'b-id', 'ab-id', 'ac-id', 'ad-id'])
435
        tree.commit('initial', rev_id='rev-1')
436
        root_id = tree.get_root_id()
437
438
        tree.remove(['a/b', 'a/d'])
439
440
        self.assertEqual([('a', 'b/a')],
441
                         tree.move(['a'], 'b'))
442
        self.assertTreeLayout([('', root_id),
443
                               ('b', 'b-id'),
444
                               ('b/a', 'a-id'),
445
                               ('b/a/c', 'ac-id'),
446
                              ], tree)
447
        tree._validate()
448
2438.1.6 by John Arbash Meinel
Simplify the test since all we require is renaming a newly added entry's parent dir.
449
    def test_move_directory_with_new_children(self):
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
450
        tree = self.make_branch_and_tree('.')
2438.1.6 by John Arbash Meinel
Simplify the test since all we require is renaming a newly added entry's parent dir.
451
        self.build_tree(['a/', 'a/c', 'b/'])
452
        tree.add(['a', 'b', 'a/c'], ['a-id', 'b-id', 'ac-id'])
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
453
        tree.commit('initial', rev_id='rev-1')
454
        root_id = tree.get_root_id()
455
2438.1.6 by John Arbash Meinel
Simplify the test since all we require is renaming a newly added entry's parent dir.
456
        self.build_tree(['a/b', 'a/d'])
457
        tree.add(['a/b', 'a/d'], ['ab-id', 'ad-id'])
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
458
2438.1.6 by John Arbash Meinel
Simplify the test since all we require is renaming a newly added entry's parent dir.
459
        self.assertEqual([('a', 'b/a')],
460
                         tree.move(['a'], 'b'))
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
461
        self.assertTreeLayout([('', root_id),
462
                               ('b', 'b-id'),
463
                               ('b/a', 'a-id'),
2438.1.6 by John Arbash Meinel
Simplify the test since all we require is renaming a newly added entry's parent dir.
464
                               ('b/a/b', 'ab-id'),
465
                               ('b/a/c', 'ac-id'),
466
                               ('b/a/d', 'ad-id'),
2438.1.3 by John Arbash Meinel
Add 2 new WT.move() tests, one of which exposes bug #105479
467
                              ], tree)
468
        tree._validate()
469
2438.1.9 by John Arbash Meinel
Add another (failing) test when we move an entry which has a renamed child.
470
    def test_move_directory_with_moved_children(self):
471
        tree = self.make_branch_and_tree('.')
472
        self.build_tree(['a/', 'a/b', 'a/c', 'd', 'e/'])
473
        tree.add(['a', 'a/b', 'a/c', 'd', 'e'],
474
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
475
        tree.commit('initial', rev_id='rev-1')
476
        root_id = tree.get_root_id()
477
478
        self.assertEqual([('a/b', 'b')],
479
                         tree.move(['a/b'], ''))
480
        self.assertTreeLayout([('', root_id),
481
                               ('a', 'a-id'),
482
                               ('b', 'b-id'),
483
                               ('d', 'd-id'),
484
                               ('e', 'e-id'),
485
                               ('a/c', 'c-id'),
486
                              ], tree)
487
        self.assertEqual([('d', 'a/d')],
488
                         tree.move(['d'], 'a'))
489
        self.assertTreeLayout([('', root_id),
490
                               ('a', 'a-id'),
491
                               ('b', 'b-id'),
492
                               ('e', 'e-id'),
493
                               ('a/c', 'c-id'),
494
                               ('a/d', 'd-id'),
495
                              ], tree)
496
        self.assertEqual([('a', 'e/a')],
497
                         tree.move(['a'], 'e'))
498
        self.assertTreeLayout([('', root_id),
499
                               ('b', 'b-id'),
500
                               ('e', 'e-id'),
501
                               ('e/a', 'a-id'),
502
                               ('e/a/c', 'c-id'),
503
                               ('e/a/d', 'd-id'),
504
                              ], tree)
505
        tree._validate()
506
2438.1.11 by John Arbash Meinel
Add a test for moving a directory with a renamed child.
507
    def test_move_directory_with_renamed_child(self):
508
        tree = self.make_branch_and_tree('.')
509
        self.build_tree(['a/', 'a/b', 'a/c', 'd/'])
510
        tree.add(['a', 'a/b', 'a/c', 'd'],
511
                 ['a-id', 'b-id', 'c-id', 'd-id'])
512
        tree.commit('initial', rev_id='rev-1')
513
        root_id = tree.get_root_id()
514
515
        tree.rename_one('a/b', 'a/d')
516
        self.assertTreeLayout([('', root_id),
517
                               ('a', 'a-id'),
518
                               ('d', 'd-id'),
519
                               ('a/c', 'c-id'),
520
                               ('a/d', 'b-id'),
521
                              ], tree)
522
        self.assertEqual([('a', 'd/a')],
523
                         tree.move(['a'], 'd'))
524
        self.assertTreeLayout([('', root_id),
525
                               ('d', 'd-id'),
526
                               ('d/a', 'a-id'),
527
                               ('d/a/c', 'c-id'),
528
                               ('d/a/d', 'b-id'),
529
                              ], tree)
530
        tree._validate()
531
2438.1.12 by John Arbash Meinel
Add a test with children that have been swapped
532
    def test_move_directory_with_swapped_children(self):
533
        tree = self.make_branch_and_tree('.')
534
        self.build_tree(['a/', 'a/b', 'a/c', 'a/d', 'e/'])
535
        tree.add(['a', 'a/b', 'a/c', 'a/d', 'e'],
536
                 ['a-id', 'b-id', 'c-id', 'd-id', 'e-id'])
537
        tree.commit('initial', rev_id='rev-1')
538
        root_id = tree.get_root_id()
539
540
        tree.rename_one('a/b', 'a/bb')
541
        tree.rename_one('a/d', 'a/b')
542
        tree.rename_one('a/bb', 'a/d')
543
        self.assertTreeLayout([('', root_id),
544
                               ('a', 'a-id'),
545
                               ('e', 'e-id'),
546
                               ('a/b', 'd-id'),
547
                               ('a/c', 'c-id'),
548
                               ('a/d', 'b-id'),
549
                              ], tree)
550
        self.assertEqual([('a', 'e/a')],
551
                         tree.move(['a'], 'e'))
552
        self.assertTreeLayout([('', root_id),
553
                               ('e', 'e-id'),
554
                               ('e/a', 'a-id'),
555
                               ('e/a/b', 'd-id'),
556
                               ('e/a/c', 'c-id'),
557
                               ('e/a/d', 'b-id'),
558
                              ], tree)
559
        tree._validate()
560
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
561
    def test_move_moved(self):
562
        """Moving a moved entry works as expected."""
563
        tree = self.make_branch_and_tree('.')
564
        self.build_tree(['a/', 'a/b', 'c/'])
565
        tree.add(['a', 'a/b', 'c'], ['a-id', 'b-id', 'c-id'])
566
        tree.commit('initial', rev_id='rev-1')
567
        root_id = tree.get_root_id()
568
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
569
        self.assertEqual([('a/b', 'c/b')],
570
            tree.move(['a/b'], 'c'))
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
571
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
572
                               ('c/b', 'b-id')], tree)
573
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
574
                               ('a/b', 'b-id')], tree.basis_tree())
575
2255.7.46 by Robert Collins
Fix WorkingTree4.move to return the moved paths, and update the tree implementation tests for move to check them.
576
        self.assertEqual([('c/b', 'b')],
577
            tree.move(['c/b'], ''))
2255.7.9 by John Arbash Meinel
Add more tests for WorkingTree.move() and a similar suite
578
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
579
                               ('c', 'c-id')], tree)
580
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
581
                               ('a/b', 'b-id')], tree.basis_tree())
2371.2.1 by John Arbash Meinel
Update DirState._validate() to detect rename errors.
582
        tree._validate()