814
815
self.assertIs(None, self.wt.path2id('parent'))
815
816
self.assertIs(None, self.wt.path2id('parent.new'))
818
def test_resolve_conflicts_missing_parent(self):
819
wt = self.make_branch_and_tree('.')
820
tt = TreeTransform(wt)
821
self.addCleanup(tt.finalize)
822
parent = tt.trans_id_file_id('parent-id')
823
tt.new_file('file', parent, 'Contents')
824
raw_conflicts = resolve_conflicts(tt)
825
# Since the directory doesn't exist it's seen as 'missing'. So
826
# 'resolve_conflicts' create a conflict asking for it to be created.
827
self.assertLength(1, raw_conflicts)
828
self.assertEqual(('missing parent', 'Created directory', 'new-1'),
830
# apply fail since the missing directory doesn't exist
831
self.assertRaises(errors.NoFinalPath, tt.apply)
817
833
def test_moving_versioned_directories(self):
818
834
create, root = self.get_transform()
819
835
kansas = create.new_directory('kansas', root, 'kansas-id')
2178
2195
self.assertEqual('tree', revision.properties['branch-nick'])
2181
class MockTransform(object):
2183
def has_named_child(self, by_parent, parent_id, name):
2184
for child_id in by_parent[parent_id]:
2188
elif name == "name.~%s~" % child_id:
2193
class MockEntry(object):
2195
object.__init__(self)
2199
class TestGetBackupName(TestCase):
2200
def test_get_backup_name(self):
2198
class TestBackupName(tests.TestCase):
2200
def test_deprecations(self):
2201
class MockTransform(object):
2203
def has_named_child(self, by_parent, parent_id, name):
2204
return name in by_parent.get(parent_id, [])
2206
class MockEntry(object):
2209
object.__init__(self)
2201
2212
tt = MockTransform()
2202
name = get_backup_name(MockEntry(), {'a':[]}, 'a', tt)
2203
self.assertEqual(name, 'name.~1~')
2204
name = get_backup_name(MockEntry(), {'a':['1']}, 'a', tt)
2205
self.assertEqual(name, 'name.~2~')
2206
name = get_backup_name(MockEntry(), {'a':['2']}, 'a', tt)
2207
self.assertEqual(name, 'name.~1~')
2208
name = get_backup_name(MockEntry(), {'a':['2'], 'b':[]}, 'b', tt)
2209
self.assertEqual(name, 'name.~1~')
2210
name = get_backup_name(MockEntry(), {'a':['1', '2', '3']}, 'a', tt)
2211
self.assertEqual(name, 'name.~4~')
2213
name1 = self.applyDeprecated(
2214
symbol_versioning.deprecated_in((2, 3, 0)),
2215
transform.get_backup_name, MockEntry(), {'a':[]}, 'a', tt)
2216
self.assertEqual('name.~1~', name1)
2217
name2 = self.applyDeprecated(
2218
symbol_versioning.deprecated_in((2, 3, 0)),
2219
transform._get_backup_name, 'name', {'a':['name.~1~']}, 'a', tt)
2220
self.assertEqual('name.~2~', name2)
2214
2223
class TestFileMover(tests.TestCaseWithTransport):
2329
2338
self.failUnlessExists('a')
2330
2339
self.failUnlessExists('a/b')
2332
def test_resolve_no_parent(self):
2342
class TestTransformMissingParent(tests.TestCaseWithTransport):
2344
def make_tt_with_versioned_dir(self):
2333
2345
wt = self.make_branch_and_tree('.')
2346
self.build_tree(['dir/',])
2347
wt.add(['dir'], ['dir-id'])
2348
wt.commit('Create dir')
2334
2349
tt = TreeTransform(wt)
2335
2350
self.addCleanup(tt.finalize)
2336
parent = tt.trans_id_file_id('parent-id')
2337
tt.new_file('file', parent, 'Contents')
2338
resolve_conflicts(tt)
2353
def test_resolve_create_parent_for_versioned_file(self):
2354
wt, tt = self.make_tt_with_versioned_dir()
2355
dir_tid = tt.trans_id_tree_file_id('dir-id')
2356
file_tid = tt.new_file('file', dir_tid, 'Contents', file_id='file-id')
2357
tt.delete_contents(dir_tid)
2358
tt.unversion_file(dir_tid)
2359
conflicts = resolve_conflicts(tt)
2360
# one conflict for the missing directory, one for the unversioned
2362
self.assertLength(2, conflicts)
2364
def test_non_versioned_file_create_conflict(self):
2365
wt, tt = self.make_tt_with_versioned_dir()
2366
dir_tid = tt.trans_id_tree_file_id('dir-id')
2367
tt.new_file('file', dir_tid, 'Contents')
2368
tt.delete_contents(dir_tid)
2369
tt.unversion_file(dir_tid)
2370
conflicts = resolve_conflicts(tt)
2371
# no conflicts or rather: orphaning 'file' resolve the 'dir' conflict
2372
self.assertLength(1, conflicts)
2373
self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
2341
2377
A_ENTRY = ('a-id', ('a', 'a'), True, (True, True),
2342
2378
('TREE_ROOT', 'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2343
2379
(False, False))
2344
2380
ROOT_ENTRY = ('TREE_ROOT', ('', ''), False, (True, True), (None, None),
2345
('', ''), ('directory', 'directory'), (False, None))
2381
('', ''), ('directory', 'directory'), (False, False))
2348
2384
class TestTransformPreview(tests.TestCaseWithTransport):
3218
3254
trans_id = tt.trans_id_tree_path('file')
3219
3255
self.assertEqual((LINES_ONE,),
3220
3256
tt._get_parents_texts(trans_id))
3259
class TestOrphan(tests.TestCaseWithTransport):
3261
def test_no_orphan_for_transform_preview(self):
3262
tree = self.make_branch_and_tree('tree')
3263
tt = transform.TransformPreview(tree)
3264
self.addCleanup(tt.finalize)
3265
self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
3267
def _set_orphan_policy(self, wt, policy):
3268
wt.branch.get_config().set_user_option('bzr.transform.orphan_policy',
3271
def _prepare_orphan(self, wt):
3272
self.build_tree(['dir/', 'dir/file', 'dir/foo'])
3273
wt.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
3274
wt.commit('add dir and file ignoring foo')
3275
tt = transform.TreeTransform(wt)
3276
self.addCleanup(tt.finalize)
3277
# dir and bar are deleted
3278
dir_tid = tt.trans_id_tree_path('dir')
3279
file_tid = tt.trans_id_tree_path('dir/file')
3280
orphan_tid = tt.trans_id_tree_path('dir/foo')
3281
tt.delete_contents(file_tid)
3282
tt.unversion_file(file_tid)
3283
tt.delete_contents(dir_tid)
3284
tt.unversion_file(dir_tid)
3285
# There should be a conflict because dir still contain foo
3286
raw_conflicts = tt.find_conflicts()
3287
self.assertLength(1, raw_conflicts)
3288
self.assertEqual(('missing parent', 'new-1'), raw_conflicts[0])
3289
return tt, orphan_tid
3291
def test_new_orphan_created(self):
3292
wt = self.make_branch_and_tree('.')
3293
self._set_orphan_policy(wt, 'move')
3294
tt, orphan_tid = self._prepare_orphan(wt)
3297
warnings.append(args[0] % args[1:])
3298
self.overrideAttr(trace, 'warning', warning)
3299
remaining_conflicts = resolve_conflicts(tt)
3300
self.assertEquals(['dir/foo has been orphaned in bzr-orphans'],
3302
# Yeah for resolved conflicts !
3303
self.assertLength(0, remaining_conflicts)
3304
# We have a new orphan
3305
self.assertEquals('foo.~1~', tt.final_name(orphan_tid))
3306
self.assertEquals('bzr-orphans',
3307
tt.final_name(tt.final_parent(orphan_tid)))
3309
def test_never_orphan(self):
3310
wt = self.make_branch_and_tree('.')
3311
self._set_orphan_policy(wt, 'conflict')
3312
tt, orphan_tid = self._prepare_orphan(wt)
3313
remaining_conflicts = resolve_conflicts(tt)
3314
self.assertLength(1, remaining_conflicts)
3315
self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3316
remaining_conflicts.pop())
3318
def test_orphan_error(self):
3319
def bogus_orphan(tt, orphan_id, parent_id):
3320
raise transform.OrphaningError(tt.final_name(orphan_id),
3321
tt.final_name(parent_id))
3322
transform.orphaning_registry.register('bogus', bogus_orphan,
3323
'Raise an error when orphaning')
3324
wt = self.make_branch_and_tree('.')
3325
self._set_orphan_policy(wt, 'bogus')
3326
tt, orphan_tid = self._prepare_orphan(wt)
3327
remaining_conflicts = resolve_conflicts(tt)
3328
self.assertLength(1, remaining_conflicts)
3329
self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3330
remaining_conflicts.pop())
3332
def test_unknown_orphan_policy(self):
3333
wt = self.make_branch_and_tree('.')
3334
# Set a fictional policy nobody ever implemented
3335
self._set_orphan_policy(wt, 'donttouchmypreciouuus')
3336
tt, orphan_tid = self._prepare_orphan(wt)
3339
warnings.append(args[0] % args[1:])
3340
self.overrideAttr(trace, 'warning', warning)
3341
remaining_conflicts = resolve_conflicts(tt)
3342
# We fallback to the default policy which create a conflict
3343
self.assertLength(1, remaining_conflicts)
3344
self.assertEqual(('deleting parent', 'Not deleting', 'new-1'),
3345
remaining_conflicts.pop())
3346
self.assertLength(1, warnings)
3347
self.assertStartsWith(warnings[0], 'donttouchmypreciouuus')