2464
2464
self.assertPathExists('a/b')
2467
class TestFinalizeRobustness(tests.TestCaseWithTransport):
2468
"""Ensure treetransform creation errors can be safely cleaned up after"""
2470
def _override_globals_in_method(self, instance, method_name, globals):
2471
"""Replace method on instance with one with updated globals"""
2473
func = getattr(instance, method_name).im_func
2474
new_globals = dict(func.func_globals)
2475
new_globals.update(globals)
2476
new_func = types.FunctionType(func.func_code, new_globals,
2477
func.func_name, func.func_defaults)
2478
setattr(instance, method_name,
2479
types.MethodType(new_func, instance, instance.__class__))
2480
self.addCleanup(delattr, instance, method_name)
2483
def _fake_open_raises_before(name, mode):
2484
"""Like open() but raises before doing anything"""
2488
def _fake_open_raises_after(name, mode):
2489
"""Like open() but raises after creating file without returning"""
2490
open(name, mode).close()
2493
def create_transform_and_root_trans_id(self):
2494
"""Setup a transform creating a file in limbo"""
2495
tree = self.make_branch_and_tree('.')
2496
tt = TreeTransform(tree)
2497
return tt, tt.create_path("a", tt.root)
2499
def create_transform_and_subdir_trans_id(self):
2500
"""Setup a transform creating a directory containing a file in limbo"""
2501
tree = self.make_branch_and_tree('.')
2502
tt = TreeTransform(tree)
2503
d_trans_id = tt.create_path("d", tt.root)
2504
tt.create_directory(d_trans_id)
2505
f_trans_id = tt.create_path("a", d_trans_id)
2506
tt.adjust_path("a", d_trans_id, f_trans_id)
2507
return tt, f_trans_id
2509
def test_root_create_file_open_raises_before_creation(self):
2510
tt, trans_id = self.create_transform_and_root_trans_id()
2511
self._override_globals_in_method(tt, "create_file",
2512
{"open": self._fake_open_raises_before})
2513
self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
2514
path = tt._limbo_name(trans_id)
2515
self.assertPathDoesNotExist(path)
2517
self.assertPathDoesNotExist(tt._limbodir)
2519
def test_root_create_file_open_raises_after_creation(self):
2520
tt, trans_id = self.create_transform_and_root_trans_id()
2521
self._override_globals_in_method(tt, "create_file",
2522
{"open": self._fake_open_raises_after})
2523
self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
2524
path = tt._limbo_name(trans_id)
2525
self.assertPathExists(path)
2527
self.assertPathDoesNotExist(path)
2528
self.assertPathDoesNotExist(tt._limbodir)
2530
def test_subdir_create_file_open_raises_before_creation(self):
2531
tt, trans_id = self.create_transform_and_subdir_trans_id()
2532
self._override_globals_in_method(tt, "create_file",
2533
{"open": self._fake_open_raises_before})
2534
self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
2535
path = tt._limbo_name(trans_id)
2536
self.assertPathDoesNotExist(path)
2538
self.assertPathDoesNotExist(tt._limbodir)
2540
def test_subdir_create_file_open_raises_after_creation(self):
2541
tt, trans_id = self.create_transform_and_subdir_trans_id()
2542
self._override_globals_in_method(tt, "create_file",
2543
{"open": self._fake_open_raises_after})
2544
self.assertRaises(RuntimeError, tt.create_file, ["contents"], trans_id)
2545
path = tt._limbo_name(trans_id)
2546
self.assertPathExists(path)
2548
self.assertPathDoesNotExist(path)
2549
self.assertPathDoesNotExist(tt._limbodir)
2551
def test_rename_in_limbo_rename_raises_after_rename(self):
2552
tt, trans_id = self.create_transform_and_root_trans_id()
2553
parent1 = tt.new_directory('parent1', tt.root)
2554
child1 = tt.new_file('child1', parent1, 'contents')
2555
parent2 = tt.new_directory('parent2', tt.root)
2557
class FakeOSModule(object):
2558
def rename(self, old, new):
2561
self._override_globals_in_method(tt, "_rename_in_limbo",
2562
{"os": FakeOSModule()})
2564
RuntimeError, tt.adjust_path, "child1", parent2, child1)
2565
path = osutils.pathjoin(tt._limbo_name(parent2), "child1")
2566
self.assertPathExists(path)
2568
self.assertPathDoesNotExist(path)
2569
self.assertPathDoesNotExist(tt._limbodir)
2571
def test_rename_in_limbo_rename_raises_before_rename(self):
2572
tt, trans_id = self.create_transform_and_root_trans_id()
2573
parent1 = tt.new_directory('parent1', tt.root)
2574
child1 = tt.new_file('child1', parent1, 'contents')
2575
parent2 = tt.new_directory('parent2', tt.root)
2577
class FakeOSModule(object):
2578
def rename(self, old, new):
2580
self._override_globals_in_method(tt, "_rename_in_limbo",
2581
{"os": FakeOSModule()})
2583
RuntimeError, tt.adjust_path, "child1", parent2, child1)
2584
path = osutils.pathjoin(tt._limbo_name(parent1), "child1")
2585
self.assertPathExists(path)
2587
self.assertPathDoesNotExist(path)
2588
self.assertPathDoesNotExist(tt._limbodir)
2467
2591
class TestTransformMissingParent(tests.TestCaseWithTransport):
2469
2593
def make_tt_with_versioned_dir(self):