/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to tests/test_generic_processor.py

add lots of import tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
    # to use None to mean "don't check this".
43
43
    def assertChanges(self, branch, revno, expected_added=[],
44
44
            expected_removed=[], expected_modified=[],
45
 
            expected_renamed=[]):
 
45
            expected_renamed=[], expected_kind_changed=[]):
46
46
        """Check the changes introduced in a revision of a branch.
47
47
 
48
48
        This method checks that a revision introduces expected changes.
62
62
            been modified in the delta.
63
63
        expected_renamed: a list of (old_path, new_path) tuples that
64
64
            must have been renamed in the delta.
 
65
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
 
66
            that must have been changed in the delta.
65
67
        :return: revtree1, revtree2
66
68
        """
67
69
        repo = branch.repository
68
 
        revtree1 = repo.revision_tree(branch.revision_history()[revno - 1])
69
 
        revtree2 = repo.revision_tree(branch.revision_history()[revno])
 
70
        revtree1 = repo.revision_tree(branch.get_rev_id(revno - 1))
 
71
        revtree2 = repo.revision_tree(branch.get_rev_id(revno))
70
72
        changes = revtree2.changes_from(revtree1)
71
 
        self.check_changes(changes, expected_added, expected_removed,
72
 
            expected_modified, expected_renamed)
 
73
        self._check_changes(changes, expected_added, expected_removed,
 
74
            expected_modified, expected_renamed, expected_kind_changed)
73
75
        return revtree1, revtree2
74
76
 
75
 
    def check_changes(self, changes, expected_added=[],
 
77
    def _check_changes(self, changes, expected_added=[],
76
78
            expected_removed=[], expected_modified=[],
77
 
            expected_renamed=[]):
 
79
            expected_renamed=[], expected_kind_changed=[]):
78
80
        """Check the changes in a TreeDelta
79
81
 
80
82
        This method checks that the TreeDelta contains the expected
94
96
            been modified in the delta.
95
97
        expected_renamed: a list of (old_path, new_path) tuples that
96
98
            must have been renamed in the delta.
 
99
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
 
100
            that must have been changed in the delta.
97
101
        """
98
102
        renamed = changes.renamed
99
103
        added = changes.added
100
104
        removed = changes.removed
101
105
        modified = changes.modified
 
106
        kind_changed = changes.kind_changed
102
107
        if expected_renamed is not None:
103
108
            self.assertEquals(len(renamed), len(expected_renamed),
104
109
                "%s is renamed, expected %s" % (renamed, expected_renamed))
129
134
            modified_files = [(item[0],) for item in modified]
130
135
            for expected_modified_entry in expected_modified:
131
136
                self.assertTrue(expected_modified_entry in modified_files,
132
 
                    "%s is not modified, %s are" % (str(expected_modified_entry),
133
 
                        modified_files))
 
137
                    "%s is not modified, %s are" % (
 
138
                    str(expected_modified_entry), modified_files))
 
139
        if expected_kind_changed is not None:
 
140
            self.assertEquals(len(kind_changed), len(expected_kind_changed),
 
141
                "%s is kind-changed, expected %s" % (kind_changed,
 
142
                    expected_kind_changed))
 
143
            kind_changed_files = [(item[0], item[2], item[3])
 
144
                for item in kind_changed]
 
145
            for expected_kind_changed_entry in expected_kind_changed:
 
146
                self.assertTrue(expected_kind_changed_entry in
 
147
                    kind_changed_files, "%s is not kind-changed, %s are" % (
 
148
                    str(expected_kind_changed_entry), kind_changed_files))
 
149
 
 
150
    def assertContent(self, branch, tree, path, content):
 
151
        file_id = tree.inventory.path2id(path)
 
152
        branch.lock_read()
 
153
        self.addCleanup(branch.unlock)
 
154
        self.assertEqual(tree.get_file_text(file_id), content)
 
155
 
 
156
    def assertSymlinkTarget(self, branch, tree, path, target):
 
157
        file_id = tree.inventory.path2id(path)
 
158
        branch.lock_read()
 
159
        self.addCleanup(branch.unlock)
 
160
        self.assertEqual(tree.get_symlink_target(file_id), target)
 
161
 
 
162
    def assertExecutable(self, branch, tree, path, executable):
 
163
        file_id = tree.inventory.path2id(path)
 
164
        branch.lock_read()
 
165
        self.addCleanup(branch.unlock)
 
166
        self.assertEqual(tree.is_executable(file_id), executable)
 
167
 
 
168
    def assertRevisionRoot(self, revtree, path):
 
169
        self.assertEqual(revtree.get_revision_id(),
 
170
                         revtree.inventory.root.children[path].revision)
 
171
 
 
172
 
 
173
class TestModify(TestCaseForGenericProcessor):
 
174
 
 
175
    def file_command_iter(self, path, kind='file', content='aaa',
 
176
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
 
177
        # Revno 1: create a file or symlink
 
178
        # Revno 2: modify it
 
179
        if to_kind is None:
 
180
            to_kind = kind
 
181
        if to_executable is None:
 
182
            to_executable = executable
 
183
        def command_list():
 
184
            author = ['', 'bugs@a.com', time.time(), time.timezone]
 
185
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
 
186
            def files_one():
 
187
                yield commands.FileModifyCommand(path, kind, executable,
 
188
                        None, content)
 
189
            yield commands.CommitCommand('head', '1', author,
 
190
                committer, "commit 1", None, [], files_one)
 
191
            def files_two():
 
192
                yield commands.FileModifyCommand(path, to_kind, to_executable,
 
193
                        None, to_content)
 
194
            yield commands.CommitCommand('head', '2', author,
 
195
                committer, "commit 2", ":1", [], files_two)
 
196
        return command_list
 
197
 
 
198
    def test_modify_file_in_root(self):
 
199
        handler, branch = self.get_handler()
 
200
        path = 'a'
 
201
        handler.process(self.file_command_iter(path))
 
202
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
203
            expected_added=[(path,)])
 
204
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
205
            expected_modified=[(path,)])
 
206
        self.assertContent(branch, revtree1, path, "aaa")
 
207
        self.assertContent(branch, revtree2, path, "bbb")
 
208
        self.assertRevisionRoot(revtree1, path)
 
209
        self.assertRevisionRoot(revtree2, path)
 
210
 
 
211
    def test_modify_file_in_subdir(self):
 
212
        handler, branch = self.get_handler()
 
213
        path = 'a/a'
 
214
        handler.process(self.file_command_iter(path))
 
215
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
216
            expected_added=[('a',), (path,)])
 
217
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
218
            expected_modified=[(path,)])
 
219
        self.assertContent(branch, revtree1, path, "aaa")
 
220
        self.assertContent(branch, revtree2, path, "bbb")
 
221
 
 
222
    def test_modify_symlink_in_root(self):
 
223
        handler, branch = self.get_handler()
 
224
        path = 'a'
 
225
        handler.process(self.file_command_iter(path, kind='symlink'))
 
226
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
227
            expected_modified=[(path,)])
 
228
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
 
229
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
 
230
        self.assertRevisionRoot(revtree1, path)
 
231
        self.assertRevisionRoot(revtree2, path)
 
232
 
 
233
    def test_modify_symlink_in_subdir(self):
 
234
        handler, branch = self.get_handler()
 
235
        path = 'a/a'
 
236
        handler.process(self.file_command_iter(path, kind='symlink'))
 
237
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
238
            expected_added=[('a',), (path,)])
 
239
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
240
            expected_modified=[(path,)])
 
241
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
 
242
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
 
243
 
 
244
    def test_modify_file_becomes_symlink(self):
 
245
        handler, branch = self.get_handler()
 
246
        path = 'a/a'
 
247
        handler.process(self.file_command_iter(path,
 
248
            kind='file', to_kind='symlink'))
 
249
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
250
            expected_added=[('a',), (path,)])
 
251
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
252
            expected_kind_changed=[(path, 'file', 'symlink')])
 
253
        self.assertContent(branch, revtree1, path, "aaa")
 
254
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
 
255
 
 
256
    def test_modify_symlink_becomes_file(self):
 
257
        handler, branch = self.get_handler()
 
258
        path = 'a/a'
 
259
        handler.process(self.file_command_iter(path,
 
260
            kind='symlink', to_kind='file'))
 
261
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
262
            expected_added=[('a',), (path,)])
 
263
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
264
            expected_kind_changed=[(path, 'symlink', 'file')])
 
265
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
 
266
        self.assertContent(branch, revtree2, path, "bbb")
 
267
 
 
268
    def test_modify_file_now_executable(self):
 
269
        handler, branch = self.get_handler()
 
270
        path = 'a/a'
 
271
        handler.process(self.file_command_iter(path,
 
272
            executable=False, to_executable=True, to_content='aaa'))
 
273
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
274
            expected_added=[('a',), (path,)])
 
275
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
276
            expected_modified=[(path,)])
 
277
        self.assertExecutable(branch, revtree1, path, False)
 
278
        self.assertExecutable(branch, revtree2, path, True)
 
279
 
 
280
    def test_modify_file_no_longer_executable(self):
 
281
        handler, branch = self.get_handler()
 
282
        path = 'a/a'
 
283
        handler.process(self.file_command_iter(path,
 
284
            executable=True, to_executable=False, to_content='aaa'))
 
285
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
286
            expected_added=[('a',), (path,)])
 
287
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
288
            expected_modified=[(path,)])
 
289
        self.assertExecutable(branch, revtree1, path, True)
 
290
        self.assertExecutable(branch, revtree2, path, False)
 
291
 
 
292
 
 
293
class TestModifyTricky(TestCaseForGenericProcessor):
 
294
 
 
295
    def file_command_iter(self, path1, path2, kind='file'):
 
296
        # Revno 1: create a file or symlink in a directory
 
297
        # Revno 2: create a second file that implicitly deletes the
 
298
        # first one because either:
 
299
        # * the new file is a in directory with the old file name
 
300
        # * the new file has the same name as the directory of the first
 
301
        def command_list():
 
302
            author = ['', 'bugs@a.com', time.time(), time.timezone]
 
303
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
 
304
            def files_one():
 
305
                yield commands.FileModifyCommand(path1, kind, False,
 
306
                        None, "aaa")
 
307
            yield commands.CommitCommand('head', '1', author,
 
308
                committer, "commit 1", None, [], files_one)
 
309
            def files_two():
 
310
                yield commands.FileModifyCommand(path2, kind, False,
 
311
                        None, "bbb")
 
312
            yield commands.CommitCommand('head', '2', author,
 
313
                committer, "commit 2", ":1", [], files_two)
 
314
        return command_list
 
315
 
 
316
 
 
317
    def test_modify_file_becomes_directory(self):
 
318
        handler, branch = self.get_handler()
 
319
        path1 = 'a/b'
 
320
        path2 = 'a/b/c'
 
321
        handler.process(self.file_command_iter(path1, path2))
 
322
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
323
            expected_added=[('a',), (path1,)])
 
324
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
325
            expected_added=[(path2,)],
 
326
            expected_kind_changed=[(path1, 'file', 'directory')])
 
327
        self.assertContent(branch, revtree1, path1, "aaa")
 
328
        self.assertContent(branch, revtree2, path2, "bbb")
 
329
 
 
330
    def test_modify_directory_becomes_file(self):
 
331
        handler, branch = self.get_handler()
 
332
        path1 = 'a/b/c'
 
333
        path2 = 'a/b'
 
334
        handler.process(self.file_command_iter(path1, path2))
 
335
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
336
            expected_added=[('a',), ('a/b',), (path1,)])
 
337
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
338
            expected_removed=[(path1,),],
 
339
            expected_kind_changed=[(path2, 'directory', 'file')])
 
340
        self.assertContent(branch, revtree1, path1, "aaa")
 
341
        self.assertContent(branch, revtree2, path2, "bbb")
 
342
 
 
343
    def test_modify_symlink_becomes_directory(self):
 
344
        handler, branch = self.get_handler()
 
345
        path1 = 'a/b'
 
346
        path2 = 'a/b/c'
 
347
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
 
348
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
349
            expected_added=[('a',), (path1,)])
 
350
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
351
            expected_added=[(path2,)],
 
352
            expected_kind_changed=[(path1, 'symlink', 'directory')])
 
353
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
 
354
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
 
355
 
 
356
    def test_modify_directory_becomes_symlink(self):
 
357
        handler, branch = self.get_handler()
 
358
        path1 = 'a/b/c'
 
359
        path2 = 'a/b'
 
360
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
 
361
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
362
            expected_added=[('a',), ('a/b',), (path1,)])
 
363
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
364
            expected_removed=[(path1,),],
 
365
            expected_kind_changed=[(path2, 'directory', 'symlink')])
 
366
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
 
367
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
 
368
 
 
369
 
 
370
class TestDelete(TestCaseForGenericProcessor):
 
371
 
 
372
    def file_command_iter(self, path, kind='file'):
 
373
        # Revno 1: create a file or symlink
 
374
        # Revno 2: delete it
 
375
        def command_list():
 
376
            author = ['', 'bugs@a.com', time.time(), time.timezone]
 
377
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
 
378
            def files_one():
 
379
                yield commands.FileModifyCommand(path, kind, False,
 
380
                        None, "aaa")
 
381
            yield commands.CommitCommand('head', '1', author,
 
382
                committer, "commit 1", None, [], files_one)
 
383
            def files_two():
 
384
                yield commands.FileDeleteCommand(path)
 
385
            yield commands.CommitCommand('head', '2', author,
 
386
                committer, "commit 2", ":1", [], files_two)
 
387
        return command_list
 
388
 
 
389
    def test_delete_file_in_root(self):
 
390
        handler, branch = self.get_handler()
 
391
        path = 'a'
 
392
        handler.process(self.file_command_iter(path))
 
393
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
394
            expected_added=[(path,)])
 
395
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
396
            expected_removed=[(path,)])
 
397
        self.assertContent(branch, revtree1, path, "aaa")
 
398
        self.assertRevisionRoot(revtree1, path)
 
399
 
 
400
    def test_delete_file_in_subdir(self):
 
401
        handler, branch = self.get_handler()
 
402
        path = 'a/a'
 
403
        handler.process(self.file_command_iter(path))
 
404
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
405
            expected_added=[('a',), (path,)])
 
406
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
407
            expected_removed=[(path,)])
 
408
        self.assertContent(branch, revtree1, path, "aaa")
 
409
 
 
410
    def test_delete_symlink_in_root(self):
 
411
        handler, branch = self.get_handler()
 
412
        path = 'a'
 
413
        handler.process(self.file_command_iter(path, kind='symlink'))
 
414
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
415
            expected_removed=[(path,)])
 
416
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
 
417
        self.assertRevisionRoot(revtree1, path)
 
418
 
 
419
    def test_delete_symlink_in_subdir(self):
 
420
        handler, branch = self.get_handler()
 
421
        path = 'a/a'
 
422
        handler.process(self.file_command_iter(path, kind='symlink'))
 
423
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
424
            expected_added=[('a',), (path,)])
 
425
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
426
            expected_removed=[(path,)])
 
427
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
 
428
 
 
429
 
 
430
class TestDeleteDirectory(TestCaseForGenericProcessor):
 
431
 
 
432
    def file_command_iter(self, paths, dir):
 
433
        # Revno 1: create multiple files
 
434
        # Revno 2: delete a directory holding those files
 
435
        def command_list():
 
436
            author = ['', 'bugs@a.com', time.time(), time.timezone]
 
437
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
 
438
            def files_one():
 
439
                for i, path in enumerate(paths):
 
440
                    yield commands.FileModifyCommand(path, 'file', False,
 
441
                            None, "aaa%d" % i)
 
442
            yield commands.CommitCommand('head', '1', author,
 
443
                committer, "commit 1", None, [], files_one)
 
444
            def files_two():
 
445
                yield commands.FileDeleteCommand(dir)
 
446
            yield commands.CommitCommand('head', '2', author,
 
447
                committer, "commit 2", ":1", [], files_two)
 
448
        return command_list
 
449
 
 
450
    def test_delete_dir(self):
 
451
        handler, branch = self.get_handler()
 
452
        paths = ['a/b/c', 'a/b/d', 'a/b/e/f', 'a/g']
 
453
        dir = 'a/b'
 
454
        handler.process(self.file_command_iter(paths, dir))
 
455
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
456
            expected_added=[
 
457
                ('a',), ('a/b',), ('a/b/c',),
 
458
                ('a/b/d',),
 
459
                ('a/b/e',), ('a/b/e/f',),
 
460
                ('a/g',),
 
461
                ])
 
462
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
463
            expected_removed=[
 
464
                ('a/b',), ('a/b/c',),
 
465
                ('a/b/d',),
 
466
                ('a/b/e',), ('a/b/e/f',),
 
467
                ])
134
468
 
135
469
 
136
470
class TestRename(TestCaseForGenericProcessor):
137
471
 
138
472
    def get_command_iter(self, old_path, new_path):
 
473
        # Revno 1: create a file or symlink
 
474
        # Revno 2: rename it
139
475
        def command_list():
140
476
            author = ['', 'bugs@a.com', time.time(), time.timezone]
141
477
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
155
491
        old_path = 'a'
156
492
        new_path = 'b'
157
493
        handler.process(self.get_command_iter(old_path, new_path))
158
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
494
        revtree1, revtree2 = self.assertChanges(branch, 2,
159
495
            expected_renamed=[(old_path, new_path)])
160
 
        self.assertEqual(revtree1.get_revision_id(),
161
 
                         revtree1.inventory.root.children['a'].revision)
162
 
        self.assertEqual(revtree2.get_revision_id(),
163
 
                         revtree2.inventory.root.children['b'].revision)
 
496
        self.assertRevisionRoot(revtree1, old_path)
 
497
        self.assertRevisionRoot(revtree2, new_path)
164
498
 
165
499
    def test_rename_in_subdir(self):
166
500
        handler, branch = self.get_handler()
167
501
        old_path = 'a/a'
168
502
        new_path = 'a/b'
169
503
        handler.process(self.get_command_iter(old_path, new_path))
170
 
        self.assertChanges(branch, 1, expected_renamed=[(old_path, new_path)])
 
504
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)])
171
505
 
172
506
    def test_move_to_new_dir(self):
173
507
        handler, branch = self.get_handler()
174
508
        old_path = 'a/a'
175
509
        new_path = 'b/a'
176
510
        handler.process(self.get_command_iter(old_path, new_path))
177
 
        self.assertChanges(branch, 1, expected_renamed=[(old_path, new_path)],
 
511
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)],
178
512
            expected_added=[('b',)])
179
513
 
180
514
 
 
515
class TestRenameTricky(TestCaseForGenericProcessor):
 
516
 
 
517
    def file_command_iter(self, path1, old_path2, new_path2, kind='file'):
 
518
        # Revno 1: create two files or symlinks in a directory
 
519
        # Revno 2: rename the second file so that it implicitly deletes the
 
520
        # first one because either:
 
521
        # * the new file is a in directory with the old file name
 
522
        # * the new file has the same name as the directory of the first
 
523
        def command_list():
 
524
            author = ['', 'bugs@a.com', time.time(), time.timezone]
 
525
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
 
526
            def files_one():
 
527
                yield commands.FileModifyCommand(path1, kind, False,
 
528
                        None, "aaa")
 
529
                yield commands.FileModifyCommand(old_path2, kind, False,
 
530
                        None, "bbb")
 
531
            yield commands.CommitCommand('head', '1', author,
 
532
                committer, "commit 1", None, [], files_one)
 
533
            def files_two():
 
534
                yield commands.FileRenameCommand(old_path2, new_path2)
 
535
            yield commands.CommitCommand('head', '2', author,
 
536
                committer, "commit 2", ":1", [], files_two)
 
537
        return command_list
 
538
 
 
539
 
 
540
    def test_rename_file_becomes_directory(self):
 
541
        handler, branch = self.get_handler()
 
542
        old_path2 = 'foo'
 
543
        path1     = 'a/b'
 
544
        new_path2 = 'a/b/c'
 
545
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
 
546
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
547
            expected_added=[('a',), (path1,), (old_path2,)])
 
548
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
549
            expected_renamed=[(old_path2, new_path2)],
 
550
            expected_kind_changed=[(path1, 'file', 'directory')])
 
551
        self.assertContent(branch, revtree1, path1, "aaa")
 
552
        self.assertContent(branch, revtree2, new_path2, "bbb")
 
553
 
 
554
    def test_rename_directory_becomes_file(self):
 
555
        handler, branch = self.get_handler()
 
556
        old_path2 = 'foo'
 
557
        path1     = 'a/b/c'
 
558
        new_path2 = 'a/b'
 
559
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
 
560
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
561
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
 
562
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
563
            expected_renamed=[(old_path2, new_path2)],
 
564
            expected_removed=[(path1,), (new_path2,)])
 
565
        self.assertContent(branch, revtree1, path1, "aaa")
 
566
        self.assertContent(branch, revtree2, new_path2, "bbb")
 
567
 
 
568
    def test_rename_symlink_becomes_directory(self):
 
569
        handler, branch = self.get_handler()
 
570
        old_path2 = 'foo'
 
571
        path1     = 'a/b'
 
572
        new_path2 = 'a/b/c'
 
573
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
 
574
            'symlink'))
 
575
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
576
            expected_added=[('a',), (path1,), (old_path2,)])
 
577
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
578
            expected_renamed=[(old_path2, new_path2)],
 
579
            expected_kind_changed=[(path1, 'symlink', 'directory')])
 
580
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
 
581
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
 
582
 
 
583
    def test_rename_directory_becomes_symlink(self):
 
584
        handler, branch = self.get_handler()
 
585
        old_path2 = 'foo'
 
586
        path1     = 'a/b/c'
 
587
        new_path2 = 'a/b'
 
588
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
 
589
            'symlink'))
 
590
        revtree0, revtree1 = self.assertChanges(branch, 1,
 
591
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
 
592
        revtree1, revtree2 = self.assertChanges(branch, 2,
 
593
            expected_renamed=[(old_path2, new_path2)],
 
594
            expected_removed=[(path1,), (new_path2,)])
 
595
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
 
596
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
 
597
 
 
598
 
181
599
class TestCopy(TestCaseForGenericProcessor):
182
600
 
183
 
    def file_command_iter(self, src_path, dest_path):
 
601
    def file_command_iter(self, src_path, dest_path, kind='file'):
 
602
        # Revno 1: create a file or symlink
 
603
        # Revno 2: copy it
184
604
        def command_list():
185
605
            author = ['', 'bugs@a.com', time.time(), time.timezone]
186
606
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
187
607
            def files_one():
188
 
                yield commands.FileModifyCommand(src_path, 'file', False,
 
608
                yield commands.FileModifyCommand(src_path, kind, False,
189
609
                        None, "aaa")
190
610
            yield commands.CommitCommand('head', '1', author,
191
611
                committer, "commit 1", None, [], files_one)
195
615
                committer, "commit 2", ":1", [], files_two)
196
616
        return command_list
197
617
 
198
 
    def assertContent(self, branch, tree, path, content):
199
 
        file_id = tree.inventory.path2id(path)
200
 
        branch.lock_read()
201
 
        self.addCleanup(branch.unlock)
202
 
        self.assertEqual(tree.get_file_text(file_id), content)
203
 
 
204
618
    def test_copy_file_in_root(self):
205
619
        handler, branch = self.get_handler()
206
620
        src_path = 'a'
207
621
        dest_path = 'b'
208
622
        handler.process(self.file_command_iter(src_path, dest_path))
209
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
623
        revtree1, revtree2 = self.assertChanges(branch, 2,
210
624
            expected_added=[(dest_path,)])
 
625
        self.assertContent(branch, revtree1, src_path, "aaa")
 
626
        self.assertContent(branch, revtree2, src_path, "aaa")
211
627
        self.assertContent(branch, revtree2, dest_path, "aaa")
212
 
        self.assertEqual(revtree1.get_revision_id(),
213
 
                         revtree1.inventory.root.children['a'].revision)
214
 
        self.assertEqual(revtree2.get_revision_id(),
215
 
                         revtree2.inventory.root.children['b'].revision)
 
628
        self.assertRevisionRoot(revtree1, src_path)
 
629
        self.assertRevisionRoot(revtree2, dest_path)
216
630
 
217
631
    def test_copy_file_in_subdir(self):
218
632
        handler, branch = self.get_handler()
219
633
        src_path = 'a/a'
220
634
        dest_path = 'a/b'
221
635
        handler.process(self.file_command_iter(src_path, dest_path))
222
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
636
        revtree1, revtree2 = self.assertChanges(branch, 2,
223
637
            expected_added=[(dest_path,)])
 
638
        self.assertContent(branch, revtree1, src_path, "aaa")
 
639
        self.assertContent(branch, revtree2, src_path, "aaa")
224
640
        self.assertContent(branch, revtree2, dest_path, "aaa")
225
641
 
226
642
    def test_copy_file_to_new_dir(self):
228
644
        src_path = 'a/a'
229
645
        dest_path = 'b/a'
230
646
        handler.process(self.file_command_iter(src_path, dest_path))
231
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
647
        revtree1, revtree2 = self.assertChanges(branch, 2,
232
648
            expected_added=[('b',), (dest_path,)])
 
649
        self.assertContent(branch, revtree1, src_path, "aaa")
 
650
        self.assertContent(branch, revtree2, src_path, "aaa")
233
651
        self.assertContent(branch, revtree2, dest_path, "aaa")
234
652
 
235
 
    def symlink_command_iter(self, src_path, dest_path):
236
 
        def command_list():
237
 
            author = ['', 'bugs@a.com', time.time(), time.timezone]
238
 
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
239
 
            def files_one():
240
 
                yield commands.FileModifyCommand(src_path, 'symlink', False,
241
 
                        None, "aaa")
242
 
            yield commands.CommitCommand('head', '1', author,
243
 
                committer, "commit 1", None, [], files_one)
244
 
            def files_two():
245
 
                yield commands.FileCopyCommand(src_path, dest_path)
246
 
            yield commands.CommitCommand('head', '2', author,
247
 
                committer, "commit 2", ":1", [], files_two)
248
 
        return command_list
249
 
 
250
 
    def assertSymlinkTarget(self, branch, tree, path, target):
251
 
        file_id = tree.inventory.path2id(path)
252
 
        branch.lock_read()
253
 
        self.addCleanup(branch.unlock)
254
 
        self.assertEqual(tree.get_symlink_target(file_id), target)
255
 
 
256
653
    def test_copy_symlink_in_root(self):
257
654
        handler, branch = self.get_handler()
258
655
        src_path = 'a'
259
656
        dest_path = 'b'
260
 
        handler.process(self.symlink_command_iter(src_path, dest_path))
261
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
657
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
 
658
        revtree1, revtree2 = self.assertChanges(branch, 2,
262
659
            expected_added=[(dest_path,)])
 
660
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
 
661
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
263
662
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
264
 
        self.assertEqual(revtree1.get_revision_id(),
265
 
                         revtree1.inventory.root.children['a'].revision)
266
 
        self.assertEqual(revtree2.get_revision_id(),
267
 
                         revtree2.inventory.root.children['b'].revision)
 
663
        self.assertRevisionRoot(revtree1, src_path)
 
664
        self.assertRevisionRoot(revtree2, dest_path)
268
665
 
269
666
    def test_copy_symlink_in_subdir(self):
270
667
        handler, branch = self.get_handler()
271
668
        src_path = 'a/a'
272
669
        dest_path = 'a/b'
273
 
        handler.process(self.symlink_command_iter(src_path, dest_path))
274
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
670
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
 
671
        revtree1, revtree2 = self.assertChanges(branch, 2,
275
672
            expected_added=[(dest_path,)])
 
673
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
 
674
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
276
675
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
277
676
 
278
677
    def test_copy_symlink_to_new_dir(self):
279
678
        handler, branch = self.get_handler()
280
679
        src_path = 'a/a'
281
680
        dest_path = 'b/a'
282
 
        handler.process(self.symlink_command_iter(src_path, dest_path))
283
 
        revtree1, revtree2 = self.assertChanges(branch, 1,
 
681
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
 
682
        revtree1, revtree2 = self.assertChanges(branch, 2,
284
683
            expected_added=[('b',), (dest_path,)])
 
684
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
 
685
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
285
686
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
286
687
 
287
688