27
from bzrlib.tests.matchers import HasLayout
27
28
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
29
from bzrlib.tests import (
30
34
class TestMove(TestCaseWithWorkingTree):
32
def get_tree_layout(self, tree):
33
"""Get the (path, file_id) pairs for the current tree."""
36
return [(path, ie.file_id) for path, ie
37
in tree.iter_entries_by_dir()]
41
36
def assertTreeLayout(self, expected, tree):
42
37
"""Check that the tree has the correct layout."""
43
actual = self.get_tree_layout(tree)
44
self.assertEqual(expected, actual)
38
self.assertThat(tree, HasLayout(expected))
46
40
def test_move_via_rm_and_add(self):
47
41
"""Move by remove and add-with-id"""
132
126
tree.move, ['d', 'c', 'b'], 'a')
133
127
if osutils.lexists('a/c'):
134
128
# If 'c' was actually moved, then 'd' should have also been moved
135
self.assertTreeLayout([('', root_id), ('a', 'a-id'),
129
self.assertTreeLayout([('', root_id), ('a/', 'a-id'),
136
130
('a/c', 'c-id'), ('a/d', 'd-id')], tree)
138
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
132
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c', 'c-id'),
139
133
('d', 'd-id')], tree)
140
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
134
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c', 'c-id'),
141
135
('d', 'd-id')], tree.basis_tree())
151
145
tree.remove(['a/b'], keep_files=False)
152
146
self.assertEqual([('b', 'a/b')], tree.move(['b'], 'a'))
153
147
self.assertTreeLayout([('', root_id),
162
156
tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
163
157
tree.commit('initial', rev_id='rev-1')
164
158
root_id = tree.get_root_id()
165
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
159
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
166
160
('b/c', 'c-id')], tree)
167
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
161
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
168
162
('b/c', 'c-id')], tree.basis_tree())
169
163
a_contents = tree.get_file_text('a-id')
170
164
self.assertEqual([('a', 'b/a')],
171
165
tree.move(['a'], 'b'))
172
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id'),
166
self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id'),
173
167
('b/c', 'c-id')], tree)
174
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
168
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
175
169
('b/c', 'c-id')], tree.basis_tree())
176
170
self.assertPathDoesNotExist('a')
177
171
self.assertFileEqual(a_contents, 'b/a')
186
180
c_contents = tree.get_file_text('c-id')
187
181
self.assertEqual([('b/c', 'c')],
188
182
tree.move(['b/c'], ''))
189
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
183
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
190
184
('c', 'c-id')], tree)
191
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
185
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
192
186
('b/c', 'c-id')], tree.basis_tree())
193
187
self.assertPathDoesNotExist('b/c')
194
188
self.assertFileEqual(c_contents, 'c')
206
200
# 'c' may or may not have been moved, but either way the tree should
207
201
# maintain a consistent state.
208
202
if osutils.lexists('c'):
209
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
203
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
210
204
('c', 'c-id')], tree)
212
206
self.assertPathExists('b/c')
213
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
207
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
214
208
('b/c', 'c-id')], tree)
215
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
209
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
216
210
('c', 'c-id')], tree.basis_tree())
244
238
root_id = tree.get_root_id()
245
239
os.rename('a', 'b/a')
247
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
241
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
249
243
# We don't need after=True as long as source is missing and target
251
245
self.assertEqual([('a', 'b/a')],
252
246
tree.move(['a'], 'b'))
253
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
247
self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
255
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
249
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
256
250
tree.basis_tree())
264
258
root_id = tree.get_root_id()
265
259
os.rename('a', 'b/a')
267
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
261
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
269
263
# Passing after=True should work as well
270
264
self.assertEqual([('a', 'b/a')],
271
265
tree.move(['a'], 'b', after=True))
272
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
266
self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
274
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
268
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
275
269
tree.basis_tree())
285
279
# Passing after when the file hasn't been move raises an exception
286
280
self.assertRaises(errors.BzrMoveFailedError,
287
281
tree.move, ['a'], 'b', after=True)
288
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
282
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
289
283
tree.basis_tree())
312
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
306
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
314
308
self.assertRaises(errors.RenameFailedFilesExist,
315
309
tree.move, ['a'], 'b', after=False)
316
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
310
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
318
312
self.assertFileEqual(a_text, 'a')
319
313
self.assertFileEqual(ba_text, 'b/a')
320
314
# But you can pass after=True
321
315
self.assertEqual([('a', 'b/a')],
322
316
tree.move(['a'], 'b', after=True))
323
self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/a', 'a-id')],
317
self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/a', 'a-id')],
325
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
319
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
326
320
tree.basis_tree())
327
321
# But it shouldn't actually move anything
328
322
self.assertFileEqual(a_text, 'a')
340
334
self.assertEqual([('a', 'e/a')],
341
335
tree.move(['a'], 'e'))
342
self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/a', 'a-id'),
343
('e/a/b', 'b-id'), ('e/a/c', 'c-id'),
336
self.assertTreeLayout([('', root_id), ('e/', 'e-id'), ('e/a/', 'a-id'),
337
('e/a/b', 'b-id'), ('e/a/c/', 'c-id'),
344
338
('e/a/c/d', 'd-id')], tree)
345
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
346
('a/b', 'b-id'), ('a/c', 'c-id'),
339
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('e/', 'e-id'),
340
('a/b', 'b-id'), ('a/c/', 'c-id'),
347
341
('a/c/d', 'd-id')], tree.basis_tree())
350
344
def test_move_directory_into_parent(self):
345
if not self.workingtree_format.supports_versioned_directories:
346
raise tests.TestNotApplicable(
347
"test requires versioned directories")
351
348
tree = self.make_branch_and_tree('.')
352
349
self.build_tree(['c/', 'c/b/', 'c/b/d/'])
353
350
tree.add(['c', 'c/b', 'c/b/d'],
372
369
tree.commit('initial', rev_id='rev-1')
373
370
root_id = tree.get_root_id()
376
372
tree.rename_one('a/b', 'a/c/b')
377
373
self.assertTreeLayout([('', root_id),
381
377
('a/c/b', 'b-id'),
383
379
self.assertEqual([('a', 'd/a')],
384
380
tree.move(['a'], 'd'))
385
381
self.assertTreeLayout([('', root_id),
389
385
('d/a/c/b', 'b-id'),
441
437
self.assertEqual([('a/b', 'b')],
442
438
tree.move(['a/b'], ''))
443
439
self.assertTreeLayout([('', root_id),
450
446
self.assertEqual([('d', 'a/d')],
451
447
tree.move(['d'], 'a'))
452
448
self.assertTreeLayout([('', root_id),
478
474
tree.rename_one('a/b', 'a/d')
479
475
self.assertTreeLayout([('', root_id),
485
481
self.assertEqual([('a', 'd/a')],
486
482
tree.move(['a'], 'd'))
487
483
self.assertTreeLayout([('', root_id),
490
486
('d/a/c', 'c-id'),
491
487
('d/a/d', 'b-id'),
532
528
self.assertEqual([('a/b', 'c/b')],
533
529
tree.move(['a/b'], 'c'))
534
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
530
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
535
531
('c/b', 'b-id')], tree)
536
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
532
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
537
533
('a/b', 'b-id')], tree.basis_tree())
539
535
self.assertEqual([('c/b', 'b')],
540
536
tree.move(['c/b'], ''))
541
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
542
('c', 'c-id')], tree)
543
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
537
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('b', 'b-id'),
538
('c/', 'c-id')], tree)
539
self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
544
540
('a/b', 'b-id')], tree.basis_tree())
547
543
def test_move_to_unversioned_non_ascii_dir(self):
548
544
"""Check error when moving to unversioned non-ascii directory"""
549
self.requireFeature(tests.UnicodeFilename)
545
self.requireFeature(features.UnicodeFilenameFeature)
550
546
tree = self.make_branch_and_tree(".")
551
547
self.build_tree(["a", u"\xA7/"])
558
554
def test_move_unversioned_non_ascii(self):
559
555
"""Check error when moving an unversioned non-ascii file"""
560
self.requireFeature(tests.UnicodeFilename)
556
self.requireFeature(features.UnicodeFilenameFeature)
561
557
tree = self.make_branch_and_tree(".")
562
558
self.build_tree([u"\xA7", "dir/"])