31
31
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
32
32
ReusingTransform, CantMoveRoot,
33
33
PathsNotVersionedError, ExistingLimbo,
34
ExistingPendingDeletion, ImmortalLimbo,
35
ImmortalPendingDeletion, LockError)
34
ImmortalLimbo, LockError)
36
35
from bzrlib.osutils import file_kind, has_symlinks, pathjoin
37
36
from bzrlib.merge import Merge3Merger
38
37
from bzrlib.tests import TestCaseInTempDir, TestSkipped, TestCase
39
38
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths,
40
39
resolve_conflicts, cook_conflicts,
41
40
find_interesting, build_tree, get_backup_name,
42
change_entry, _FileMover)
45
44
class TestTreeTransform(tests.TestCaseWithTransport):
65
64
self.assertRaises(LockError, self.wt.unlock)
66
65
os.rmdir(pathjoin(limbo_name, 'hehe'))
67
66
os.rmdir(limbo_name)
68
os.rmdir(deletion_path)
69
67
transform, root = self.get_transform()
72
def test_existing_pending_deletion(self):
73
transform, root = self.get_transform()
74
deletion_path = self._limbodir = urlutils.local_path_from_url(
75
transform._tree._control_files.controlfilename('pending-deletion'))
76
os.mkdir(pathjoin(deletion_path, 'blocking-directory'))
77
self.assertRaises(ImmortalPendingDeletion, transform.apply)
78
self.assertRaises(LockError, self.wt.unlock)
79
self.assertRaises(ExistingPendingDeletion, self.get_transform)
81
70
def test_build(self):
82
71
transform, root = self.get_transform()
83
72
self.assertIs(transform.get_tree_parent(root), ROOT_PARENT)
1349
1338
self.assertEqual(name, 'name.~1~')
1350
1339
name = get_backup_name(MockEntry(), {'a':['1', '2', '3']}, 'a', tt)
1351
1340
self.assertEqual(name, 'name.~4~')
1354
class TestFileMover(tests.TestCaseWithTransport):
1356
def test_file_mover(self):
1357
self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
1358
mover = _FileMover()
1359
mover.rename('a', 'q')
1360
self.failUnlessExists('q')
1361
self.failIfExists('a')
1362
self.failUnlessExists('q/b')
1363
self.failUnlessExists('c')
1364
self.failUnlessExists('c/d')
1366
def test_pre_delete_rollback(self):
1367
self.build_tree(['a/'])
1368
mover = _FileMover()
1369
mover.pre_delete('a', 'q')
1370
self.failUnlessExists('q')
1371
self.failIfExists('a')
1373
self.failIfExists('q')
1374
self.failUnlessExists('a')
1376
def test_apply_deletions(self):
1377
self.build_tree(['a/', 'b/'])
1378
mover = _FileMover()
1379
mover.pre_delete('a', 'q')
1380
mover.pre_delete('b', 'r')
1381
self.failUnlessExists('q')
1382
self.failUnlessExists('r')
1383
self.failIfExists('a')
1384
self.failIfExists('b')
1385
mover.apply_deletions()
1386
self.failIfExists('q')
1387
self.failIfExists('r')
1388
self.failIfExists('a')
1389
self.failIfExists('b')
1391
def test_file_mover_rollback(self):
1392
self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
1393
mover = _FileMover()
1394
mover.rename('c/d', 'c/f')
1395
mover.rename('c/e', 'c/d')
1397
mover.rename('a', 'c')
1400
self.failUnlessExists('a')
1401
self.failUnlessExists('c/d')
1404
class Bogus(Exception):
1408
class TestTransformRollback(tests.TestCaseWithTransport):
1410
class ExceptionFileMover(_FileMover):
1412
def __init__(self, bad_source=None, bad_target=None):
1413
_FileMover.__init__(self)
1414
self.bad_source = bad_source
1415
self.bad_target = bad_target
1417
def rename(self, source, target):
1418
if (self.bad_source is not None and
1419
source.endswith(self.bad_source)):
1421
elif (self.bad_target is not None and
1422
target.endswith(self.bad_target)):
1425
_FileMover.rename(self, source, target)
1427
def test_rollback_rename(self):
1428
tree = self.make_branch_and_tree('.')
1429
self.build_tree(['a/', 'a/b'])
1430
tt = TreeTransform(tree)
1431
self.addCleanup(tt.finalize)
1432
a_id = tt.trans_id_tree_path('a')
1433
tt.adjust_path('c', tt.root, a_id)
1434
tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
1435
self.assertRaises(Bogus, tt.apply,
1436
_mover=self.ExceptionFileMover(bad_source='a'))
1437
self.failUnlessExists('a')
1438
self.failUnlessExists('a/b')
1440
self.failUnlessExists('c')
1441
self.failUnlessExists('c/d')
1443
def test_rollback_rename_into_place(self):
1444
tree = self.make_branch_and_tree('.')
1445
self.build_tree(['a/', 'a/b'])
1446
tt = TreeTransform(tree)
1447
self.addCleanup(tt.finalize)
1448
a_id = tt.trans_id_tree_path('a')
1449
tt.adjust_path('c', tt.root, a_id)
1450
tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
1451
self.assertRaises(Bogus, tt.apply,
1452
_mover=self.ExceptionFileMover(bad_target='c/d'))
1453
self.failUnlessExists('a')
1454
self.failUnlessExists('a/b')
1456
self.failUnlessExists('c')
1457
self.failUnlessExists('c/d')
1459
def test_rollback_deletion(self):
1460
tree = self.make_branch_and_tree('.')
1461
self.build_tree(['a/', 'a/b'])
1462
tt = TreeTransform(tree)
1463
self.addCleanup(tt.finalize)
1464
a_id = tt.trans_id_tree_path('a')
1465
tt.delete_contents(a_id)
1466
tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
1467
self.assertRaises(Bogus, tt.apply,
1468
_mover=self.ExceptionFileMover(bad_target='d'))
1469
self.failUnlessExists('a')
1470
self.failUnlessExists('a/b')