~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_mv.py

  • Committer: Martin Pool
  • Date: 2007-04-04 06:17:31 UTC
  • mto: This revision was merged to the branch mainline in revision 2397.
  • Revision ID: mbp@sourcefrog.net-20070404061731-tt2xrzllqhbodn83
Contents of TODO file moved into bug tracker

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Test for 'bzr mv'"""
18
18
 
19
19
import os
20
20
 
21
 
import bzrlib.branch
22
21
from bzrlib import (
23
22
    osutils,
24
23
    workingtree,
26
25
 
27
26
from bzrlib.tests import (
28
27
    TestCaseWithTransport,
29
 
    )
30
 
from bzrlib.tests.features import (
31
 
    CaseInsensitiveFilesystemFeature,
32
 
    SymlinkFeature,
33
 
    UnicodeFilenameFeature,
 
28
    TestSkipped,
34
29
    )
35
30
 
36
31
 
37
32
class TestMove(TestCaseWithTransport):
38
33
 
 
34
    def assertInWorkingTree(self,path):
 
35
        tree = workingtree.WorkingTree.open('.')
 
36
        self.assertIsNot(tree.path2id(path), None,
 
37
            path+' not in working tree.')
 
38
 
 
39
    def assertNotInWorkingTree(self,path):
 
40
        tree = workingtree.WorkingTree.open('.')
 
41
        self.assertIs(tree.path2id(path), None, path+' in working tree.')
 
42
 
39
43
    def assertMoved(self,from_path,to_path):
40
44
        """Assert that to_path is existing and versioned but from_path not. """
41
 
        self.assertPathDoesNotExist(from_path)
 
45
        self.failIfExists(from_path)
42
46
        self.assertNotInWorkingTree(from_path)
43
47
 
44
 
        self.assertPathExists(to_path)
 
48
        self.failUnlessExists(to_path)
45
49
        self.assertInWorkingTree(to_path)
46
50
 
47
51
    def test_mv_modes(self):
50
54
        files = self.build_tree(['a', 'c', 'subdir/'])
51
55
        tree.add(['a', 'c', 'subdir'])
52
56
 
53
 
        self.run_bzr('mv a b')
 
57
        self.run_bzr('mv', 'a', 'b')
54
58
        self.assertMoved('a','b')
55
59
 
56
 
        self.run_bzr('mv b subdir')
 
60
        self.run_bzr('mv', 'b', 'subdir')
57
61
        self.assertMoved('b','subdir/b')
58
62
 
59
 
        self.run_bzr('mv subdir/b a')
 
63
        self.run_bzr('mv', 'subdir/b', 'a')
60
64
        self.assertMoved('subdir/b','a')
61
65
 
62
 
        self.run_bzr('mv a c subdir')
 
66
        self.run_bzr('mv', 'a', 'c', 'subdir')
63
67
        self.assertMoved('a','subdir/a')
64
68
        self.assertMoved('c','subdir/c')
65
69
 
66
 
        self.run_bzr('mv subdir/a subdir/newa')
 
70
        self.run_bzr('mv', 'subdir/a', 'subdir/newa')
67
71
        self.assertMoved('subdir/a','subdir/newa')
68
72
 
69
73
    def test_mv_unversioned(self):
70
74
        self.build_tree(['unversioned.txt'])
71
75
        self.run_bzr_error(
72
76
            ["^bzr: ERROR: Could not rename unversioned.txt => elsewhere."
73
 
             " .*unversioned.txt is not versioned\.$"],
74
 
            'mv unversioned.txt elsewhere')
 
77
             " .*unversioned.txt is not versioned$"],
 
78
            'mv', 'unversioned.txt', 'elsewhere')
75
79
 
76
80
    def test_mv_nonexisting(self):
77
81
        self.run_bzr_error(
78
82
            ["^bzr: ERROR: Could not rename doesnotexist => somewhereelse."
79
 
             " .*doesnotexist is not versioned\.$"],
80
 
            'mv doesnotexist somewhereelse')
 
83
             " .*doesnotexist is not versioned$"],
 
84
            'mv', 'doesnotexist', 'somewhereelse')
81
85
 
82
86
    def test_mv_unqualified(self):
83
87
        self.run_bzr_error(['^bzr: ERROR: missing file argument$'], 'mv')
84
 
 
 
88
        
85
89
    def test_mv_invalid(self):
86
90
        tree = self.make_branch_and_tree('.')
87
91
        self.build_tree(['test.txt', 'sub1/'])
88
92
        tree.add(['test.txt'])
89
93
 
90
94
        self.run_bzr_error(
91
 
            ["^bzr: ERROR: Could not move to sub1: sub1 is not versioned\.$"],
92
 
            'mv test.txt sub1')
 
95
            ["^bzr: ERROR: Could not move to sub1: sub1 is not versioned$"],
 
96
            'mv', 'test.txt', 'sub1')
93
97
 
94
98
        self.run_bzr_error(
95
99
            ["^bzr: ERROR: Could not move test.txt => .*hello.txt: "
96
 
             "sub1 is not versioned\.$"],
97
 
            'mv test.txt sub1/hello.txt')
98
 
 
 
100
             "sub1 is not versioned$"],
 
101
            'mv', 'test.txt', 'sub1/hello.txt')
 
102
        
99
103
    def test_mv_dirs(self):
100
104
        tree = self.make_branch_and_tree('.')
101
105
        self.build_tree(['hello.txt', 'sub1/'])
102
106
        tree.add(['hello.txt', 'sub1'])
103
107
 
104
 
        self.run_bzr('mv sub1 sub2')
 
108
        self.run_bzr('mv', 'sub1', 'sub2')
105
109
        self.assertMoved('sub1','sub2')
106
110
 
107
 
        self.run_bzr('mv hello.txt sub2')
 
111
        self.run_bzr('mv', 'hello.txt', 'sub2')
108
112
        self.assertMoved('hello.txt','sub2/hello.txt')
109
113
 
110
114
        self.build_tree(['sub1/'])
111
115
        tree.add(['sub1'])
112
 
        self.run_bzr('mv sub2/hello.txt sub1')
 
116
        self.run_bzr('mv', 'sub2/hello.txt', 'sub1')
113
117
        self.assertMoved('sub2/hello.txt','sub1/hello.txt')
114
118
 
115
 
        self.run_bzr('mv sub2 sub1')
 
119
        self.run_bzr('mv', 'sub2', 'sub1')
116
120
        self.assertMoved('sub2','sub1/sub2')
117
121
 
118
122
    def test_mv_relative(self):
121
125
        tree.add(['sub1', 'sub1/sub2', 'sub1/hello.txt'])
122
126
 
123
127
        os.chdir('sub1/sub2')
124
 
        self.run_bzr('mv ../hello.txt .')
125
 
        self.assertPathExists('./hello.txt')
 
128
        self.run_bzr('mv', '../hello.txt', '.')
 
129
        self.failUnlessExists('./hello.txt')
126
130
 
127
131
        os.chdir('..')
128
 
        self.run_bzr('mv sub2/hello.txt .')
 
132
        self.run_bzr('mv', 'sub2/hello.txt', '.')
129
133
        os.chdir('..')
130
134
        self.assertMoved('sub1/sub2/hello.txt','sub1/hello.txt')
131
135
 
132
 
    def test_mv_change_case_file(self):
133
 
        # test for bug #77740 (mv unable change filename case on Windows)
134
 
        tree = self.make_branch_and_tree('.')
135
 
        self.build_tree(['test.txt'])
136
 
        tree.add(['test.txt'])
137
 
        self.run_bzr('mv test.txt Test.txt')
138
 
        # we can't use failUnlessExists on case-insensitive filesystem
139
 
        # so try to check shape of the tree
140
 
        shape = sorted(os.listdir(u'.'))
141
 
        self.assertEqual(['.bzr', 'Test.txt'], shape)
142
 
        self.assertInWorkingTree('Test.txt')
143
 
        self.assertNotInWorkingTree('test.txt')
144
 
 
145
 
    def test_mv_change_case_dir(self):
146
 
        tree = self.make_branch_and_tree('.')
147
 
        self.build_tree(['foo/'])
148
 
        tree.add(['foo'])
149
 
        self.run_bzr('mv foo Foo')
150
 
        # we can't use failUnlessExists on case-insensitive filesystem
151
 
        # so try to check shape of the tree
152
 
        shape = sorted(os.listdir(u'.'))
153
 
        self.assertEqual(['.bzr', 'Foo'], shape)
154
 
        self.assertInWorkingTree('Foo')
155
 
        self.assertNotInWorkingTree('foo')
156
 
 
157
 
    def test_mv_change_case_dir_w_files(self):
158
 
        tree = self.make_branch_and_tree('.')
159
 
        self.build_tree(['foo/', 'foo/bar'])
160
 
        tree.add(['foo'])
161
 
        self.run_bzr('mv foo Foo')
162
 
        # we can't use failUnlessExists on case-insensitive filesystem
163
 
        # so try to check shape of the tree
164
 
        shape = sorted(os.listdir(u'.'))
165
 
        self.assertEqual(['.bzr', 'Foo'], shape)
166
 
        self.assertInWorkingTree('Foo')
167
 
        self.assertNotInWorkingTree('foo')
168
 
 
169
 
    def test_mv_file_to_wrong_case_dir(self):
170
 
        self.requireFeature(CaseInsensitiveFilesystemFeature)
171
 
        tree = self.make_branch_and_tree('.')
172
 
        self.build_tree(['foo/', 'bar'])
173
 
        tree.add(['foo', 'bar'])
174
 
        out, err = self.run_bzr('mv bar Foo', retcode=3)
175
 
        self.assertEquals('', out)
176
 
        self.assertEquals(
177
 
            'bzr: ERROR: Could not move to Foo: Foo is not versioned.\n',
178
 
            err)
179
 
 
180
136
    def test_mv_smoke_aliases(self):
181
137
        # just test that aliases for mv exist, if their behaviour is changed in
182
138
        # the future, then extend the tests.
184
140
        tree = self.make_branch_and_tree('.')
185
141
        tree.add(['a'])
186
142
 
187
 
        self.run_bzr('move a b')
188
 
        self.run_bzr('rename b a')
 
143
        self.run_bzr('move', 'a', 'b')
 
144
        self.run_bzr('rename', 'b', 'a')
189
145
 
190
146
    def test_mv_through_symlinks(self):
191
 
        self.requireFeature(SymlinkFeature)
 
147
        if not osutils.has_symlinks():
 
148
            raise TestSkipped('Symlinks are not supported on this platform')
192
149
        tree = self.make_branch_and_tree('.')
193
150
        self.build_tree(['a/', 'a/b'])
194
151
        os.symlink('a', 'c')
195
152
        os.symlink('.', 'd')
196
153
        tree.add(['a', 'a/b', 'c'], ['a-id', 'b-id', 'c-id'])
197
 
        self.run_bzr('mv c/b b')
 
154
        self.run_bzr('mv', 'c/b', 'b')
198
155
        tree = workingtree.WorkingTree.open('.')
199
156
        self.assertEqual('b-id', tree.path2id('b'))
200
157
 
211
168
        tree.add(['a'])
212
169
 
213
170
        osutils.rename('a', 'b')
214
 
        self.run_bzr('mv a b')
 
171
        self.run_bzr('mv', 'a', 'b')
215
172
        self.assertMoved('a','b')
216
173
 
217
174
    def test_mv_already_moved_file_to_versioned_target(self):
229
186
        os.remove('b')
230
187
        osutils.rename('a', 'b')
231
188
        self.run_bzr_error(
232
 
            ["^bzr: ERROR: Could not move a => b. b is already versioned\.$"],
233
 
            'mv a b')
 
189
            ["^bzr: ERROR: Could not move a => b. b is already versioned$"],
 
190
            'mv', 'a', 'b')
234
191
        #check that nothing changed
235
 
        self.assertPathDoesNotExist('a')
236
 
        self.assertPathExists('b')
 
192
        self.failIfExists('a')
 
193
        self.failUnlessExists('b')
237
194
 
238
195
    def test_mv_already_moved_file_into_subdir(self):
239
196
        """Test bzr mv original_file to versioned_directory/file.
248
205
        tree.add(['a', 'sub'])
249
206
 
250
207
        osutils.rename('a', 'sub/a')
251
 
        self.run_bzr('mv a sub/a')
 
208
        self.run_bzr('mv', 'a', 'sub/a')
252
209
        self.assertMoved('a','sub/a')
253
210
 
254
211
    def test_mv_already_moved_file_into_unversioned_subdir(self):
265
222
 
266
223
        osutils.rename('a', 'sub/a')
267
224
        self.run_bzr_error(
268
 
            ["^bzr: ERROR: Could not move a => a: sub is not versioned\.$"],
269
 
            'mv a sub/a')
270
 
        self.assertPathDoesNotExist('a')
271
 
        self.assertPathExists('sub/a')
 
225
            ["^bzr: ERROR: Could not move a => a: sub is not versioned$"],
 
226
            'mv', 'a', 'sub/a')
 
227
        self.failIfExists('a')
 
228
        self.failUnlessExists('sub/a')
272
229
 
273
230
    def test_mv_already_moved_files_into_subdir(self):
274
231
        """Test bzr mv original_files to versioned_directory.
283
240
        tree.add(['a1', 'a2', 'sub'])
284
241
 
285
242
        osutils.rename('a1', 'sub/a1')
286
 
        self.run_bzr('mv a1 a2 sub')
 
243
        self.run_bzr('mv', 'a1', 'a2', 'sub')
287
244
        self.assertMoved('a1','sub/a1')
288
245
        self.assertMoved('a2','sub/a2')
289
246
 
301
258
 
302
259
        osutils.rename('a1', 'sub/a1')
303
260
        self.run_bzr_error(
304
 
            ["^bzr: ERROR: Could not move to sub. sub is not versioned\.$"],
305
 
            'mv a1 a2 sub')
306
 
        self.assertPathDoesNotExist('a1')
307
 
        self.assertPathExists('sub/a1')
308
 
        self.assertPathExists('a2')
309
 
        self.assertPathDoesNotExist('sub/a2')
 
261
            ["^bzr: ERROR: Could not move to sub. sub is not versioned$"],
 
262
            'mv', 'a1', 'a2', 'sub')
 
263
        self.failIfExists('a1')
 
264
        self.failUnlessExists('sub/a1')
 
265
        self.failUnlessExists('a2')
 
266
        self.failIfExists('sub/a2')
310
267
 
311
268
    def test_mv_already_moved_file_forcing_after(self):
312
269
        """Test bzr mv versioned_file to unversioned_file.
325
282
        self.build_tree(['a']) #touch a
326
283
        self.run_bzr_error(
327
284
            ["^bzr: ERROR: Could not rename a => b because both files exist."
328
 
             " \(Use --after to tell bzr about a rename that has already"
329
 
             " happened\)$"],
330
 
            'mv a b')
331
 
        self.assertPathExists('a')
332
 
        self.assertPathExists('b')
 
285
             " \(Use --after to update the Bazaar id\)$"],
 
286
            'mv', 'a', 'b')
 
287
        self.failUnlessExists('a')
 
288
        self.failUnlessExists('b')
333
289
 
334
290
    def test_mv_already_moved_file_using_after(self):
335
291
        """Test bzr mv --after versioned_file to unversioned_file.
348
304
        osutils.rename('a', 'b')
349
305
        self.build_tree(['a']) #touch a
350
306
 
351
 
        self.run_bzr('mv a b --after')
352
 
        self.assertPathExists('a')
 
307
        self.run_bzr('mv', 'a', 'b', '--after')
 
308
        self.failUnlessExists('a')
353
309
        self.assertNotInWorkingTree('a')#a should be unknown now.
354
 
        self.assertPathExists('b')
 
310
        self.failUnlessExists('b')
355
311
        self.assertInWorkingTree('b')
356
312
 
357
313
    def test_mv_already_moved_files_forcing_after(self):
374
330
        self.build_tree(['a2']) #touch a2
375
331
 
376
332
        self.run_bzr_error(
377
 
            ["^bzr: ERROR: Could not rename a1 => sub/a1 because both files"
378
 
             " exist. \(Use --after to tell bzr about a rename that has already"
379
 
             " happened\)$"],
380
 
            'mv a1 a2 sub')
381
 
        self.assertPathExists('a1')
382
 
        self.assertPathExists('a2')
383
 
        self.assertPathExists('sub/a1')
384
 
        self.assertPathExists('sub/a2')
 
333
            ["^bzr: ERROR: Could not rename a1 => sub/a1 because both files exist."
 
334
             " \(Use --after to update the Bazaar id\)$"],
 
335
            'mv', 'a1', 'a2', 'sub')
 
336
        self.failUnlessExists('a1')
 
337
        self.failUnlessExists('a2')
 
338
        self.failUnlessExists('sub/a1')
 
339
        self.failUnlessExists('sub/a2')
385
340
 
386
341
    def test_mv_already_moved_files_using_after(self):
387
342
        """Test bzr mv --after versioned_file to directory/unversioned_file.
404
359
        self.build_tree(['a1']) #touch a1
405
360
        self.build_tree(['a2']) #touch a2
406
361
 
407
 
        self.run_bzr('mv a1 a2 sub --after')
408
 
        self.assertPathExists('a1')
409
 
        self.assertPathExists('a2')
410
 
        self.assertPathExists('sub/a1')
411
 
        self.assertPathExists('sub/a2')
 
362
        self.run_bzr('mv', 'a1', 'a2', 'sub', '--after')
 
363
        self.failUnlessExists('a1')
 
364
        self.failUnlessExists('a2')
 
365
        self.failUnlessExists('sub/a1')
 
366
        self.failUnlessExists('sub/a2')
412
367
        self.assertInWorkingTree('sub/a1')
413
368
        self.assertInWorkingTree('sub/a2')
414
 
 
415
 
    def test_mv_already_moved_directory(self):
416
 
        """Use `bzr mv a b` to mark a directory as renamed.
417
 
 
418
 
        https://bugs.launchpad.net/bzr/+bug/107967/
419
 
        """
420
 
        self.build_tree(['a/', 'c/'])
421
 
        tree = self.make_branch_and_tree('.')
422
 
        tree.add(['a', 'c'])
423
 
        osutils.rename('a', 'b')
424
 
        osutils.rename('c', 'd')
425
 
        # mv a b should work just like it does for already renamed files
426
 
        self.run_bzr('mv a b')
427
 
        self.assertPathDoesNotExist('a')
428
 
        self.assertNotInWorkingTree('a')
429
 
        self.assertPathExists('b')
430
 
        self.assertInWorkingTree('b')
431
 
        # and --after should work, too (technically it's ignored)
432
 
        self.run_bzr('mv --after c d')
433
 
        self.assertPathDoesNotExist('c')
434
 
        self.assertNotInWorkingTree('c')
435
 
        self.assertPathExists('d')
436
 
        self.assertInWorkingTree('d')
437
 
 
438
 
    def make_abcd_tree(self):
439
 
        tree = self.make_branch_and_tree('tree')
440
 
        self.build_tree(['tree/a', 'tree/c'])
441
 
        tree.add(['a', 'c'])
442
 
        tree.commit('record old names')
443
 
        osutils.rename('tree/a', 'tree/b')
444
 
        osutils.rename('tree/c', 'tree/d')
445
 
        return tree
446
 
 
447
 
    def test_mv_auto(self):
448
 
        self.make_abcd_tree()
449
 
        out, err = self.run_bzr('mv --auto', working_dir='tree')
450
 
        self.assertEqual(out, '')
451
 
        self.assertEqual(err, 'a => b\nc => d\n')
452
 
        tree = workingtree.WorkingTree.open('tree')
453
 
        self.assertIsNot(None, tree.path2id('b'))
454
 
        self.assertIsNot(None, tree.path2id('d'))
455
 
 
456
 
    def test_mv_auto_one_path(self):
457
 
        self.make_abcd_tree()
458
 
        out, err = self.run_bzr('mv --auto tree')
459
 
        self.assertEqual(out, '')
460
 
        self.assertEqual(err, 'a => b\nc => d\n')
461
 
        tree = workingtree.WorkingTree.open('tree')
462
 
        self.assertIsNot(None, tree.path2id('b'))
463
 
        self.assertIsNot(None, tree.path2id('d'))
464
 
 
465
 
    def test_mv_auto_two_paths(self):
466
 
        self.make_abcd_tree()
467
 
        out, err = self.run_bzr('mv --auto tree tree2', retcode=3)
468
 
        self.assertEqual('bzr: ERROR: Only one path may be specified to'
469
 
                         ' --auto.\n', err)
470
 
 
471
 
    def test_mv_auto_dry_run(self):
472
 
        self.make_abcd_tree()
473
 
        out, err = self.run_bzr('mv --auto --dry-run', working_dir='tree')
474
 
        self.assertEqual(out, '')
475
 
        self.assertEqual(err, 'a => b\nc => d\n')
476
 
        tree = workingtree.WorkingTree.open('tree')
477
 
        self.assertIsNot(None, tree.path2id('a'))
478
 
        self.assertIsNot(None, tree.path2id('c'))
479
 
 
480
 
    def test_mv_no_auto_dry_run(self):
481
 
        self.make_abcd_tree()
482
 
        out, err = self.run_bzr('mv c d --dry-run',
483
 
                                working_dir='tree', retcode=3)
484
 
        self.assertEqual('bzr: ERROR: --dry-run requires --auto.\n', err)
485
 
 
486
 
    def test_mv_auto_after(self):
487
 
        self.make_abcd_tree()
488
 
        out, err = self.run_bzr('mv --auto --after', working_dir='tree',
489
 
                                retcode=3)
490
 
        self.assertEqual('bzr: ERROR: --after cannot be specified with'
491
 
                         ' --auto.\n', err)
492
 
 
493
 
    def test_mv_quiet(self):
494
 
        tree = self.make_branch_and_tree('.')
495
 
        self.build_tree(['aaa'])
496
 
        tree.add(['aaa'])
497
 
        out, err = self.run_bzr('mv --quiet aaa bbb')
498
 
        self.assertEqual(out, '')
499
 
        self.assertEqual(err, '')
500
 
 
501
 
    def test_mv_readonly_lightweight_checkout(self):
502
 
        branch = self.make_branch('foo')
503
 
        branch = bzrlib.branch.Branch.open(self.get_readonly_url('foo'))
504
 
        tree = branch.create_checkout('tree', lightweight=True)
505
 
        self.build_tree(['tree/path'])
506
 
        tree.add('path')
507
 
        # If this fails, the tree is trying to acquire a branch lock, which it
508
 
        # shouldn't.
509
 
        self.run_bzr(['mv', 'tree/path', 'tree/path2'])
510
 
 
511
 
    def test_mv_unversioned_non_ascii(self):
512
 
        """Clear error on mv of an unversioned non-ascii file, see lp:707954"""
513
 
        self.requireFeature(UnicodeFilenameFeature)
514
 
        tree = self.make_branch_and_tree(".")
515
 
        self.build_tree([u"\xA7"])
516
 
        out, err = self.run_bzr_error(["Could not rename", "not versioned"],
517
 
            ["mv", u"\xA7", "b"])