~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-01-02 08:23:44 UTC
  • mfrom: (3140.1.9 find-branches)
  • Revision ID: pqm@pqm.ubuntu.com-20080102082344-qret383z2bdk1ud4
Optimize find_branches for standalone repositories (abentley)

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
32
32
                           ReusingTransform, CantMoveRoot, 
33
33
                           PathsNotVersionedError, ExistingLimbo,
34
 
                           ImmortalLimbo, LockError)
35
 
from bzrlib.osutils import file_kind, has_symlinks, pathjoin
 
34
                           ExistingPendingDeletion, ImmortalLimbo,
 
35
                           ImmortalPendingDeletion, LockError)
 
36
from bzrlib.osutils import file_kind, pathjoin
36
37
from bzrlib.merge import Merge3Merger
37
 
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
 
38
from bzrlib.tests import (
 
39
    CaseInsensitiveFilesystemFeature,
 
40
    SymlinkFeature,
 
41
    TestCase,
 
42
    TestCaseInTempDir,
 
43
    TestSkipped,
 
44
    )
38
45
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths, 
39
46
                              resolve_conflicts, cook_conflicts, 
40
 
                              find_interesting, build_tree, get_backup_name)
 
47
                              find_interesting, build_tree, get_backup_name,
 
48
                              change_entry, _FileMover, resolve_checkout)
41
49
 
42
50
 
43
51
class TestTreeTransform(tests.TestCaseWithTransport):
53
61
        return transform, transform.root
54
62
 
55
63
    def test_existing_limbo(self):
56
 
        limbo_name = urlutils.local_path_from_url(
57
 
            self.wt._control_files.controlfilename('limbo'))
58
64
        transform, root = self.get_transform()
 
65
        limbo_name = transform._limbodir
 
66
        deletion_path = transform._deletiondir
59
67
        os.mkdir(pathjoin(limbo_name, 'hehe'))
60
68
        self.assertRaises(ImmortalLimbo, transform.apply)
61
69
        self.assertRaises(LockError, self.wt.unlock)
63
71
        self.assertRaises(LockError, self.wt.unlock)
64
72
        os.rmdir(pathjoin(limbo_name, 'hehe'))
65
73
        os.rmdir(limbo_name)
 
74
        os.rmdir(deletion_path)
66
75
        transform, root = self.get_transform()
67
76
        transform.apply()
68
77
 
 
78
    def test_existing_pending_deletion(self):
 
79
        transform, root = self.get_transform()
 
80
        deletion_path = self._limbodir = urlutils.local_path_from_url(
 
81
            transform._tree._control_files.controlfilename('pending-deletion'))
 
82
        os.mkdir(pathjoin(deletion_path, 'blocking-directory'))
 
83
        self.assertRaises(ImmortalPendingDeletion, transform.apply)
 
84
        self.assertRaises(LockError, self.wt.unlock)
 
85
        self.assertRaises(ExistingPendingDeletion, self.get_transform)
 
86
 
69
87
    def test_build(self):
70
 
        transform, root = self.get_transform() 
 
88
        transform, root = self.get_transform()
 
89
        self.wt.lock_tree_write()
 
90
        self.addCleanup(self.wt.unlock)
71
91
        self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
72
92
        imaginary_id = transform.trans_id_tree_path('imaginary')
73
93
        imaginary_id2 = transform.trans_id_tree_path('imaginary/')
110
130
 
111
131
    def test_convenience(self):
112
132
        transform, root = self.get_transform()
 
133
        self.wt.lock_tree_write()
 
134
        self.addCleanup(self.wt.unlock)
113
135
        trans_id = transform.new_file('name', root, 'contents', 
114
136
                                      'my_pretties', True)
115
137
        oz = transform.new_directory('oz', root, 'oz-id')
216
238
        transform3.adjust_path('tip', root_id, tip_id)
217
239
        transform3.apply()
218
240
 
 
241
    def test_conflict_on_case_insensitive(self):
 
242
        tree = self.make_branch_and_tree('tree')
 
243
        # Don't try this at home, kids!
 
244
        # Force the tree to report that it is case sensitive, for conflict
 
245
        # resolution tests
 
246
        tree.case_sensitive = True
 
247
        transform = TreeTransform(tree)
 
248
        self.addCleanup(transform.finalize)
 
249
        transform.new_file('file', transform.root, 'content')
 
250
        transform.new_file('FiLe', transform.root, 'content')
 
251
        result = transform.find_conflicts()
 
252
        self.assertEqual([], result)
 
253
        # Force the tree to report that it is case insensitive, for conflict
 
254
        # generation tests
 
255
        tree.case_sensitive = False
 
256
        result = transform.find_conflicts()
 
257
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
 
258
 
 
259
    def test_conflict_on_case_insensitive_existing(self):
 
260
        tree = self.make_branch_and_tree('tree')
 
261
        self.build_tree(['tree/FiLe'])
 
262
        # Don't try this at home, kids!
 
263
        # Force the tree to report that it is case sensitive, for conflict
 
264
        # resolution tests
 
265
        tree.case_sensitive = True
 
266
        transform = TreeTransform(tree)
 
267
        self.addCleanup(transform.finalize)
 
268
        transform.new_file('file', transform.root, 'content')
 
269
        result = transform.find_conflicts()
 
270
        self.assertEqual([], result)
 
271
        # Force the tree to report that it is case insensitive, for conflict
 
272
        # generation tests
 
273
        tree.case_sensitive = False
 
274
        result = transform.find_conflicts()
 
275
        self.assertEqual([('duplicate', 'new-1', 'new-2', 'file')], result)
 
276
 
 
277
    def test_resolve_case_insensitive_conflict(self):
 
278
        tree = self.make_branch_and_tree('tree')
 
279
        # Don't try this at home, kids!
 
280
        # Force the tree to report that it is case insensitive, for conflict
 
281
        # resolution tests
 
282
        tree.case_sensitive = False
 
283
        transform = TreeTransform(tree)
 
284
        self.addCleanup(transform.finalize)
 
285
        transform.new_file('file', transform.root, 'content')
 
286
        transform.new_file('FiLe', transform.root, 'content')
 
287
        resolve_conflicts(transform)
 
288
        transform.apply()
 
289
        self.failUnlessExists('tree/file')
 
290
        self.failUnlessExists('tree/FiLe.moved')
 
291
 
 
292
    def test_resolve_checkout_case_conflict(self):
 
293
        tree = self.make_branch_and_tree('tree')
 
294
        # Don't try this at home, kids!
 
295
        # Force the tree to report that it is case insensitive, for conflict
 
296
        # resolution tests
 
297
        tree.case_sensitive = False
 
298
        transform = TreeTransform(tree)
 
299
        self.addCleanup(transform.finalize)
 
300
        transform.new_file('file', transform.root, 'content')
 
301
        transform.new_file('FiLe', transform.root, 'content')
 
302
        resolve_conflicts(transform,
 
303
                          pass_func=lambda t, c: resolve_checkout(t, c, []))
 
304
        transform.apply()
 
305
        self.failUnlessExists('tree/file')
 
306
        self.failUnlessExists('tree/FiLe.moved')
 
307
 
 
308
    def test_apply_case_conflict(self):
 
309
        """Ensure that a transform with case conflicts can always be applied"""
 
310
        tree = self.make_branch_and_tree('tree')
 
311
        transform = TreeTransform(tree)
 
312
        self.addCleanup(transform.finalize)
 
313
        transform.new_file('file', transform.root, 'content')
 
314
        transform.new_file('FiLe', transform.root, 'content')
 
315
        dir = transform.new_directory('dir', transform.root)
 
316
        transform.new_file('dirfile', dir, 'content')
 
317
        transform.new_file('dirFiLe', dir, 'content')
 
318
        resolve_conflicts(transform)
 
319
        transform.apply()
 
320
        self.failUnlessExists('tree/file')
 
321
        if not os.path.exists('tree/FiLe.moved'):
 
322
            self.failUnlessExists('tree/FiLe')
 
323
        self.failUnlessExists('tree/dir/dirfile')
 
324
        if not os.path.exists('tree/dir/dirFiLe.moved'):
 
325
            self.failUnlessExists('tree/dir/dirFiLe')
 
326
 
 
327
    def test_case_insensitive_limbo(self):
 
328
        tree = self.make_branch_and_tree('tree')
 
329
        # Don't try this at home, kids!
 
330
        # Force the tree to report that it is case insensitive
 
331
        tree.case_sensitive = False
 
332
        transform = TreeTransform(tree)
 
333
        self.addCleanup(transform.finalize)
 
334
        dir = transform.new_directory('dir', transform.root)
 
335
        first = transform.new_file('file', dir, 'content')
 
336
        second = transform.new_file('FiLe', dir, 'content')
 
337
        self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
 
338
        self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
 
339
 
219
340
    def test_add_del(self):
220
341
        start, root = self.get_transform()
221
342
        start.new_directory('a', root, 'a')
373
494
        replace.apply()
374
495
 
375
496
    def test_symlinks(self):
376
 
        if not has_symlinks():
377
 
            raise TestSkipped('Symlinks are not supported on this platform')
 
497
        self.requireFeature(SymlinkFeature)
378
498
        transform,root = self.get_transform()
379
499
        oz_id = transform.new_directory('oz', root, 'oz-id')
380
500
        wizard = transform.new_symlink('wizard', oz_id, 'wizard-target', 
394
514
        self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
395
515
                         'wizard-target')
396
516
 
 
517
    def test_unable_create_symlink(self):
 
518
        def tt_helper():
 
519
            wt = self.make_branch_and_tree('.')
 
520
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
521
            try:
 
522
                tt.new_symlink('foo', tt.root, 'bar')
 
523
                tt.apply()
 
524
            finally:
 
525
                wt.unlock()
 
526
        os_symlink = getattr(os, 'symlink', None)
 
527
        os.symlink = None
 
528
        try:
 
529
            err = self.assertRaises(errors.UnableCreateSymlink, tt_helper)
 
530
            self.assertEquals(
 
531
                "Unable to create symlink 'foo' on this platform",
 
532
                str(err))
 
533
        finally:
 
534
            if os_symlink:
 
535
                os.symlink = os_symlink
 
536
 
397
537
    def get_conflicted(self):
398
538
        create,root = self.get_transform()
399
539
        create.new_file('dorothy', root, 'dorothy', 'dorothy-id')
542
682
        """
543
683
        transform, root = self.get_transform()
544
684
        wt = transform._tree
 
685
        wt.lock_read()
 
686
        self.addCleanup(wt.unlock)
545
687
        transform.new_file('set_on_creation', root, 'Set on creation', 'soc',
546
688
                           True)
547
689
        sac = transform.new_file('set_after_creation', root,
942
1084
        transform.cancel_creation(parent)
943
1085
        transform.finalize()
944
1086
 
 
1087
    def test_change_entry(self):
 
1088
        txt = 'bzrlib.transform.change_entry was deprecated in version 0.90.'
 
1089
        self.callDeprecated([txt], change_entry, None, None, None, None, None,
 
1090
            None, None, None)
 
1091
 
 
1092
    def test_case_insensitive_clash(self):
 
1093
        self.requireFeature(CaseInsensitiveFilesystemFeature)
 
1094
        def tt_helper():
 
1095
            wt = self.make_branch_and_tree('.')
 
1096
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1097
            try:
 
1098
                tt.new_file('foo', tt.root, 'bar')
 
1099
                tt.new_file('Foo', tt.root, 'spam')
 
1100
                # Lie to tt that we've already resolved all conflicts.
 
1101
                tt.apply(no_conflicts=True)
 
1102
            except:
 
1103
                wt.unlock()
 
1104
                raise
 
1105
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1106
        self.assertContainsRe(str(err),
 
1107
            "^File exists: .+/foo")
 
1108
 
 
1109
    def test_two_directories_clash(self):
 
1110
        def tt_helper():
 
1111
            wt = self.make_branch_and_tree('.')
 
1112
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1113
            try:
 
1114
                foo_1 = tt.new_directory('foo', tt.root)
 
1115
                tt.new_directory('bar', foo_1)
 
1116
                foo_2 = tt.new_directory('foo', tt.root)
 
1117
                tt.new_directory('baz', foo_2)
 
1118
                # Lie to tt that we've already resolved all conflicts.
 
1119
                tt.apply(no_conflicts=True)
 
1120
            except:
 
1121
                wt.unlock()
 
1122
                raise
 
1123
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1124
        self.assertContainsRe(str(err),
 
1125
            "^File exists: .+/foo")
 
1126
 
 
1127
    def test_two_directories_clash_finalize(self):
 
1128
        def tt_helper():
 
1129
            wt = self.make_branch_and_tree('.')
 
1130
            tt = TreeTransform(wt)  # TreeTransform obtains write lock
 
1131
            try:
 
1132
                foo_1 = tt.new_directory('foo', tt.root)
 
1133
                tt.new_directory('bar', foo_1)
 
1134
                foo_2 = tt.new_directory('foo', tt.root)
 
1135
                tt.new_directory('baz', foo_2)
 
1136
                # Lie to tt that we've already resolved all conflicts.
 
1137
                tt.apply(no_conflicts=True)
 
1138
            except:
 
1139
                tt.finalize()
 
1140
                raise
 
1141
        err = self.assertRaises(errors.FileExists, tt_helper)
 
1142
        self.assertContainsRe(str(err),
 
1143
            "^File exists: .+/foo")
 
1144
 
945
1145
 
946
1146
class TransformGroup(object):
 
1147
 
947
1148
    def __init__(self, dirname, root_id):
948
1149
        self.name = dirname
949
1150
        os.mkdir(dirname)
1035
1236
        self.assertSubset(merge_modified, modified)
1036
1237
        self.assertEqual(len(merge_modified), len(modified))
1037
1238
        this.wt.remove('b')
1038
 
        this.wt.revert([])
 
1239
        this.wt.revert()
1039
1240
 
1040
1241
    def test_file_merge(self):
1041
 
        if not has_symlinks():
1042
 
            raise TestSkipped('Symlinks are not supported on this platform')
 
1242
        self.requireFeature(SymlinkFeature)
1043
1243
        root_id = generate_ids.gen_root_id()
1044
1244
        base = TransformGroup("BASE", root_id)
1045
1245
        this = TransformGroup("THIS", root_id)
1147
1347
 
1148
1348
class TestBuildTree(tests.TestCaseWithTransport):
1149
1349
 
1150
 
    def test_build_tree(self):
1151
 
        if not has_symlinks():
1152
 
            raise TestSkipped('Test requires symlink support')
 
1350
    def test_build_tree_with_symlinks(self):
 
1351
        self.requireFeature(SymlinkFeature)
1153
1352
        os.mkdir('a')
1154
1353
        a = BzrDir.create_standalone_workingtree('a')
1155
1354
        os.mkdir('a/foo')
1203
1402
 
1204
1403
    def test_symlink_conflict_handling(self):
1205
1404
        """Ensure that when building trees, conflict handling is done"""
1206
 
        if not has_symlinks():
1207
 
            raise TestSkipped('Test requires symlink support')
 
1405
        self.requireFeature(SymlinkFeature)
1208
1406
        source = self.make_branch_and_tree('source')
1209
1407
        os.symlink('foo', 'source/symlink')
1210
1408
        source.add('symlink', 'new-symlink')
1301
1499
        # children of non-root directories should not be renamed
1302
1500
        self.assertEqual(2, transform_result.rename_count)
1303
1501
 
 
1502
    def test_build_tree_accelerator_tree(self):
 
1503
        source = self.make_branch_and_tree('source')
 
1504
        self.build_tree_contents([('source/file1', 'A')])
 
1505
        self.build_tree_contents([('source/file2', 'B')])
 
1506
        source.add(['file1', 'file2'], ['file1-id', 'file2-id'])
 
1507
        source.commit('commit files')
 
1508
        self.build_tree_contents([('source/file2', 'C')])
 
1509
        calls = []
 
1510
        real_source_get_file = source.get_file
 
1511
        def get_file(file_id, path=None):
 
1512
            calls.append(file_id)
 
1513
            return real_source_get_file(file_id, path)
 
1514
        source.get_file = get_file
 
1515
        source.lock_read()
 
1516
        self.addCleanup(source.unlock)
 
1517
        target = self.make_branch_and_tree('target')
 
1518
        revision_tree = source.basis_tree()
 
1519
        revision_tree.lock_read()
 
1520
        self.addCleanup(revision_tree.unlock)
 
1521
        build_tree(revision_tree, target, source)
 
1522
        self.assertEqual(['file1-id'], calls)
 
1523
        target.lock_read()
 
1524
        self.addCleanup(target.unlock)
 
1525
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1526
 
 
1527
    def test_build_tree_accelerator_tree_missing_file(self):
 
1528
        source = self.make_branch_and_tree('source')
 
1529
        self.build_tree_contents([('source/file1', 'A')])
 
1530
        self.build_tree_contents([('source/file2', 'B')])
 
1531
        source.add(['file1', 'file2'])
 
1532
        source.commit('commit files')
 
1533
        os.unlink('source/file1')
 
1534
        source.remove(['file2'])
 
1535
        target = self.make_branch_and_tree('target')
 
1536
        revision_tree = source.basis_tree()
 
1537
        revision_tree.lock_read()
 
1538
        self.addCleanup(revision_tree.unlock)
 
1539
        build_tree(revision_tree, target, source)
 
1540
        target.lock_read()
 
1541
        self.addCleanup(target.unlock)
 
1542
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1543
 
 
1544
    def test_build_tree_accelerator_wrong_kind(self):
 
1545
        source = self.make_branch_and_tree('source')
 
1546
        self.build_tree_contents([('source/file1', '')])
 
1547
        self.build_tree_contents([('source/file2', '')])
 
1548
        source.add(['file1', 'file2'], ['file1-id', 'file2-id'])
 
1549
        source.commit('commit files')
 
1550
        os.unlink('source/file2')
 
1551
        self.build_tree_contents([('source/file2/', 'C')])
 
1552
        os.unlink('source/file1')
 
1553
        os.symlink('file2', 'source/file1')
 
1554
        calls = []
 
1555
        real_source_get_file = source.get_file
 
1556
        def get_file(file_id, path=None):
 
1557
            calls.append(file_id)
 
1558
            return real_source_get_file(file_id, path)
 
1559
        source.get_file = get_file
 
1560
        source.lock_read()
 
1561
        self.addCleanup(source.unlock)
 
1562
        target = self.make_branch_and_tree('target')
 
1563
        revision_tree = source.basis_tree()
 
1564
        revision_tree.lock_read()
 
1565
        self.addCleanup(revision_tree.unlock)
 
1566
        build_tree(revision_tree, target, source)
 
1567
        self.assertEqual([], calls)
 
1568
        target.lock_read()
 
1569
        self.addCleanup(target.unlock)
 
1570
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1571
 
 
1572
    def test_build_tree_accelerator_tree_moved(self):
 
1573
        source = self.make_branch_and_tree('source')
 
1574
        self.build_tree_contents([('source/file1', 'A')])
 
1575
        source.add(['file1'], ['file1-id'])
 
1576
        source.commit('commit files')
 
1577
        source.rename_one('file1', 'file2')
 
1578
        source.lock_read()
 
1579
        self.addCleanup(source.unlock)
 
1580
        target = self.make_branch_and_tree('target')
 
1581
        revision_tree = source.basis_tree()
 
1582
        revision_tree.lock_read()
 
1583
        self.addCleanup(revision_tree.unlock)
 
1584
        build_tree(revision_tree, target, source)
 
1585
        target.lock_read()
 
1586
        self.addCleanup(target.unlock)
 
1587
        self.assertEqual([], list(target._iter_changes(revision_tree)))
 
1588
 
1304
1589
 
1305
1590
class MockTransform(object):
1306
1591
 
1319
1604
        object.__init__(self)
1320
1605
        self.name = "name"
1321
1606
 
 
1607
 
1322
1608
class TestGetBackupName(TestCase):
1323
1609
    def test_get_backup_name(self):
1324
1610
        tt = MockTransform()
1332
1618
        self.assertEqual(name, 'name.~1~')
1333
1619
        name = get_backup_name(MockEntry(), {'a':['1', '2', '3']}, 'a', tt)
1334
1620
        self.assertEqual(name, 'name.~4~')
 
1621
 
 
1622
 
 
1623
class TestFileMover(tests.TestCaseWithTransport):
 
1624
 
 
1625
    def test_file_mover(self):
 
1626
        self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
 
1627
        mover = _FileMover()
 
1628
        mover.rename('a', 'q')
 
1629
        self.failUnlessExists('q')
 
1630
        self.failIfExists('a')
 
1631
        self.failUnlessExists('q/b')
 
1632
        self.failUnlessExists('c')
 
1633
        self.failUnlessExists('c/d')
 
1634
 
 
1635
    def test_pre_delete_rollback(self):
 
1636
        self.build_tree(['a/'])
 
1637
        mover = _FileMover()
 
1638
        mover.pre_delete('a', 'q')
 
1639
        self.failUnlessExists('q')
 
1640
        self.failIfExists('a')
 
1641
        mover.rollback()
 
1642
        self.failIfExists('q')
 
1643
        self.failUnlessExists('a')
 
1644
 
 
1645
    def test_apply_deletions(self):
 
1646
        self.build_tree(['a/', 'b/'])
 
1647
        mover = _FileMover()
 
1648
        mover.pre_delete('a', 'q')
 
1649
        mover.pre_delete('b', 'r')
 
1650
        self.failUnlessExists('q')
 
1651
        self.failUnlessExists('r')
 
1652
        self.failIfExists('a')
 
1653
        self.failIfExists('b')
 
1654
        mover.apply_deletions()
 
1655
        self.failIfExists('q')
 
1656
        self.failIfExists('r')
 
1657
        self.failIfExists('a')
 
1658
        self.failIfExists('b')
 
1659
 
 
1660
    def test_file_mover_rollback(self):
 
1661
        self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
 
1662
        mover = _FileMover()
 
1663
        mover.rename('c/d', 'c/f')
 
1664
        mover.rename('c/e', 'c/d')
 
1665
        try:
 
1666
            mover.rename('a', 'c')
 
1667
        except errors.FileExists, e:
 
1668
            mover.rollback()
 
1669
        self.failUnlessExists('a')
 
1670
        self.failUnlessExists('c/d')
 
1671
 
 
1672
 
 
1673
class Bogus(Exception):
 
1674
    pass
 
1675
 
 
1676
 
 
1677
class TestTransformRollback(tests.TestCaseWithTransport):
 
1678
 
 
1679
    class ExceptionFileMover(_FileMover):
 
1680
 
 
1681
        def __init__(self, bad_source=None, bad_target=None):
 
1682
            _FileMover.__init__(self)
 
1683
            self.bad_source = bad_source
 
1684
            self.bad_target = bad_target
 
1685
 
 
1686
        def rename(self, source, target):
 
1687
            if (self.bad_source is not None and
 
1688
                source.endswith(self.bad_source)):
 
1689
                raise Bogus
 
1690
            elif (self.bad_target is not None and
 
1691
                target.endswith(self.bad_target)):
 
1692
                raise Bogus
 
1693
            else:
 
1694
                _FileMover.rename(self, source, target)
 
1695
 
 
1696
    def test_rollback_rename(self):
 
1697
        tree = self.make_branch_and_tree('.')
 
1698
        self.build_tree(['a/', 'a/b'])
 
1699
        tt = TreeTransform(tree)
 
1700
        self.addCleanup(tt.finalize)
 
1701
        a_id = tt.trans_id_tree_path('a')
 
1702
        tt.adjust_path('c', tt.root, a_id)
 
1703
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
 
1704
        self.assertRaises(Bogus, tt.apply,
 
1705
                          _mover=self.ExceptionFileMover(bad_source='a'))
 
1706
        self.failUnlessExists('a')
 
1707
        self.failUnlessExists('a/b')
 
1708
        tt.apply()
 
1709
        self.failUnlessExists('c')
 
1710
        self.failUnlessExists('c/d')
 
1711
 
 
1712
    def test_rollback_rename_into_place(self):
 
1713
        tree = self.make_branch_and_tree('.')
 
1714
        self.build_tree(['a/', 'a/b'])
 
1715
        tt = TreeTransform(tree)
 
1716
        self.addCleanup(tt.finalize)
 
1717
        a_id = tt.trans_id_tree_path('a')
 
1718
        tt.adjust_path('c', tt.root, a_id)
 
1719
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
 
1720
        self.assertRaises(Bogus, tt.apply,
 
1721
                          _mover=self.ExceptionFileMover(bad_target='c/d'))
 
1722
        self.failUnlessExists('a')
 
1723
        self.failUnlessExists('a/b')
 
1724
        tt.apply()
 
1725
        self.failUnlessExists('c')
 
1726
        self.failUnlessExists('c/d')
 
1727
 
 
1728
    def test_rollback_deletion(self):
 
1729
        tree = self.make_branch_and_tree('.')
 
1730
        self.build_tree(['a/', 'a/b'])
 
1731
        tt = TreeTransform(tree)
 
1732
        self.addCleanup(tt.finalize)
 
1733
        a_id = tt.trans_id_tree_path('a')
 
1734
        tt.delete_contents(a_id)
 
1735
        tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
 
1736
        self.assertRaises(Bogus, tt.apply,
 
1737
                          _mover=self.ExceptionFileMover(bad_target='d'))
 
1738
        self.failUnlessExists('a')
 
1739
        self.failUnlessExists('a/b')
 
1740
 
 
1741
    def test_resolve_no_parent(self):
 
1742
        wt = self.make_branch_and_tree('.')
 
1743
        tt = TreeTransform(wt)
 
1744
        self.addCleanup(tt.finalize)
 
1745
        parent = tt.trans_id_file_id('parent-id')
 
1746
        tt.new_file('file', parent, 'Contents')
 
1747
        resolve_conflicts(tt)