153
162
modified_paths = transform.apply().modified_paths
154
163
with self.wt.get_file('name') as f:
155
164
self.assertEqual(b'contents', f.read())
156
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
165
if self.wt.supports_setting_file_ids():
166
self.assertEqual(self.wt.path2id('name'), b'my_pretties')
157
167
self.assertIs(self.wt.is_executable('name'), True)
158
168
self.assertIs(self.wt.is_executable('name2'), False)
159
169
self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
160
170
self.assertEqual(len(modified_paths), 3)
161
tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
162
(b'ozzie', b'my_pretties', b'my_pretties2')]
163
self.assertSubset(tree_mod_paths, modified_paths)
171
if self.wt.supports_setting_file_ids():
172
tree_mod_paths = [self.wt.abspath(self.wt.id2path(f)) for f in
173
(b'ozzie', b'my_pretties', b'my_pretties2')]
174
self.assertSubset(tree_mod_paths, modified_paths)
164
175
# is it safe to finalize repeatedly?
165
176
transform.finalize()
166
177
transform.finalize()
168
179
def test_apply_informs_tree_of_observed_sha1(self):
169
180
trans, root, contents, sha1 = self.transform_for_sha1_test()
181
from ...bzr.workingtree import InventoryWorkingTree
182
if not isinstance(self.wt, InventoryWorkingTree):
183
self.skipTest('not a bzr working tree')
170
184
trans_id = trans.new_file('file1', root, contents, file_id=b'file1-id',
427
454
[('non-directory parent', trans_id)])
428
455
tinman_id = transform.trans_id_tree_path('tinman')
429
456
transform.adjust_path('name', tinman_id, trans_id2)
430
self.assertEqual(transform.find_raw_conflicts(),
431
[('unversioned parent', tinman_id),
432
('missing parent', tinman_id)])
457
if self.wt.has_versioned_directories():
458
self.assertEqual(transform.find_raw_conflicts(),
459
[('unversioned parent', tinman_id),
460
('missing parent', tinman_id)])
462
self.assertEqual(transform.find_raw_conflicts(),
463
[('missing parent', tinman_id)])
433
464
lion_id = transform.create_path('lion', root)
434
self.assertEqual(transform.find_raw_conflicts(),
435
[('unversioned parent', tinman_id),
436
('missing parent', tinman_id)])
465
if self.wt.has_versioned_directories():
466
self.assertEqual(transform.find_raw_conflicts(),
467
[('unversioned parent', tinman_id),
468
('missing parent', tinman_id)])
470
self.assertEqual(transform.find_raw_conflicts(),
471
[('missing parent', tinman_id)])
437
472
transform.adjust_path('name', lion_id, trans_id2)
438
self.assertEqual(transform.find_raw_conflicts(),
439
[('unversioned parent', lion_id),
440
('missing parent', lion_id)])
473
if self.wt.has_versioned_directories():
474
self.assertEqual(transform.find_raw_conflicts(),
475
[('unversioned parent', lion_id),
476
('missing parent', lion_id)])
478
self.assertEqual(transform.find_raw_conflicts(),
479
[('missing parent', lion_id)])
441
480
transform.version_file(lion_id, file_id=b"Courage")
442
481
self.assertEqual(transform.find_raw_conflicts(),
443
482
[('missing parent', lion_id),
840
892
conflicts.delete_versioned(oz)
841
893
emerald = conflicts.trans_id_tree_path('oz/emeraldcity')
842
894
# set up MissingParent conflict
843
munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
895
if conflicts._tree.supports_setting_file_ids():
896
munchkincity = conflicts.trans_id_file_id(b'munchkincity-id')
898
munchkincity = conflicts.assign_id()
844
899
conflicts.adjust_path('munchkincity', root, munchkincity)
845
900
conflicts.new_directory('auntem', munchkincity, b'auntem-id')
846
901
# set up parent loop
847
902
conflicts.adjust_path('emeraldcity', emerald, emerald)
848
return conflicts, emerald, oz, old_dorothy, new_dorothy
903
return conflicts, emerald, oz, old_dorothy, new_dorothy, munchkincity
850
905
def test_conflict_resolution(self):
851
conflicts, emerald, oz, old_dorothy, new_dorothy =\
906
conflicts, emerald, oz, old_dorothy, new_dorothy, munchkincity =\
852
907
self.get_conflicted()
853
908
resolve_conflicts(conflicts)
854
909
self.assertEqual(conflicts.final_name(old_dorothy), 'dorothy.moved')
855
self.assertIs(conflicts.final_file_id(old_dorothy), None)
910
if self.wt.supports_setting_file_ids():
911
self.assertIs(conflicts.final_file_id(old_dorothy), None)
912
self.assertEqual(conflicts.final_file_id(new_dorothy), b'dorothy-id')
856
913
self.assertEqual(conflicts.final_name(new_dorothy), 'dorothy')
857
self.assertEqual(conflicts.final_file_id(new_dorothy), b'dorothy-id')
858
914
self.assertEqual(conflicts.final_parent(emerald), oz)
859
915
conflicts.apply()
861
917
def test_cook_conflicts(self):
862
tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
918
tt, emerald, oz, old_dorothy, new_dorothy, munchkincity = self.get_conflicted()
863
919
raw_conflicts = resolve_conflicts(tt)
864
cooked_conflicts = tt.cook_conflicts(raw_conflicts)
865
duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
866
'dorothy', None, b'dorothy-id')
867
self.assertEqual(cooked_conflicts[0], duplicate)
868
duplicate_id = DuplicateID('Unversioned existing file',
869
'dorothy.moved', 'dorothy', None,
871
self.assertEqual(cooked_conflicts[1], duplicate_id)
872
missing_parent = MissingParent('Created directory', 'munchkincity',
874
deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
875
self.assertEqual(cooked_conflicts[2], missing_parent)
876
unversioned_parent = UnversionedParent('Versioned directory',
879
unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
881
self.assertEqual(cooked_conflicts[3], unversioned_parent)
882
parent_loop = ParentLoop(
883
'Cancelled move', 'oz/emeraldcity',
884
'oz/emeraldcity', b'emerald-id', b'emerald-id')
885
self.assertEqual(cooked_conflicts[4], deleted_parent)
886
self.assertEqual(cooked_conflicts[5], unversioned_parent2)
887
self.assertEqual(cooked_conflicts[6], parent_loop)
888
self.assertEqual(len(cooked_conflicts), 7)
920
cooked_conflicts = list(tt.cook_conflicts(raw_conflicts))
921
if self.wt.supports_setting_file_ids():
922
duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
923
'dorothy', None, b'dorothy-id')
924
self.assertEqual(cooked_conflicts[0], duplicate)
925
duplicate_id = DuplicateID('Unversioned existing file',
926
'dorothy.moved', 'dorothy', None,
928
self.assertEqual(cooked_conflicts[1], duplicate_id)
929
missing_parent = MissingParent('Created directory', 'munchkincity',
931
deleted_parent = DeletingParent('Not deleting', 'oz', b'oz-id')
932
self.assertEqual(cooked_conflicts[2], missing_parent)
933
unversioned_parent = UnversionedParent('Versioned directory',
936
unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
938
self.assertEqual(cooked_conflicts[3], unversioned_parent)
939
parent_loop = ParentLoop(
940
'Cancelled move', 'oz/emeraldcity',
941
'oz/emeraldcity', b'emerald-id', b'emerald-id')
942
self.assertEqual(cooked_conflicts[4], deleted_parent)
943
self.assertEqual(cooked_conflicts[5], unversioned_parent2)
944
self.assertEqual(cooked_conflicts[6], parent_loop)
945
self.assertEqual(len(cooked_conflicts), 7)
948
set([c.path for c in cooked_conflicts]),
949
set(['oz/emeraldcity', 'oz', 'munchkincity', 'dorothy.moved']))
891
952
def test_string_conflicts(self):
892
tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
953
tt, emerald, oz, old_dorothy, new_dorothy, munchkincity = self.get_conflicted()
893
954
raw_conflicts = resolve_conflicts(tt)
894
cooked_conflicts = tt.cook_conflicts(raw_conflicts)
955
cooked_conflicts = list(tt.cook_conflicts(raw_conflicts))
896
957
conflicts_s = [str(c) for c in cooked_conflicts]
897
958
self.assertEqual(len(cooked_conflicts), len(conflicts_s))
898
self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy. '
899
'Moved existing file to '
901
self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy. '
902
'Unversioned existing file '
904
self.assertEqual(conflicts_s[2], 'Conflict adding files to'
905
' munchkincity. Created directory.')
906
self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
907
' versioned, but has versioned'
908
' children. Versioned directory.')
909
self.assertEqualDiff(
910
conflicts_s[4], "Conflict: can't delete oz because it"
911
" is not empty. Not deleting.")
912
self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
913
' versioned, but has versioned'
914
' children. Versioned directory.')
915
self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
916
' oz/emeraldcity. Cancelled move.')
959
if self.wt.supports_setting_file_ids():
960
self.assertEqual(conflicts_s[0], 'Conflict adding file dorothy. '
961
'Moved existing file to '
963
self.assertEqual(conflicts_s[1], 'Conflict adding id to dorothy. '
964
'Unversioned existing file '
966
self.assertEqual(conflicts_s[2], 'Conflict adding files to'
967
' munchkincity. Created directory.')
968
self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
969
' versioned, but has versioned'
970
' children. Versioned directory.')
971
self.assertEqualDiff(
972
conflicts_s[4], "Conflict: can't delete oz because it"
973
" is not empty. Not deleting.")
974
self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
975
' versioned, but has versioned'
976
' children. Versioned directory.')
977
self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
978
' oz/emeraldcity. Cancelled move.')
981
{'Text conflict in dorothy.moved',
982
'Text conflict in munchkincity',
983
'Text conflict in oz',
984
'Text conflict in oz/emeraldcity'},
985
set([c for c in conflicts_s]))
918
987
def prepare_wrong_parent_kind(self):
919
988
tt, root = self.transform()
920
989
tt.new_file('parent', root, [b'contents'], b'parent-id')
922
991
tt, root = self.transform()
923
parent_id = tt.trans_id_file_id(b'parent-id')
992
parent_id = tt.trans_id_tree_path('parent')
924
993
tt.new_file('child,', parent_id, [b'contents2'], b'file-id')
1142
1222
transform.apply()
1143
1223
transform, root = self.transform()
1145
self.assertEqual([], list(transform.iter_changes()))
1225
self.assertTreeChanges(transform, [])
1146
1226
old = transform.trans_id_tree_path('old')
1147
1227
transform.unversion_file(old)
1148
self.assertEqual([(b'id-1', ('old', None), False, (True, False),
1150
('old', 'old'), ('file', 'file'),
1151
(True, True), False)],
1152
list(transform.iter_changes()))
1228
self.assertTreeChanges(
1230
InventoryTreeChange(
1231
b'id-1', ('old', None), False, (True, False),
1232
(root_id, root_id), ('old', 'old'), ('file', 'file'),
1233
(True, True), False)])
1153
1234
transform.new_directory('new', root, b'id-1')
1154
self.assertEqual([(b'id-1', ('old', 'new'), True, (True, True),
1155
(root_id, root_id), ('old', 'new'),
1156
('file', 'directory'),
1157
(True, False), False)],
1158
list(transform.iter_changes()))
1235
if transform._tree.supports_setting_file_ids():
1236
self.assertTreeChanges(
1238
[InventoryTreeChange(
1239
b'id-1', ('old', 'new'), True, (True, True),
1240
(root_id, root_id), ('old', 'new'),
1241
('file', 'directory'),
1242
(True, False), False)])
1244
self.assertTreeChanges(
1247
(None, 'new'), False, (False, True),
1248
(None, 'new'), (None, 'directory'),
1249
(False, False), False),
1251
('old', None), False, (True, False),
1252
('old', 'old'), ('file', 'file'),
1253
(True, True), False)])
1160
1255
transform.finalize()
1188
1287
old = transform.trans_id_tree_path('old')
1189
1288
subdir = transform.trans_id_tree_path('subdir')
1190
1289
new = transform.trans_id_tree_path('new')
1191
self.assertEqual([], list(transform.iter_changes()))
1290
self.assertTreeChanges(transform, [])
1193
1292
# content deletion
1194
1293
transform.delete_contents(old)
1195
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1197
('old', 'old'), ('file', None),
1198
(False, False), False)],
1199
list(transform.iter_changes()))
1294
self.assertTreeChanges(
1296
[InventoryTreeChange(
1297
b'id-1', ('old', 'old'), True, (True, True),
1299
('old', 'old'), ('file', None),
1300
(False, False), False)])
1201
1302
# content change
1202
1303
transform.create_file([b'blah'], old)
1203
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1205
('old', 'old'), ('file', 'file'),
1206
(False, False), False)],
1207
list(transform.iter_changes()))
1304
self.assertTreeChanges(
1306
[InventoryTreeChange(
1307
b'id-1', ('old', 'old'), True, (True, True),
1309
('old', 'old'), ('file', 'file'),
1310
(False, False), False)])
1208
1311
transform.cancel_deletion(old)
1209
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1211
('old', 'old'), ('file', 'file'),
1212
(False, False), False)],
1213
list(transform.iter_changes()))
1312
self.assertTreeChanges(
1314
[InventoryTreeChange(
1315
b'id-1', ('old', 'old'), True, (True, True),
1317
('old', 'old'), ('file', 'file'),
1318
(False, False), False)])
1214
1319
transform.cancel_creation(old)
1216
1321
# move file_id to a different file
1217
self.assertEqual([], list(transform.iter_changes()))
1322
self.assertTreeChanges(transform, [])
1218
1323
transform.unversion_file(old)
1219
1324
transform.version_file(new, file_id=b'id-1')
1220
1325
transform.adjust_path('old', root, new)
1221
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1223
('old', 'old'), ('file', 'file'),
1224
(False, False), False)],
1225
list(transform.iter_changes()))
1326
if transform._tree.supports_setting_file_ids():
1327
self.assertTreeChanges(
1329
[InventoryTreeChange(
1330
b'id-1', ('old', 'old'), True, (True, True),
1332
('old', 'old'), ('file', 'file'),
1333
(False, False), False)])
1335
self.assertTreeChanges(
1338
(None, 'old'), False, (False, True),
1339
(None, 'old'), (None, 'file'), (False, False), False),
1341
('old', None), False, (True, False), ('old', 'old'),
1342
('file', 'file'), (False, False), False)])
1226
1344
transform.cancel_versioning(new)
1227
1345
transform._removed_id = set()
1230
self.assertEqual([], list(transform.iter_changes()))
1348
self.assertTreeChanges(transform, [])
1231
1349
transform.set_executability(True, old)
1232
self.assertEqual([(b'id-1', ('old', 'old'), False, (True, True),
1234
('old', 'old'), ('file', 'file'),
1235
(False, True), False)],
1236
list(transform.iter_changes()))
1350
self.assertTreeChanges(
1352
[InventoryTreeChange(
1353
b'id-1', ('old', 'old'), False, (True, True),
1355
('old', 'old'), ('file', 'file'),
1356
(False, True), False)])
1237
1357
transform.set_executability(None, old)
1240
self.assertEqual([], list(transform.iter_changes()))
1360
self.assertTreeChanges(transform, [])
1241
1361
transform.adjust_path('new', root, old)
1242
1362
transform._new_parent = {}
1243
self.assertEqual([(b'id-1', ('old', 'new'), False, (True, True),
1245
('old', 'new'), ('file', 'file'),
1246
(False, False), False)],
1247
list(transform.iter_changes()))
1363
self.assertTreeChanges(
1365
[InventoryTreeChange(
1366
b'id-1', ('old', 'new'), False, (True, True),
1368
('old', 'new'), ('file', 'file'),
1369
(False, False), False)])
1248
1370
transform._new_name = {}
1250
1372
# parent directory
1251
self.assertEqual([], list(transform.iter_changes()))
1373
self.assertTreeChanges(transform, [])
1252
1374
transform.adjust_path('new', subdir, old)
1253
1375
transform._new_name = {}
1254
self.assertEqual([(b'id-1', ('old', 'subdir/old'), False,
1255
(True, True), (root_id, b'subdir-id'), ('old', 'old'),
1256
('file', 'file'), (False, False), False)],
1257
list(transform.iter_changes()))
1376
self.assertTreeChanges(
1378
InventoryTreeChange(
1379
b'id-1', ('old', 'subdir/old'), False,
1380
(True, True), (root_id, b'subdir-id'), ('old', 'old'),
1381
('file', 'file'), (False, False), False)])
1258
1382
transform._new_path = {}
1261
1384
transform.finalize()
1386
def assertTreeChanges(self, tt, expected):
1387
# TODO(jelmer): Turn this into a matcher?
1388
actual = list(tt.iter_changes())
1389
if tt._tree.supports_setting_file_ids():
1390
self.assertEqual(expected, actual)
1393
TreeChange(path=c.path, changed_content=c.changed_content,
1394
versioned=c.versioned, name=c.name,
1395
kind=c.kind, executable=c.executable,
1396
copied=c.copied) for c in expected]
1398
TreeChange(path=c.path, changed_content=c.changed_content,
1399
versioned=c.versioned, name=c.name,
1400
kind=c.kind, executable=c.executable,
1401
copied=c.copied) for c in actual]
1402
self.assertEqual(expected, actual)
1263
1404
def test_iter_changes_modified_bleed(self):
1264
1405
root_id = self.wt.path2id('')
1265
1406
"""Modified flag should not bleed from one change to another"""
1273
1414
transform.apply()
1274
1415
transform, root = self.transform()
1276
transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1277
transform.set_executability(True,
1278
transform.trans_id_file_id(b'id-2'))
1280
[(b'id-1', (u'file1', u'file1'), True, (True, True),
1281
(root_id, root_id), ('file1', u'file1'),
1282
('file', None), (False, False), False),
1283
(b'id-2', (u'file2', u'file2'), False, (True, True),
1284
(root_id, root_id), ('file2', u'file2'),
1285
('file', 'file'), (False, True), False)],
1286
list(transform.iter_changes()))
1417
transform.delete_contents(transform.trans_id_tree_path('file1'))
1418
transform.set_executability(True, transform.trans_id_tree_path('file2'))
1419
self.assertTreeChanges(transform, [
1420
InventoryTreeChange(
1421
b'id-1', (u'file1', u'file1'), True, (True, True),
1422
(root_id, root_id), ('file1', u'file1'),
1423
('file', None), (False, False), False),
1424
InventoryTreeChange(
1425
b'id-2', (u'file2', u'file2'), False, (True, True),
1426
(root_id, root_id), ('file2', u'file2'),
1427
('file', 'file'), (False, True), False)])
1288
1429
transform.finalize()