~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-10-31 04:39:04 UTC
  • mfrom: (3565.6.16 switch_nick)
  • Revision ID: pqm@pqm.ubuntu.com-20081031043904-52fnbfrloojemvcc
(mbp) branch nickname documentation

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 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
"""Test for 'bzr mv'"""
 
18
 
 
19
import os
 
20
 
 
21
from bzrlib import (
 
22
    osutils,
 
23
    workingtree,
 
24
    )
 
25
 
 
26
from bzrlib.tests import (
 
27
    CaseInsensitiveFilesystemFeature,
 
28
    SymlinkFeature,
 
29
    TestCaseWithTransport,
 
30
    )
 
31
 
 
32
 
 
33
class TestMove(TestCaseWithTransport):
 
34
 
 
35
    def assertMoved(self,from_path,to_path):
 
36
        """Assert that to_path is existing and versioned but from_path not. """
 
37
        self.failIfExists(from_path)
 
38
        self.assertNotInWorkingTree(from_path)
 
39
 
 
40
        self.failUnlessExists(to_path)
 
41
        self.assertInWorkingTree(to_path)
 
42
 
 
43
    def test_mv_modes(self):
 
44
        """Test two modes of operation for mv"""
 
45
        tree = self.make_branch_and_tree('.')
 
46
        files = self.build_tree(['a', 'c', 'subdir/'])
 
47
        tree.add(['a', 'c', 'subdir'])
 
48
 
 
49
        self.run_bzr('mv a b')
 
50
        self.assertMoved('a','b')
 
51
 
 
52
        self.run_bzr('mv b subdir')
 
53
        self.assertMoved('b','subdir/b')
 
54
 
 
55
        self.run_bzr('mv subdir/b a')
 
56
        self.assertMoved('subdir/b','a')
 
57
 
 
58
        self.run_bzr('mv a c subdir')
 
59
        self.assertMoved('a','subdir/a')
 
60
        self.assertMoved('c','subdir/c')
 
61
 
 
62
        self.run_bzr('mv subdir/a subdir/newa')
 
63
        self.assertMoved('subdir/a','subdir/newa')
 
64
 
 
65
    def test_mv_unversioned(self):
 
66
        self.build_tree(['unversioned.txt'])
 
67
        self.run_bzr_error(
 
68
            ["^bzr: ERROR: Could not rename unversioned.txt => elsewhere."
 
69
             " .*unversioned.txt is not versioned\.$"],
 
70
            'mv unversioned.txt elsewhere')
 
71
 
 
72
    def test_mv_nonexisting(self):
 
73
        self.run_bzr_error(
 
74
            ["^bzr: ERROR: Could not rename doesnotexist => somewhereelse."
 
75
             " .*doesnotexist is not versioned\.$"],
 
76
            'mv doesnotexist somewhereelse')
 
77
 
 
78
    def test_mv_unqualified(self):
 
79
        self.run_bzr_error(['^bzr: ERROR: missing file argument$'], 'mv')
 
80
        
 
81
    def test_mv_invalid(self):
 
82
        tree = self.make_branch_and_tree('.')
 
83
        self.build_tree(['test.txt', 'sub1/'])
 
84
        tree.add(['test.txt'])
 
85
 
 
86
        self.run_bzr_error(
 
87
            ["^bzr: ERROR: Could not move to sub1: sub1 is not versioned\.$"],
 
88
            'mv test.txt sub1')
 
89
 
 
90
        self.run_bzr_error(
 
91
            ["^bzr: ERROR: Could not move test.txt => .*hello.txt: "
 
92
             "sub1 is not versioned\.$"],
 
93
            'mv test.txt sub1/hello.txt')
 
94
        
 
95
    def test_mv_dirs(self):
 
96
        tree = self.make_branch_and_tree('.')
 
97
        self.build_tree(['hello.txt', 'sub1/'])
 
98
        tree.add(['hello.txt', 'sub1'])
 
99
 
 
100
        self.run_bzr('mv sub1 sub2')
 
101
        self.assertMoved('sub1','sub2')
 
102
 
 
103
        self.run_bzr('mv hello.txt sub2')
 
104
        self.assertMoved('hello.txt','sub2/hello.txt')
 
105
 
 
106
        self.build_tree(['sub1/'])
 
107
        tree.add(['sub1'])
 
108
        self.run_bzr('mv sub2/hello.txt sub1')
 
109
        self.assertMoved('sub2/hello.txt','sub1/hello.txt')
 
110
 
 
111
        self.run_bzr('mv sub2 sub1')
 
112
        self.assertMoved('sub2','sub1/sub2')
 
113
 
 
114
    def test_mv_relative(self):
 
115
        self.build_tree(['sub1/', 'sub1/sub2/', 'sub1/hello.txt'])
 
116
        tree = self.make_branch_and_tree('.')
 
117
        tree.add(['sub1', 'sub1/sub2', 'sub1/hello.txt'])
 
118
 
 
119
        os.chdir('sub1/sub2')
 
120
        self.run_bzr('mv ../hello.txt .')
 
121
        self.failUnlessExists('./hello.txt')
 
122
 
 
123
        os.chdir('..')
 
124
        self.run_bzr('mv sub2/hello.txt .')
 
125
        os.chdir('..')
 
126
        self.assertMoved('sub1/sub2/hello.txt','sub1/hello.txt')
 
127
 
 
128
    def test_mv_change_case_file(self):
 
129
        # test for bug #77740 (mv unable change filename case on Windows)
 
130
        tree = self.make_branch_and_tree('.')
 
131
        self.build_tree(['test.txt'])
 
132
        tree.add(['test.txt'])
 
133
        self.run_bzr('mv test.txt Test.txt')
 
134
        # we can't use failUnlessExists on case-insensitive filesystem
 
135
        # so try to check shape of the tree
 
136
        shape = sorted(os.listdir(u'.'))
 
137
        self.assertEqual(['.bzr', 'Test.txt'], shape)
 
138
        self.assertInWorkingTree('Test.txt')
 
139
        self.assertNotInWorkingTree('test.txt')
 
140
 
 
141
    def test_mv_change_case_dir(self):
 
142
        tree = self.make_branch_and_tree('.')
 
143
        self.build_tree(['foo/'])
 
144
        tree.add(['foo'])
 
145
        self.run_bzr('mv foo Foo')
 
146
        # we can't use failUnlessExists on case-insensitive filesystem
 
147
        # so try to check shape of the tree
 
148
        shape = sorted(os.listdir(u'.'))
 
149
        self.assertEqual(['.bzr', 'Foo'], shape)
 
150
        self.assertInWorkingTree('Foo')
 
151
        self.assertNotInWorkingTree('foo')
 
152
 
 
153
    def test_mv_change_case_dir_w_files(self):
 
154
        tree = self.make_branch_and_tree('.')
 
155
        self.build_tree(['foo/', 'foo/bar'])
 
156
        tree.add(['foo'])
 
157
        self.run_bzr('mv foo Foo')
 
158
        # we can't use failUnlessExists on case-insensitive filesystem
 
159
        # so try to check shape of the tree
 
160
        shape = sorted(os.listdir(u'.'))
 
161
        self.assertEqual(['.bzr', 'Foo'], shape)
 
162
        self.assertInWorkingTree('Foo')
 
163
        self.assertNotInWorkingTree('foo')
 
164
 
 
165
    def test_mv_file_to_wrong_case_dir(self):
 
166
        self.requireFeature(CaseInsensitiveFilesystemFeature)
 
167
        tree = self.make_branch_and_tree('.')
 
168
        self.build_tree(['foo/', 'bar'])
 
169
        tree.add(['foo', 'bar'])
 
170
        out, err = self.run_bzr('mv bar Foo', retcode=3)
 
171
        self.assertEquals('', out)
 
172
        self.assertEquals(
 
173
            'bzr: ERROR: Could not move to Foo: Foo is not versioned.\n',
 
174
            err)
 
175
 
 
176
    def test_mv_smoke_aliases(self):
 
177
        # just test that aliases for mv exist, if their behaviour is changed in
 
178
        # the future, then extend the tests.
 
179
        self.build_tree(['a'])
 
180
        tree = self.make_branch_and_tree('.')
 
181
        tree.add(['a'])
 
182
 
 
183
        self.run_bzr('move a b')
 
184
        self.run_bzr('rename b a')
 
185
 
 
186
    def test_mv_through_symlinks(self):
 
187
        self.requireFeature(SymlinkFeature)
 
188
        tree = self.make_branch_and_tree('.')
 
189
        self.build_tree(['a/', 'a/b'])
 
190
        os.symlink('a', 'c')
 
191
        os.symlink('.', 'd')
 
192
        tree.add(['a', 'a/b', 'c'], ['a-id', 'b-id', 'c-id'])
 
193
        self.run_bzr('mv c/b b')
 
194
        tree = workingtree.WorkingTree.open('.')
 
195
        self.assertEqual('b-id', tree.path2id('b'))
 
196
 
 
197
    def test_mv_already_moved_file(self):
 
198
        """Test bzr mv original_file to moved_file.
 
199
 
 
200
        Tests if a file which has allready been moved by an external tool,
 
201
        is handled correctly by bzr mv.
 
202
        Setup: a is in the working tree, b does not exist.
 
203
        User does: mv a b; bzr mv a b
 
204
        """
 
205
        self.build_tree(['a'])
 
206
        tree = self.make_branch_and_tree('.')
 
207
        tree.add(['a'])
 
208
 
 
209
        osutils.rename('a', 'b')
 
210
        self.run_bzr('mv a b')
 
211
        self.assertMoved('a','b')
 
212
 
 
213
    def test_mv_already_moved_file_to_versioned_target(self):
 
214
        """Test bzr mv existing_file to versioned_file.
 
215
 
 
216
        Tests if an attempt to move an existing versioned file
 
217
        to another versiond file will fail.
 
218
        Setup: a and b are in the working tree.
 
219
        User does: rm b; mv a b; bzr mv a b
 
220
        """
 
221
        self.build_tree(['a', 'b'])
 
222
        tree = self.make_branch_and_tree('.')
 
223
        tree.add(['a', 'b'])
 
224
 
 
225
        os.remove('b')
 
226
        osutils.rename('a', 'b')
 
227
        self.run_bzr_error(
 
228
            ["^bzr: ERROR: Could not move a => b. b is already versioned\.$"],
 
229
            'mv a b')
 
230
        #check that nothing changed
 
231
        self.failIfExists('a')
 
232
        self.failUnlessExists('b')
 
233
 
 
234
    def test_mv_already_moved_file_into_subdir(self):
 
235
        """Test bzr mv original_file to versioned_directory/file.
 
236
 
 
237
        Tests if a file which has already been moved into a versioned
 
238
        directory by an external tool, is handled correctly by bzr mv.
 
239
        Setup: a and sub/ are in the working tree.
 
240
        User does: mv a sub/a; bzr mv a sub/a
 
241
        """
 
242
        self.build_tree(['a', 'sub/'])
 
243
        tree = self.make_branch_and_tree('.')
 
244
        tree.add(['a', 'sub'])
 
245
 
 
246
        osutils.rename('a', 'sub/a')
 
247
        self.run_bzr('mv a sub/a')
 
248
        self.assertMoved('a','sub/a')
 
249
 
 
250
    def test_mv_already_moved_file_into_unversioned_subdir(self):
 
251
        """Test bzr mv original_file to unversioned_directory/file.
 
252
 
 
253
        Tests if an attempt to move an existing versioned file
 
254
        into an unversioned directory will fail.
 
255
        Setup: a is in the working tree, sub/ is not.
 
256
        User does: mv a sub/a; bzr mv a sub/a
 
257
        """
 
258
        self.build_tree(['a', 'sub/'])
 
259
        tree = self.make_branch_and_tree('.')
 
260
        tree.add(['a'])
 
261
 
 
262
        osutils.rename('a', 'sub/a')
 
263
        self.run_bzr_error(
 
264
            ["^bzr: ERROR: Could not move a => a: sub is not versioned\.$"],
 
265
            'mv a sub/a')
 
266
        self.failIfExists('a')
 
267
        self.failUnlessExists('sub/a')
 
268
 
 
269
    def test_mv_already_moved_files_into_subdir(self):
 
270
        """Test bzr mv original_files to versioned_directory.
 
271
 
 
272
        Tests if files which has already been moved into a versioned
 
273
        directory by an external tool, is handled correctly by bzr mv.
 
274
        Setup: a1, a2, sub are in the working tree.
 
275
        User does: mv a1 sub/.; bzr mv a1 a2 sub
 
276
        """
 
277
        self.build_tree(['a1', 'a2', 'sub/'])
 
278
        tree = self.make_branch_and_tree('.')
 
279
        tree.add(['a1', 'a2', 'sub'])
 
280
 
 
281
        osutils.rename('a1', 'sub/a1')
 
282
        self.run_bzr('mv a1 a2 sub')
 
283
        self.assertMoved('a1','sub/a1')
 
284
        self.assertMoved('a2','sub/a2')
 
285
 
 
286
    def test_mv_already_moved_files_into_unversioned_subdir(self):
 
287
        """Test bzr mv original_file to unversioned_directory.
 
288
 
 
289
        Tests if an attempt to move existing versioned file
 
290
        into an unversioned directory will fail.
 
291
        Setup: a1, a2 are in the working tree, sub is not.
 
292
        User does: mv a1 sub/.; bzr mv a1 a2 sub
 
293
        """
 
294
        self.build_tree(['a1', 'a2', 'sub/'])
 
295
        tree = self.make_branch_and_tree('.')
 
296
        tree.add(['a1', 'a2'])
 
297
 
 
298
        osutils.rename('a1', 'sub/a1')
 
299
        self.run_bzr_error(
 
300
            ["^bzr: ERROR: Could not move to sub. sub is not versioned\.$"],
 
301
            'mv a1 a2 sub')
 
302
        self.failIfExists('a1')
 
303
        self.failUnlessExists('sub/a1')
 
304
        self.failUnlessExists('a2')
 
305
        self.failIfExists('sub/a2')
 
306
 
 
307
    def test_mv_already_moved_file_forcing_after(self):
 
308
        """Test bzr mv versioned_file to unversioned_file.
 
309
 
 
310
        Tests if an attempt to move an existing versioned file to an existing
 
311
        unversioned file will fail, informing the user to use the --after
 
312
        option to force this.
 
313
        Setup: a is in the working tree, b not versioned.
 
314
        User does: mv a b; touch a; bzr mv a b
 
315
        """
 
316
        self.build_tree(['a', 'b'])
 
317
        tree = self.make_branch_and_tree('.')
 
318
        tree.add(['a'])
 
319
 
 
320
        osutils.rename('a', 'b')
 
321
        self.build_tree(['a']) #touch a
 
322
        self.run_bzr_error(
 
323
            ["^bzr: ERROR: Could not rename a => b because both files exist."
 
324
             " \(Use --after to tell bzr about a rename that has already"
 
325
             " happened\)$"],
 
326
            'mv a b')
 
327
        self.failUnlessExists('a')
 
328
        self.failUnlessExists('b')
 
329
 
 
330
    def test_mv_already_moved_file_using_after(self):
 
331
        """Test bzr mv --after versioned_file to unversioned_file.
 
332
 
 
333
        Tests if an existing versioned file can be forced to move to an
 
334
        existing unversioned file using the --after option. With the result
 
335
        that bazaar considers the unversioned_file to be moved from
 
336
        versioned_file and versioned_file will become unversioned.
 
337
        Setup: a is in the working tree and b exists.
 
338
        User does: mv a b; touch a; bzr mv a b --after
 
339
        Resulting in a => b and a is unknown.
 
340
        """
 
341
        self.build_tree(['a', 'b'])
 
342
        tree = self.make_branch_and_tree('.')
 
343
        tree.add(['a'])
 
344
        osutils.rename('a', 'b')
 
345
        self.build_tree(['a']) #touch a
 
346
 
 
347
        self.run_bzr('mv a b --after')
 
348
        self.failUnlessExists('a')
 
349
        self.assertNotInWorkingTree('a')#a should be unknown now.
 
350
        self.failUnlessExists('b')
 
351
        self.assertInWorkingTree('b')
 
352
 
 
353
    def test_mv_already_moved_files_forcing_after(self):
 
354
        """Test bzr mv versioned_files to directory/unversioned_file.
 
355
 
 
356
        Tests if an attempt to move an existing versioned file to an existing
 
357
        unversioned file in some other directory will fail, informing the user
 
358
        to use the --after option to force this.
 
359
 
 
360
        Setup: a1, a2, sub are versioned and in the working tree,
 
361
               sub/a1, sub/a2 are in working tree.
 
362
        User does: mv a* sub; touch a1; touch a2; bzr mv a1 a2 sub
 
363
        """
 
364
        self.build_tree(['a1', 'a2', 'sub/', 'sub/a1', 'sub/a2'])
 
365
        tree = self.make_branch_and_tree('.')
 
366
        tree.add(['a1', 'a2', 'sub'])
 
367
        osutils.rename('a1', 'sub/a1')
 
368
        osutils.rename('a2', 'sub/a2')
 
369
        self.build_tree(['a1']) #touch a1
 
370
        self.build_tree(['a2']) #touch a2
 
371
 
 
372
        self.run_bzr_error(
 
373
            ["^bzr: ERROR: Could not rename a1 => sub/a1 because both files"
 
374
             " exist. \(Use --after to tell bzr about a rename that has already"
 
375
             " happened\)$"],
 
376
            'mv a1 a2 sub')
 
377
        self.failUnlessExists('a1')
 
378
        self.failUnlessExists('a2')
 
379
        self.failUnlessExists('sub/a1')
 
380
        self.failUnlessExists('sub/a2')
 
381
 
 
382
    def test_mv_already_moved_files_using_after(self):
 
383
        """Test bzr mv --after versioned_file to directory/unversioned_file.
 
384
 
 
385
        Tests if an existing versioned file can be forced to move to an
 
386
        existing unversioned file in some other directory using the --after
 
387
        option. With the result that bazaar considers
 
388
        directory/unversioned_file to be moved from versioned_file and
 
389
        versioned_file will become unversioned.
 
390
 
 
391
        Setup: a1, a2, sub are versioned and in the working tree,
 
392
               sub/a1, sub/a2 are in working tree.
 
393
        User does: mv a* sub; touch a1; touch a2; bzr mv a1 a2 sub --after
 
394
        """
 
395
        self.build_tree(['a1', 'a2', 'sub/', 'sub/a1', 'sub/a2'])
 
396
        tree = self.make_branch_and_tree('.')
 
397
        tree.add(['a1', 'a2', 'sub'])
 
398
        osutils.rename('a1', 'sub/a1')
 
399
        osutils.rename('a2', 'sub/a2')
 
400
        self.build_tree(['a1']) #touch a1
 
401
        self.build_tree(['a2']) #touch a2
 
402
 
 
403
        self.run_bzr('mv a1 a2 sub --after')
 
404
        self.failUnlessExists('a1')
 
405
        self.failUnlessExists('a2')
 
406
        self.failUnlessExists('sub/a1')
 
407
        self.failUnlessExists('sub/a2')
 
408
        self.assertInWorkingTree('sub/a1')
 
409
        self.assertInWorkingTree('sub/a2')
 
410
 
 
411
    def test_mv_already_moved_directory(self):
 
412
        """Use `bzr mv a b` to mark a directory as renamed.
 
413
 
 
414
        https://bugs.launchpad.net/bzr/+bug/107967/
 
415
        """
 
416
        self.build_tree(['a/', 'c/'])
 
417
        tree = self.make_branch_and_tree('.')
 
418
        tree.add(['a', 'c'])
 
419
        osutils.rename('a', 'b')
 
420
        osutils.rename('c', 'd')
 
421
        # mv a b should work just like it does for already renamed files
 
422
        self.run_bzr('mv a b')
 
423
        self.failIfExists('a')
 
424
        self.assertNotInWorkingTree('a')
 
425
        self.failUnlessExists('b')
 
426
        self.assertInWorkingTree('b')
 
427
        # and --after should work, too (technically it's ignored)
 
428
        self.run_bzr('mv --after c d')
 
429
        self.failIfExists('c')
 
430
        self.assertNotInWorkingTree('c')
 
431
        self.failUnlessExists('d')
 
432
        self.assertInWorkingTree('d')