~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_workingtree/test_rename_one.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
    osutils,
24
24
    tests,
25
25
    )
 
26
from bzrlib.tests import (
 
27
    features,
 
28
    )
 
29
from bzrlib.tests.matchers import HasLayout
26
30
 
27
31
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
28
32
 
29
33
 
30
34
class TestRenameOne(TestCaseWithWorkingTree):
31
35
 
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
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))
45
39
 
46
40
    def test_rename_one_target_not_dir(self):
47
41
        tree = self.make_branch_and_tree('.')
87
81
 
88
82
        a_contents = tree.get_file_text('a-id')
89
83
        tree.rename_one('a', 'foo')
90
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('foo', 'a-id')],
 
84
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('foo', 'a-id')],
91
85
                              tree)
92
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
86
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
93
87
                              tree.basis_tree())
94
 
        self.failIfExists('a')
 
88
        self.assertPathDoesNotExist('a')
95
89
        self.assertFileEqual(a_contents, 'foo')
96
90
 
97
91
    def test_rename_one_not_localdir(self):
103
97
 
104
98
        a_contents = tree.get_file_text('a-id')
105
99
        tree.rename_one('a', 'b/foo')
106
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/foo', 'a-id')],
 
100
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/foo', 'a-id')],
107
101
                              tree)
108
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
102
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
109
103
                              tree.basis_tree())
110
 
        self.failIfExists('tree/a')
 
104
        self.assertPathDoesNotExist('tree/a')
111
105
        self.assertFileEqual(a_contents, 'tree/b/foo')
112
106
 
113
107
    def test_rename_one_subdir(self):
116
110
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
117
111
        tree.commit('initial', rev_id='rev-1')
118
112
        root_id = tree.get_root_id()
119
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
113
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
120
114
                               ('b/c', 'c-id')], tree)
121
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
115
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
122
116
                               ('b/c', 'c-id')], tree.basis_tree())
123
117
        a_contents = tree.get_file_text('a-id')
124
118
        tree.rename_one('a', 'b/d')
125
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'), ('b/c', 'c-id'),
 
119
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'), ('b/c', 'c-id'),
126
120
                               ('b/d', 'a-id')], tree)
127
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
121
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
128
122
                               ('b/c', 'c-id')], tree.basis_tree())
129
 
        self.failIfExists('a')
 
123
        self.assertPathDoesNotExist('a')
130
124
        self.assertFileEqual(a_contents, 'b/d')
131
125
 
132
126
    def test_rename_one_parent_dir(self):
137
131
        root_id = tree.get_root_id()
138
132
        c_contents = tree.get_file_text('c-id')
139
133
        tree.rename_one('b/c', 'd')
140
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
134
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
141
135
                               ('d', 'c-id')], tree)
142
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
136
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
143
137
                               ('b/c', 'c-id')], tree.basis_tree())
144
 
        self.failIfExists('b/c')
 
138
        self.assertPathDoesNotExist('b/c')
145
139
        self.assertFileEqual(c_contents, 'd')
146
140
 
147
141
    def test_rename_one_fail_consistent(self):
153
147
        # Target already exists
154
148
        self.assertRaises(errors.RenameFailedFilesExist,
155
149
                          tree.rename_one, 'a', 'b/a')
156
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
150
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
157
151
                               ('c', 'c-id')], tree)
158
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id'),
 
152
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id'),
159
153
                               ('c', 'c-id')], tree.basis_tree())
160
154
 
161
155
    def test_rename_one_onto_existing(self):
193
187
        root_id = tree.get_root_id()
194
188
        os.rename('a', 'b/foo')
195
189
 
196
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
190
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
197
191
                              tree)
198
192
        # We don't need after=True as long as source is missing and target
199
193
        # exists.
200
194
        tree.rename_one('a', 'b/foo')
201
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
 
195
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
202
196
                               ('b/foo', 'a-id')], tree)
203
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
197
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
204
198
                              tree.basis_tree())
205
199
 
206
200
    def test_rename_one_after_with_after(self):
211
205
        root_id = tree.get_root_id()
212
206
        os.rename('a', 'b/foo')
213
207
 
214
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
208
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
215
209
                              tree)
216
210
        # Passing after=True should work as well
217
211
        tree.rename_one('a', 'b/foo', after=True)
218
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
 
212
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
219
213
                               ('b/foo', 'a-id')], tree)
220
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
214
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
221
215
                              tree.basis_tree())
222
216
 
 
217
    def test_rename_one_after_dest_versioned(self):
 
218
        tree = self.make_branch_and_tree('.')
 
219
        self.build_tree(['a'])
 
220
        tree.add(['a'], ['a-id'])
 
221
        tree.commit('initial', rev_id='rev-1')
 
222
        root_id = tree.get_root_id()
 
223
        os.rename('a', 'b')
 
224
        tree.add(['b'], ['b-id'])
 
225
 
 
226
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
227
                               tree)
 
228
        e = self.assertRaises(errors.BzrMoveFailedError,
 
229
            tree.rename_one, 'a', 'b')
 
230
        self.assertIsInstance(e.extra, errors.AlreadyVersionedError)
 
231
 
 
232
    def test_rename_one_after_with_after_dest_versioned(self):
 
233
        ''' using after with an already versioned file should fail '''
 
234
        tree = self.make_branch_and_tree('.')
 
235
        self.build_tree(['a', 'b'])
 
236
        tree.add(['a', 'b'], ['a-id', 'b-id'])
 
237
        tree.commit('initial', rev_id='rev-1')
 
238
        root_id = tree.get_root_id()
 
239
        os.unlink('a')
 
240
 
 
241
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
242
                               tree)
 
243
        e = self.assertRaises(errors.BzrMoveFailedError,
 
244
            tree.rename_one, 'a', 'b', after=True)
 
245
        self.assertIsInstance(e.extra, errors.AlreadyVersionedError)
 
246
 
 
247
    def test_rename_one_after_with_after_dest_added(self):
 
248
        ''' using after with a newly added file should work '''
 
249
        tree = self.make_branch_and_tree('.')
 
250
        self.build_tree(['a'])
 
251
        tree.add(['a'], ['a-id'])
 
252
        tree.commit('initial', rev_id='rev-1')
 
253
        root_id = tree.get_root_id()
 
254
        os.rename('a', 'b')
 
255
        tree.add(['b'], ['b-id'])
 
256
 
 
257
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
258
                               tree)
 
259
        tree.rename_one('a', 'b', after=True)
 
260
        self.assertTreeLayout([('', root_id), ('b', 'a-id')], tree)
 
261
 
223
262
    def test_rename_one_after_source_removed(self):
224
 
        """Rename even if the source was removed from the inventory already"""
 
263
        """Rename even if the source was already unversioned."""
225
264
        tree = self.make_branch_and_tree('.')
226
265
        self.build_tree(['a', 'b/'])
227
266
        tree.add(['a', 'b'], ['a-id', 'b-id'])
230
269
        os.rename('a', 'b/foo')
231
270
        tree.remove(['a'])
232
271
 
233
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id')], tree)
 
272
        self.assertTreeLayout([('', root_id), ('b/', 'b-id')], tree)
234
273
        # We don't need after=True as long as source is missing and target
235
274
        # exists.
236
275
        tree.rename_one('a', 'b/foo')
237
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
 
276
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
238
277
                               ('b/foo', 'a-id')], tree)
239
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
278
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
240
279
                              tree.basis_tree())
241
280
 
242
281
    def test_rename_one_after_no_target(self):
249
288
        # Passing after when the file hasn't been rename_one raises an exception
250
289
        self.assertRaises(errors.BzrMoveFailedError,
251
290
                          tree.rename_one, 'a', 'b/foo', after=True)
252
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
291
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
253
292
                              tree)
254
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
293
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
255
294
                              tree.basis_tree())
256
295
 
257
296
    def test_rename_one_after_source_and_dest(self):
274
313
        finally:
275
314
            foo_file.close()
276
315
 
277
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
316
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
278
317
                              tree)
279
318
        self.assertRaises(errors.RenameFailedFilesExist,
280
319
                          tree.rename_one, 'a', 'b/foo', after=False)
281
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
320
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
282
321
                              tree)
283
322
        self.assertFileEqual(a_text, 'a')
284
323
        self.assertFileEqual(foo_text, 'b/foo')
285
324
        # But you can pass after=True
286
325
        tree.rename_one('a', 'b/foo', after=True)
287
 
        self.assertTreeLayout([('', root_id), ('b', 'b-id'),
 
326
        self.assertTreeLayout([('', root_id), ('b/', 'b-id'),
288
327
                               ('b/foo', 'a-id')], tree)
289
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b', 'b-id')],
 
328
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('b/', 'b-id')],
290
329
                              tree.basis_tree())
291
330
        # But it shouldn't actually move anything
292
331
        self.assertFileEqual(a_text, 'a')
301
340
        root_id = tree.get_root_id()
302
341
 
303
342
        tree.rename_one('a', 'e/f')
304
 
        self.assertTreeLayout([('', root_id), ('e', 'e-id'), ('e/f', 'a-id'),
305
 
                               ('e/f/b', 'b-id'), ('e/f/c', 'c-id'),
 
343
        self.assertTreeLayout([('', root_id), ('e/', 'e-id'), ('e/f/', 'a-id'),
 
344
                               ('e/f/b', 'b-id'), ('e/f/c/', 'c-id'),
306
345
                               ('e/f/c/d', 'd-id')], tree)
307
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('e', 'e-id'),
308
 
                               ('a/b', 'b-id'), ('a/c', 'c-id'),
 
346
        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('e/', 'e-id'),
 
347
                               ('a/b', 'b-id'), ('a/c/', 'c-id'),
309
348
                               ('a/c/d', 'd-id')], tree.basis_tree())
310
349
 
311
350
    def test_rename_one_moved(self):
317
356
        root_id = tree.get_root_id()
318
357
 
319
358
        tree.rename_one('a/b', 'c/foo')
320
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
359
        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
321
360
                               ('c/foo', 'b-id')], tree)
322
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
361
        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
323
362
                               ('a/b', 'b-id')], tree.basis_tree())
324
363
 
325
364
        tree.rename_one('c/foo', 'bar')
326
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('bar', 'b-id'),
327
 
                               ('c', 'c-id')], tree)
328
 
        self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
 
365
        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('bar', 'b-id'),
 
366
                               ('c/', 'c-id')], tree)
 
367
        self.assertTreeLayout([('', root_id), ('a/', 'a-id'), ('c/', 'c-id'),
329
368
                               ('a/b', 'b-id')], tree.basis_tree())
330
369
 
331
370
    def test_rename_to_denormalised_fails(self):
336
375
        tree.add(['a'])
337
376
        self.assertRaises((errors.InvalidNormalization, UnicodeEncodeError),
338
377
            tree.rename_one, 'a', u'ba\u030arry')
 
378
 
 
379
    def test_rename_unversioned_non_ascii(self):
 
380
        """Check error when renaming an unversioned non-ascii file"""
 
381
        self.requireFeature(features.UnicodeFilenameFeature)
 
382
        tree = self.make_branch_and_tree(".")
 
383
        self.build_tree([u"\xA7"])
 
384
        e = self.assertRaises(errors.BzrRenameFailedError,
 
385
            tree.rename_one, u"\xA7", "b")
 
386
        self.assertIsInstance(e.extra, errors.NotVersionedError)
 
387
        self.assertEqual(e.extra.path, u"\xA7")
 
388
 
 
389
    def test_rename_into_unversioned_non_ascii_dir(self):
 
390
        """Check error when renaming into unversioned non-ascii directory"""
 
391
        self.requireFeature(features.UnicodeFilenameFeature)
 
392
        tree = self.make_branch_and_tree(".")
 
393
        self.build_tree(["a", u"\xA7/"])
 
394
        tree.add(["a"])
 
395
        e = self.assertRaises(errors.BzrMoveFailedError,
 
396
            tree.rename_one, "a", u"\xA7/a")
 
397
        self.assertIsInstance(e.extra, errors.NotVersionedError)
 
398
        self.assertEqual(e.extra.path, u"\xA7")
 
399
 
 
400
    def test_rename_over_already_versioned_non_ascii(self):
 
401
        """Check error renaming over an already versioned non-ascii file"""
 
402
        self.requireFeature(features.UnicodeFilenameFeature)
 
403
        tree = self.make_branch_and_tree(".")
 
404
        self.build_tree(["a", u"\xA7"])
 
405
        tree.add(["a", u"\xA7"])
 
406
        e = self.assertRaises(errors.BzrMoveFailedError,
 
407
            tree.rename_one, "a", u"\xA7")
 
408
        self.assertIsInstance(e.extra, errors.AlreadyVersionedError)
 
409
        self.assertEqual(e.extra.path, u"\xA7")
 
410
 
 
411
    def test_rename_after_non_existant_non_ascii(self):
 
412
        """Check error renaming after move with missing non-ascii file"""
 
413
        self.requireFeature(features.UnicodeFilenameFeature)
 
414
        tree = self.make_branch_and_tree(".")
 
415
        self.build_tree(["a"])
 
416
        tree.add(["a"])
 
417
        e = self.assertRaises(errors.BzrMoveFailedError,
 
418
            tree.rename_one, "a", u"\xA7", after=True)
 
419
        self.assertIsInstance(e.extra, errors.NoSuchFile)
 
420
        self.assertEqual(e.extra.path, u"\xA7")