258
259
fo, st2 = self.wt.get_file_with_stat('two', filtered=False)
260
261
# We only guarantee 2s resolution
261
self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
263
abs(creation_mtime - st1.st_mtime) < 2.0,
262
264
"%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
263
265
# But if we have more than that, all files should get the same result
264
266
self.assertEqual(st1.st_mtime, st2.st_mtime)
290
292
def test_add_two_roots(self):
291
293
transform, root = self.get_transform()
292
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
293
new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
294
transform.new_directory('', ROOT_PARENT, b'new-root-id')
295
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
294
296
self.assertRaises(ValueError, transform.fixup_new_roots)
296
298
def test_retain_existing_root(self):
310
312
def test_add_unversioned_root(self):
311
313
transform, root = self.get_transform()
312
new_trans_id = transform.new_directory('', ROOT_PARENT, None)
314
transform.new_directory('', ROOT_PARENT, None)
313
315
transform.delete_contents(transform.root)
314
316
transform.fixup_new_roots()
315
317
self.assertNotIn(transform.root, transform._new_id)
325
327
self.assertEqual(old_root_id, self.wt.get_root_id())
327
329
transform, root = self.get_transform()
328
new_trans_id = transform.new_directory('', ROOT_PARENT, b'new-root-id')
329
new_trans_id = transform.new_directory('', ROOT_PARENT, b'alt-root-id')
330
transform.new_directory('', ROOT_PARENT, b'new-root-id')
331
transform.new_directory('', ROOT_PARENT, b'alt-root-id')
330
332
self.assertRaises(ValueError, transform.fixup_new_roots)
332
334
def test_fixup_new_roots_permits_empty_tree(self):
374
376
transform, root = self.get_transform()
375
377
self.wt.lock_tree_write()
376
378
self.addCleanup(self.wt.unlock)
377
trans_id = transform.new_file('name', root, [b'contents'],
378
b'my_pretties', True)
379
transform.new_file('name', root, [b'contents'], b'my_pretties', True)
379
380
oz = transform.new_directory('oz', root, b'oz-id')
380
381
dorothy = transform.new_directory('dorothy', oz, b'dorothy-id')
381
toto = transform.new_file('toto', dorothy, [b'toto-contents'],
382
transform.new_file('toto', dorothy, [b'toto-contents'], b'toto-id',
384
385
self.assertEqual(len(transform.find_conflicts()), 0)
385
386
transform.apply()
404
405
transform.apply()
406
407
self.addCleanup(tree.unlock)
407
self.assertEqual(b'subtree-revision',
408
tree.root_inventory.get_entry(b'subtree-id').reference_revision)
410
tree.root_inventory.get_entry(b'subtree-id').reference_revision)
410
412
def test_conflicts(self):
411
413
transform, root = self.get_transform()
641
643
mangle_tree, root = self.get_transform()
642
644
root = mangle_tree.root
644
646
name1 = mangle_tree.trans_id_tree_path('name1')
645
647
name2 = mangle_tree.trans_id_tree_path('name2')
646
648
mangle_tree.adjust_path('name2', root, name1)
647
649
mangle_tree.adjust_path('name1', root, name2)
649
#tests for deleting parent directories
651
# tests for deleting parent directories
650
652
ddir = mangle_tree.trans_id_tree_path('dying_directory')
651
653
mangle_tree.delete_contents(ddir)
652
654
dfile = mangle_tree.trans_id_tree_path('dying_directory/dying_file')
655
657
mfile = mangle_tree.trans_id_tree_path('dying_directory/moving_file')
656
658
mangle_tree.adjust_path('mfile', root, mfile)
658
#tests for adding parent directories
660
# tests for adding parent directories
659
661
newdir = mangle_tree.new_directory('new_directory', root, b'newdir')
660
662
mfile2 = mangle_tree.trans_id_tree_path('moving_file2')
661
663
mangle_tree.adjust_path('mfile2', newdir, mfile2)
684
686
def test_both_rename(self):
685
687
create_tree, root = self.get_transform()
686
688
newdir = create_tree.new_directory('selftest', root, b'selftest-id')
687
create_tree.new_file('blackbox.py', newdir, [b'hello1'], b'blackbox-id')
689
create_tree.new_file('blackbox.py', newdir, [
690
b'hello1'], b'blackbox-id')
688
691
create_tree.apply()
689
692
mangle_tree, root = self.get_transform()
690
693
selftest = mangle_tree.trans_id_tree_path('selftest')
705
708
mangle_tree, root = self.get_transform()
706
709
breezy = mangle_tree.trans_id_tree_path('breezy')
707
710
tests = mangle_tree.trans_id_tree_path('breezy/tests')
708
test_too_much = mangle_tree.trans_id_tree_path('breezy/tests/blackbox/test_too_much.py')
711
test_too_much = mangle_tree.trans_id_tree_path(
712
'breezy/tests/blackbox/test_too_much.py')
709
713
mangle_tree.adjust_path('selftest', breezy, tests)
710
714
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
711
715
mangle_tree.set_executability(True, test_too_much)
719
723
create_tree.apply()
720
724
mangle_tree, root = self.get_transform()
721
725
tests = mangle_tree.trans_id_tree_path('tests')
722
test_too_much = mangle_tree.trans_id_tree_path('tests/test_too_much.py')
726
test_too_much = mangle_tree.trans_id_tree_path(
727
'tests/test_too_much.py')
723
728
mangle_tree.adjust_path('selftest', root, tests)
724
729
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
725
730
mangle_tree.set_executability(True, test_too_much)
765
770
def _test_symlinks(self, link_name1, link_target1,
766
771
link_name2, link_target2):
768
def ozpath(p): return 'oz/' + p
770
776
self.requireFeature(SymlinkFeature)
771
777
transform, root = self.get_transform()
772
778
oz_id = transform.new_directory('oz', root, b'oz-id')
773
wizard = transform.new_symlink(link_name1, oz_id, link_target1,
779
transform.new_symlink(link_name1, oz_id, link_target1, b'wizard-id')
775
780
wiz_id = transform.create_path(link_name2, oz_id)
776
781
transform.create_symlink(link_target2, wiz_id)
777
782
transform.version_file(b'wiz-id2', wiz_id)
873
878
b'munchkincity-id')
874
879
unversioned_parent2 = UnversionedParent('Versioned directory', 'oz',
876
881
self.assertEqual(cooked_conflicts[3], unversioned_parent)
877
parent_loop = ParentLoop('Cancelled move', 'oz/emeraldcity',
878
'oz/emeraldcity', b'emerald-id', b'emerald-id')
882
parent_loop = ParentLoop(
883
'Cancelled move', 'oz/emeraldcity',
884
'oz/emeraldcity', b'emerald-id', b'emerald-id')
879
885
self.assertEqual(cooked_conflicts[4], deleted_parent)
880
886
self.assertEqual(cooked_conflicts[5], unversioned_parent2)
881
887
self.assertEqual(cooked_conflicts[6], parent_loop)
900
906
self.assertEqual(conflicts_s[3], 'Conflict because munchkincity is not'
901
907
' versioned, but has versioned'
902
908
' children. Versioned directory.')
903
self.assertEqualDiff(conflicts_s[4], "Conflict: can't delete oz because it"
904
" is not empty. Not deleting.")
909
self.assertEqualDiff(
910
conflicts_s[4], "Conflict: can't delete oz because it"
911
" is not empty. Not deleting.")
905
912
self.assertEqual(conflicts_s[5], 'Conflict because oz is not'
906
913
' versioned, but has versioned'
907
914
' children. Versioned directory.')
925
932
tt = self.prepare_wrong_parent_kind()
926
933
raw_conflicts = resolve_conflicts(tt)
927
934
self.assertEqual({('non-directory parent', 'Created directory',
928
'new-3')}, raw_conflicts)
935
'new-3')}, raw_conflicts)
929
936
cooked_conflicts = cook_conflicts(raw_conflicts, tt)
930
937
self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
931
b'parent-id')], cooked_conflicts)
938
b'parent-id')], cooked_conflicts)
933
940
self.assertFalse(self.wt.is_versioned('parent'))
934
941
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
944
951
tt.create_file([b'contents'], parent_id)
945
952
raw_conflicts = resolve_conflicts(tt)
946
953
self.assertEqual({('non-directory parent', 'Created directory',
947
'new-3')}, raw_conflicts)
954
'new-3')}, raw_conflicts)
949
956
self.assertFalse(self.wt.is_versioned('parent'))
950
957
self.assertEqual(b'parent-id', self.wt.path2id('parent.new'))
1020
1027
self.requireFeature(features.not_running_as_root)
1021
1028
# see https://bugs.launchpad.net/bzr/+bug/491763
1022
1029
create, root_id = self.get_transform()
1023
first_dir = create.new_directory('first-dir', root_id, b'first-id')
1024
myfile = create.new_file('myfile', root_id, [b'myfile-text'],
1030
create.new_directory('first-dir', root_id, b'first-id')
1031
create.new_file('myfile', root_id, [b'myfile-text'], b'myfile-id')
1027
1033
if os.name == "posix" and sys.platform != "cygwin":
1028
1034
# posix filesystems fail on renaming if the readonly bit is set
1038
1044
dir_id = rename_transform.trans_id_file_id(b'first-id')
1039
1045
rename_transform.adjust_path('newname', dir_id, file_trans_id)
1040
1046
e = self.assertRaises(errors.TransformRenameFailed,
1041
rename_transform.apply)
1042
# On nix looks like:
1047
rename_transform.apply)
1048
# On nix looks like:
1043
1049
# "Failed to rename .../work/.bzr/checkout/limbo/new-1
1044
1050
# to .../first-dir/newname: [Errno 13] Permission denied"
1045
1051
# On windows looks like:
1046
# "Failed to rename .../work/myfile to
1052
# "Failed to rename .../work/myfile to
1047
1053
# .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
1048
1054
# This test isn't concerned with exactly what the error looks like,
1049
1055
# and the strerror will vary across OS and locales, but the assert
1067
1074
wt = transform._tree
1069
1076
self.addCleanup(wt.unlock)
1070
transform.new_file('set_on_creation', root, [b'Set on creation'], b'soc',
1077
transform.new_file('set_on_creation', root, [b'Set on creation'],
1072
1079
sac = transform.new_file('set_after_creation', root,
1073
1080
[b'Set after creation'], b'sac')
1074
1081
transform.set_executability(True, sac)
1137
1146
old = transform.trans_id_tree_path('old')
1138
1147
transform.unversion_file(old)
1139
1148
self.assertEqual([(b'id-1', ('old', None), False, (True, False),
1140
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1141
(True, True))], list(transform.iter_changes()))
1149
(b'eert_toor', b'eert_toor'),
1150
('old', 'old'), ('file', 'file'),
1151
(True, True))], list(transform.iter_changes()))
1142
1152
transform.new_directory('new', root, b'id-1')
1143
1153
self.assertEqual([(b'id-1', ('old', 'new'), True, (True, True),
1144
(b'eert_toor', b'eert_toor'), ('old', 'new'),
1145
('file', 'directory'),
1146
(True, False))], list(transform.iter_changes()))
1154
(b'eert_toor', b'eert_toor'), ('old', 'new'),
1155
('file', 'directory'),
1156
(True, False))], list(transform.iter_changes()))
1148
1158
transform.finalize()
1157
1167
old = transform.trans_id_tree_path('old')
1158
1168
transform.version_file(b'id-1', old)
1159
1169
self.assertEqual([(b'id-1', (None, 'old'), False, (False, True),
1160
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1161
(False, False))], list(transform.iter_changes()))
1170
(b'eert_toor', b'eert_toor'),
1171
('old', 'old'), ('file', 'file'),
1173
list(transform.iter_changes()))
1163
1175
transform.finalize()
1176
1188
new = transform.trans_id_tree_path('new')
1177
1189
self.assertEqual([], list(transform.iter_changes()))
1180
1192
transform.delete_contents(old)
1181
1193
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1182
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', None),
1183
(False, False))], list(transform.iter_changes()))
1194
(b'eert_toor', b'eert_toor'),
1195
('old', 'old'), ('file', None),
1197
list(transform.iter_changes()))
1186
1200
transform.create_file([b'blah'], old)
1187
1201
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1188
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1189
(False, False))], list(transform.iter_changes()))
1202
(b'eert_toor', b'eert_toor'),
1203
('old', 'old'), ('file', 'file'),
1205
list(transform.iter_changes()))
1190
1206
transform.cancel_deletion(old)
1191
1207
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1192
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1193
(False, False))], list(transform.iter_changes()))
1208
(b'eert_toor', b'eert_toor'),
1209
('old', 'old'), ('file', 'file'),
1211
list(transform.iter_changes()))
1194
1212
transform.cancel_creation(old)
1196
1214
# move file_id to a different file
1199
1217
transform.version_file(b'id-1', new)
1200
1218
transform.adjust_path('old', root, new)
1201
1219
self.assertEqual([(b'id-1', ('old', 'old'), True, (True, True),
1202
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1203
(False, False))], list(transform.iter_changes()))
1220
(b'eert_toor', b'eert_toor'),
1221
('old', 'old'), ('file', 'file'),
1223
list(transform.iter_changes()))
1204
1224
transform.cancel_versioning(new)
1205
1225
transform._removed_id = set()
1208
1228
self.assertEqual([], list(transform.iter_changes()))
1209
1229
transform.set_executability(True, old)
1210
1230
self.assertEqual([(b'id-1', ('old', 'old'), False, (True, True),
1211
(b'eert_toor', b'eert_toor'), ('old', 'old'), ('file', 'file'),
1212
(False, True))], list(transform.iter_changes()))
1231
(b'eert_toor', b'eert_toor'),
1232
('old', 'old'), ('file', 'file'),
1234
list(transform.iter_changes()))
1213
1235
transform.set_executability(None, old)
1217
1239
transform.adjust_path('new', root, old)
1218
1240
transform._new_parent = {}
1219
1241
self.assertEqual([(b'id-1', ('old', 'new'), False, (True, True),
1220
(b'eert_toor', b'eert_toor'), ('old', 'new'), ('file', 'file'),
1221
(False, False))], list(transform.iter_changes()))
1242
(b'eert_toor', b'eert_toor'),
1243
('old', 'new'), ('file', 'file'),
1245
list(transform.iter_changes()))
1222
1246
transform._new_name = {}
1224
1248
# parent directory
1226
1250
transform.adjust_path('new', subdir, old)
1227
1251
transform._new_name = {}
1228
1252
self.assertEqual([(b'id-1', ('old', 'subdir/old'), False,
1229
(True, True), (b'eert_toor', b'subdir-id'), ('old', 'old'),
1230
('file', 'file'), (False, False))],
1231
list(transform.iter_changes()))
1253
(True, True), (b'eert_toor',
1254
b'subdir-id'), ('old', 'old'),
1255
('file', 'file'), (False, False))],
1256
list(transform.iter_changes()))
1232
1257
transform._new_path = {}
1250
1275
transform.delete_contents(transform.trans_id_file_id(b'id-1'))
1251
1276
transform.set_executability(True,
1252
transform.trans_id_file_id(b'id-2'))
1253
self.assertEqual([(b'id-1', (u'file1', u'file1'), True, (True, True),
1254
(b'eert_toor', b'eert_toor'), ('file1', u'file1'),
1255
('file', None), (False, False)),
1256
(b'id-2', (u'file2', u'file2'), False, (True, True),
1257
(b'eert_toor', b'eert_toor'), ('file2', u'file2'),
1258
('file', 'file'), (False, True))],
1277
transform.trans_id_file_id(b'id-2'))
1279
[(b'id-1', (u'file1', u'file1'), True, (True, True),
1280
(b'eert_toor', b'eert_toor'), ('file1', u'file1'),
1281
('file', None), (False, False)),
1282
(b'id-2', (u'file2', u'file2'), False, (True, True),
1283
(b'eert_toor', b'eert_toor'), ('file2', u'file2'),
1284
('file', 'file'), (False, True))],
1259
1285
list(transform.iter_changes()))
1261
1287
transform.finalize()
1276
1302
transform.adjust_path('flitter', root, floater)
1277
1303
self.assertEqual([(b'floater-id', ('floater', 'flitter'), False,
1278
(True, True), (b'toor_eert', b'toor_eert'), ('floater', 'flitter'),
1279
(None, None), (False, False))], list(transform.iter_changes()))
1305
(b'toor_eert', b'toor_eert'),
1306
('floater', 'flitter'),
1307
(None, None), (False, False))],
1308
list(transform.iter_changes()))
1281
1310
transform.finalize()
1403
1432
transform.create_directory(parent)
1404
1433
except KeyError:
1405
1434
self.fail("Can't handle contents with no name")
1406
child = transform.new_directory('child', parent)
1435
transform.new_directory('child', parent)
1407
1436
transform.adjust_path('parent', root, parent)
1408
1437
transform.apply()
1409
1438
self.assertPathExists(self.wt.abspath('parent/child'))
1413
1442
"""Avoid reusing the same limbo name for different files"""
1414
1443
transform, root = self.get_transform()
1415
1444
parent = transform.new_directory('parent', root)
1416
child1 = transform.new_directory('child', parent)
1445
transform.new_directory('child', parent)
1418
1447
child2 = transform.new_directory('child', parent)
1419
1448
except OSError:
1433
1462
parent = transform.new_directory('parent', root)
1434
1463
child1 = transform.new_directory('child', parent)
1435
1464
transform.adjust_path('child1', parent, child1)
1436
child2 = transform.new_directory('child', parent)
1465
transform.new_directory('child', parent)
1437
1466
transform.apply()
1438
1467
# limbo/new-1 => parent
1439
1468
self.assertEqual(1, transform.rename_count)
1445
1474
child1 = transform.new_directory('child1', parent2)
1446
1475
transform.cancel_creation(parent2)
1447
1476
transform.create_directory(parent2)
1448
child2 = transform.new_directory('child1', parent2)
1477
transform.new_directory('child1', parent2)
1449
1478
transform.adjust_path('child2', parent2, child1)
1450
1479
transform.apply()
1451
1480
# limbo/new-1 => parent2, limbo/new-2 => parent2/child1
1630
1659
def test_create_from_tree_bytes(self):
1631
1660
"""Provided lines are used instead of tree content."""
1632
1661
tree1 = self.make_branch_and_tree('tree1')
1633
self.build_tree_contents([('tree1/foo', b'bar'),])
1662
self.build_tree_contents([('tree1/foo', b'bar'), ])
1634
1663
tree1.add('foo', b'foo-id')
1635
1664
tree2 = self.make_branch_and_tree('tree2')
1636
1665
tt = TreeTransform(tree2)
1774
1803
merge_modified = this.wt.merge_modified()
1775
1804
self.assertSubset(merge_modified, modified)
1776
1805
self.assertEqual(len(merge_modified), len(modified))
1777
with open(this.wt.abspath(this.wt.id2path(b'a')), 'wb') as f: f.write(b'booga')
1806
with open(this.wt.abspath(this.wt.id2path(b'a')), 'wb') as f:
1778
1808
modified.pop(0)
1779
1809
merge_modified = this.wt.merge_modified()
1780
1810
self.assertSubset(merge_modified, modified)
1800
1830
for link, target in (('e', e_target), ('f', f_target),
1801
1831
('g', g_target), ('h', h_target)):
1802
1832
if target is not None:
1803
tg.tt.new_symlink(link, tg.root, target, link.encode('ascii'))
1833
tg.tt.new_symlink(link, tg.root, target,
1834
link.encode('ascii'))
1805
1836
for tg in this, base, other:
1809
1840
self.assertIs(os.path.islink(this.wt.abspath('b')), True)
1810
1841
self.assertIs(os.path.isfile(this.wt.abspath('c')), True)
1811
1842
for suffix in ('THIS', 'BASE', 'OTHER'):
1812
self.assertEqual(os.readlink(this.wt.abspath('d.'+suffix)), suffix)
1843
self.assertEqual(os.readlink(
1844
this.wt.abspath('d.' + suffix)), suffix)
1813
1845
self.assertIs(os.path.lexists(this.wt.abspath('d')), False)
1814
1846
self.assertEqual(this.wt.id2path(b'd'), 'd.OTHER')
1815
1847
self.assertEqual(this.wt.id2path(b'f'), 'f.THIS')
1897
1929
a = ControlDir.create_standalone_workingtree('a')
1898
1930
os.mkdir('a/foo')
1899
with open('a/foo/bar', 'wb') as f: f.write(b'contents')
1931
with open('a/foo/bar', 'wb') as f:
1932
f.write(b'contents')
1900
1933
os.symlink('a/foo/bar', 'a/foo/baz')
1901
1934
a.add(['foo', 'foo/bar', 'foo/baz'])
1902
1935
a.commit('initial commit')
1913
1946
def test_build_with_references(self):
1914
1947
tree = self.make_branch_and_tree('source',
1915
format='development-subtree')
1948
format='development-subtree')
1916
1949
subtree = self.make_branch_and_tree('source/subtree',
1917
format='development-subtree')
1950
format='development-subtree')
1918
1951
tree.add_reference(subtree)
1919
1952
tree.commit('a revision')
1920
1953
tree.branch.create_checkout('target')
1929
1962
source.add('file', b'new-file')
1930
1963
source.commit('added file')
1931
1964
build_tree(source.basis_tree(), target)
1932
self.assertEqual([DuplicateEntry('Moved existing file to',
1933
'file.moved', 'file', None, 'new-file')],
1966
[DuplicateEntry('Moved existing file to', 'file.moved',
1967
'file', None, 'new-file')],
1935
1969
target2 = self.make_branch_and_tree('target2')
1936
1970
with open('target2/file', 'wb') as target_file, \
1937
1971
open('source/file', 'rb') as source_file:
1949
1983
target = self.make_branch_and_tree('target')
1950
1984
os.symlink('bar', 'target/symlink')
1951
1985
build_tree(source.basis_tree(), target)
1952
self.assertEqual([DuplicateEntry('Moved existing file to',
1953
'symlink.moved', 'symlink', None, 'new-symlink')],
1987
[DuplicateEntry('Moved existing file to', 'symlink.moved',
1988
'symlink', None, 'new-symlink')],
1954
1989
target.conflicts())
1955
1990
target = self.make_branch_and_tree('target2')
1956
1991
os.symlink('foo', 'target2/symlink')
1984
2019
self.assertPathDoesNotExist('target3/dir1/file')
1985
2020
self.assertPathExists('target3/dir1/file2')
1986
2021
self.assertPathExists('target3/dir1.diverted/file')
1987
self.assertEqual([DuplicateEntry('Diverted to',
1988
'dir1.diverted', 'dir1', 'new-dir1', None)],
2023
[DuplicateEntry('Diverted to', 'dir1.diverted',
2024
'dir1', 'new-dir1', None)],
1989
2025
target.conflicts())
1991
2027
target = self.make_branch_and_tree('target4')
1995
2031
self.assertPathExists('target4/dir1/file')
1996
2032
self.assertEqual('directory', file_kind('target4/dir1/file'))
1997
2033
self.assertPathExists('target4/dir1/file.diverted')
1998
self.assertEqual([DuplicateEntry('Diverted to',
1999
'dir1/file.diverted', 'dir1/file', 'new-file', None)],
2035
[DuplicateEntry('Diverted to', 'dir1/file.diverted',
2036
'dir1/file', 'new-file', None)],
2000
2037
target.conflicts())
2002
2039
def test_mixed_conflict_handling(self):
2007
2044
source.add('name', b'new-name')
2008
2045
source.commit('added file')
2009
2046
build_tree(source.basis_tree(), target)
2010
self.assertEqual([DuplicateEntry('Moved existing file to',
2011
'name.moved', 'name', None, 'new-name')], target.conflicts())
2048
[DuplicateEntry('Moved existing file to',
2049
'name.moved', 'name', None, 'new-name')],
2013
2052
def test_raises_in_populated(self):
2014
2053
source = self.make_branch_and_tree('source')
2019
2058
self.build_tree(['target/name'])
2020
2059
target.add('name')
2021
2060
self.assertRaises(errors.WorkingTreeAlreadyPopulated,
2022
build_tree, source.basis_tree(), target)
2061
build_tree, source.basis_tree(), target)
2024
2063
def test_build_tree_rename_count(self):
2025
2064
source = self.make_branch_and_tree('source')
2186
2227
# below, but that looks a bit... hard to read even if it's exactly
2187
2228
# the same thing.
2188
2229
original_registry = filters._reset_registry()
2189
2231
def restore_registry():
2190
2232
filters._reset_registry(original_registry)
2191
2233
self.addCleanup(restore_registry)
2192
2235
def rot13(chunks, context=None):
2193
return [codecs.encode(chunk.decode('ascii'), 'rot13').encode('ascii')
2194
for chunk in chunks]
2237
codecs.encode(chunk.decode('ascii'), 'rot13').encode('ascii')
2238
for chunk in chunks]
2195
2239
rot13filter = filters.ContentFilter(rot13, rot13)
2196
2240
filters.filter_stacks_registry.register(
2197
2241
'rot13', {'yes': [rot13filter]}.get)
2231
2276
def test_case_insensitive_build_tree_inventory(self):
2232
2277
if (features.CaseInsensitiveFilesystemFeature.available()
2233
or features.CaseInsCasePresFilenameFeature.available()):
2278
or features.CaseInsCasePresFilenameFeature.available()):
2234
2279
raise tests.UnavailableFeature('Fully case sensitive filesystem')
2235
2280
source = self.make_branch_and_tree('source')
2236
2281
self.build_tree(['source/file', 'source/FILE'])
2315
2360
def test_merge_parents(self):
2316
2361
branch, tt = self.get_branch_and_transform()
2317
rev = tt.commit(branch, 'my message', [b'rev1b', b'rev1c'])
2362
tt.commit(branch, 'my message', [b'rev1b', b'rev1c'])
2318
2363
self.assertEqual([b'rev1b', b'rev1c'],
2319
2364
branch.basis_tree().get_parent_ids()[1:])
2325
2370
tt = TransformPreview(branch.basis_tree())
2326
2371
self.addCleanup(tt.finalize)
2327
2372
tt.new_directory('', ROOT_PARENT, b'TREE_ROOT')
2328
rev = tt.commit(branch, 'my message')
2373
tt.commit(branch, 'my message')
2329
2374
self.assertEqual([], branch.basis_tree().get_parent_ids())
2330
2375
self.assertNotEqual(_mod_revision.NULL_REVISION,
2331
2376
branch.last_revision())
2337
2382
tt = TransformPreview(branch.basis_tree())
2338
2383
self.addCleanup(tt.finalize)
2339
2384
e = self.assertRaises(ValueError, tt.commit, branch,
2340
'my message', [b'rev1b-id'])
2385
'my message', [b'rev1b-id'])
2341
2386
self.assertEqual('Cannot supply merge parents for first commit.',
2343
2388
self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
2348
2393
trans_id = tt.new_directory('dir', tt.root, b'dir-id')
2349
2394
if SymlinkFeature.available():
2350
2395
tt.new_symlink('symlink', trans_id, 'target', b'symlink-id')
2351
rev = tt.commit(branch, 'message')
2396
tt.commit(branch, 'message')
2352
2397
tree = branch.basis_tree()
2353
2398
self.assertEqual('file', tree.id2path(b'file-id'))
2354
2399
self.assertEqual(b'contents', tree.get_file_text('file'))
2391
2436
committer='me <me@example.com>',
2392
2437
revprops={u'foo': 'bar'}, revision_id=b'revid-1',
2393
2438
authors=['Author1 <author1@example.com>',
2394
'Author2 <author2@example.com>',
2439
'Author2 <author2@example.com>',
2396
2441
self.assertEqual(b'revid-1', rev_id)
2397
2442
revision = branch.repository.get_revision(rev_id)
2398
2443
self.assertEqual(1, revision.timestamp)
2484
2529
def rename(self, source, target):
2485
2530
if (self.bad_source is not None and
2486
source.endswith(self.bad_source)):
2531
source.endswith(self.bad_source)):
2488
2533
elif (self.bad_target is not None and
2489
target.endswith(self.bad_target)):
2534
target.endswith(self.bad_target)):
2492
2537
_FileMover.rename(self, source, target)
2547
2592
new_globals = dict(func.__globals__)
2548
2593
new_globals.update(globals)
2549
2594
new_func = types.FunctionType(func.__code__, new_globals,
2550
func.__name__, func.__defaults__)
2595
func.__name__, func.__defaults__)
2552
2597
setattr(instance, method_name,
2553
types.MethodType(new_func, instance))
2598
types.MethodType(new_func, instance))
2555
2600
setattr(instance, method_name,
2556
types.MethodType(new_func, instance, instance.__class__))
2601
types.MethodType(new_func, instance, instance.__class__))
2557
2602
self.addCleanup(delattr, instance, method_name)
2586
2631
def test_root_create_file_open_raises_before_creation(self):
2587
2632
tt, trans_id = self.create_transform_and_root_trans_id()
2588
self._override_globals_in_method(tt, "create_file",
2589
{"open": self._fake_open_raises_before})
2590
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2633
self._override_globals_in_method(
2634
tt, "create_file", {"open": self._fake_open_raises_before})
2635
self.assertRaises(RuntimeError, tt.create_file,
2636
[b"contents"], trans_id)
2591
2637
path = tt._limbo_name(trans_id)
2592
2638
self.assertPathDoesNotExist(path)
2596
2642
def test_root_create_file_open_raises_after_creation(self):
2597
2643
tt, trans_id = self.create_transform_and_root_trans_id()
2598
self._override_globals_in_method(tt, "create_file",
2599
{"open": self._fake_open_raises_after})
2600
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2644
self._override_globals_in_method(
2645
tt, "create_file", {"open": self._fake_open_raises_after})
2646
self.assertRaises(RuntimeError, tt.create_file,
2647
[b"contents"], trans_id)
2601
2648
path = tt._limbo_name(trans_id)
2602
2649
self.assertPathExists(path)
2607
2654
def test_subdir_create_file_open_raises_before_creation(self):
2608
2655
tt, trans_id = self.create_transform_and_subdir_trans_id()
2609
self._override_globals_in_method(tt, "create_file",
2610
{"open": self._fake_open_raises_before})
2611
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2656
self._override_globals_in_method(
2657
tt, "create_file", {"open": self._fake_open_raises_before})
2658
self.assertRaises(RuntimeError, tt.create_file,
2659
[b"contents"], trans_id)
2612
2660
path = tt._limbo_name(trans_id)
2613
2661
self.assertPathDoesNotExist(path)
2617
2665
def test_subdir_create_file_open_raises_after_creation(self):
2618
2666
tt, trans_id = self.create_transform_and_subdir_trans_id()
2619
self._override_globals_in_method(tt, "create_file",
2620
{"open": self._fake_open_raises_after})
2621
self.assertRaises(RuntimeError, tt.create_file, [b"contents"], trans_id)
2667
self._override_globals_in_method(
2668
tt, "create_file", {"open": self._fake_open_raises_after})
2669
self.assertRaises(RuntimeError, tt.create_file,
2670
[b"contents"], trans_id)
2622
2671
path = tt._limbo_name(trans_id)
2623
2672
self.assertPathExists(path)
2655
2704
def rename(self, old, new):
2656
2705
raise RuntimeError
2657
2706
self._override_globals_in_method(tt, "_rename_in_limbo",
2658
{"os": FakeOSModule()})
2707
{"os": FakeOSModule()})
2659
2708
self.assertRaises(
2660
2709
RuntimeError, tt.adjust_path, "child1", parent2, child1)
2661
2710
path = osutils.pathjoin(tt._limbo_name(parent1), "child1")
2679
2728
def test_resolve_create_parent_for_versioned_file(self):
2680
2729
wt, tt = self.make_tt_with_versioned_dir()
2681
2730
dir_tid = tt.trans_id_tree_path('dir')
2682
file_tid = tt.new_file('file', dir_tid, [b'Contents'], file_id=b'file-id')
2731
tt.new_file('file', dir_tid, [b'Contents'], file_id=b'file-id')
2683
2732
tt.delete_contents(dir_tid)
2684
2733
tt.unversion_file(dir_tid)
2685
2734
conflicts = resolve_conflicts(tt)
2703
2752
A_ENTRY = (b'a-id', ('a', 'a'), True, (True, True),
2704
(b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2753
(b'TREE_ROOT', b'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2706
2755
ROOT_ENTRY = (b'TREE_ROOT', ('', ''), False, (True, True), (None, None),
2707
2756
('', ''), ('directory', 'directory'), (False, False))
2781
2830
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2782
2831
root = revision_tree.get_root_id()
2783
2832
self.assertEqual([(b'a-id', ('a', 'a'), True, (True, True),
2784
(root, root), ('a', 'a'), ('file', 'file'),
2786
list(preview_tree.iter_changes(revision_tree)))
2833
(root, root), ('a', 'a'), ('file', 'file'),
2835
list(preview_tree.iter_changes(revision_tree)))
2788
2837
def test_include_unchanged_succeeds(self):
2789
2838
revision_tree, preview_tree = self.get_tree_and_preview_tree()
2790
2839
changes = preview_tree.iter_changes(revision_tree,
2791
2840
include_unchanged=True)
2792
root = revision_tree.get_root_id()
2794
2841
self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
2796
2843
def test_specific_files(self):
2858
2905
work_tree.add('old', b'old-id')
2859
2906
preview = TransformPreview(work_tree)
2860
2907
self.addCleanup(preview.finalize)
2861
new_id = preview.new_file('name', preview.root, [b'contents'], b'new-id',
2908
preview.new_file('name', preview.root, [b'contents'], b'new-id',
2863
2910
tree = preview.get_preview_tree()
2864
2911
self.assertEqual(len('old'), tree.get_file_size('old'))
2865
2912
self.assertEqual(len('contents'), tree.get_file_size('name'))
2911
2958
preview = TransformPreview(tree)
2912
2959
self.addCleanup(preview.finalize)
2913
2960
preview.new_file('new', preview.trans_id_file_id(b'unchanged-id'),
2914
[b'contents'], b'new-id')
2961
[b'contents'], b'new-id')
2915
2962
preview_tree = preview.get_preview_tree()
2916
2963
self.assertEqual(b'new-id', preview_tree.path2id('unchanged/new'))
3017
3064
def test_file_content_summary_executable(self):
3018
3065
preview = self.get_empty_preview()
3019
path_id = preview.new_file('path', preview.root, [b'contents'], b'path-id')
3066
path_id = preview.new_file('path', preview.root, [
3067
b'contents'], b'path-id')
3020
3068
preview.set_executability(True, path_id)
3021
3069
summary = preview.get_preview_tree().path_content_summary('path')
3022
3070
self.assertEqual(4, len(summary))
3125
3176
file_trans_id = preview.trans_id_file_id(b'file-id')
3126
3177
preview.delete_contents(file_trans_id)
3127
3178
preview_tree = preview.get_preview_tree()
3128
annotation = preview_tree.annotate_iter('file', default_revision=b'me:')
3179
annotation = preview_tree.annotate_iter(
3180
'file', default_revision=b'me:')
3129
3181
self.assertIs(None, annotation)
3131
3183
def test_stored_kind(self):
3196
3248
def test_walkdirs(self):
3197
3249
preview = self.get_empty_preview()
3198
root = preview.new_directory('', ROOT_PARENT, b'tree-root')
3250
preview.new_directory('', ROOT_PARENT, b'tree-root')
3199
3251
# FIXME: new_directory should mark root.
3200
3252
preview.fixup_new_roots()
3201
3253
preview_tree = preview.get_preview_tree()
3202
file_trans_id = preview.new_file('a', preview.root, [b'contents'],
3254
preview.new_file('a', preview.root, [b'contents'], b'a-id')
3204
3255
expected = [(('', b'tree-root'),
3205
[('a', 'a', 'file', None, b'a-id', 'file')])]
3256
[('a', 'a', 'file', None, b'a-id', 'file')])]
3206
3257
self.assertEqual(expected, list(preview_tree.walkdirs()))
3208
3259
def test_extras(self):
3483
3534
attribs = self.default_attribs()
3484
3535
attribs[b'_id_number'] = 2
3485
3536
attribs[b'_non_present_ids'] = {
3487
3538
return self.make_records(attribs, [])
3489
3540
def test_serialize_missing(self):
3490
3541
tt = self.get_preview()
3491
boo_trans_id = tt.trans_id_file_id(b'boo')
3542
tt.trans_id_file_id(b'boo')
3492
3543
self.assertSerializesTo(self.missing_records(), tt)
3494
3545
def test_deserialize_missing(self):
3589
3640
def test_get_parents_lines(self):
3590
3641
LINES_ONE = b'aa\nbb\ncc\ndd\n'
3591
LINES_TWO = b'z\nbb\nx\ndd\n'
3592
3642
tree = self.make_branch_and_tree('tree')
3593
3643
self.build_tree_contents([('tree/file', LINES_ONE)])
3594
3644
tree.add('file', b'file-id')
3595
3645
tt = self.get_preview(tree)
3596
3646
trans_id = tt.trans_id_tree_path('file')
3597
3647
self.assertEqual(([b'aa\n', b'bb\n', b'cc\n', b'dd\n'],),
3598
tt._get_parents_lines(trans_id))
3648
tt._get_parents_lines(trans_id))
3600
3650
def test_get_parents_texts(self):
3601
3651
LINES_ONE = b'aa\nbb\ncc\ndd\n'
3602
LINES_TWO = b'z\nbb\nx\ndd\n'
3603
3652
tree = self.make_branch_and_tree('tree')
3604
3653
self.build_tree_contents([('tree/file', LINES_ONE)])
3605
3654
tree.add('file', b'file-id')
3606
3655
tt = self.get_preview(tree)
3607
3656
trans_id = tt.trans_id_tree_path('file')
3608
3657
self.assertEqual((LINES_ONE,),
3609
tt._get_parents_texts(trans_id))
3658
tt._get_parents_texts(trans_id))
3612
3661
class TestOrphan(tests.TestCaseWithTransport):
3646
3695
self._set_orphan_policy(wt, 'move')
3647
3696
tt, orphan_tid = self._prepare_orphan(wt)
3649
3699
def warning(*args):
3650
3700
warnings.append(args[0] % args[1:])
3651
3701
self.overrideAttr(trace, 'warning', warning)
3652
3702
remaining_conflicts = resolve_conflicts(tt)
3653
3703
self.assertEqual(['dir/foo has been orphaned in brz-orphans'],
3655
3705
# Yeah for resolved conflicts !
3656
3706
self.assertLength(0, remaining_conflicts)
3657
3707
# We have a new orphan
3658
3708
self.assertEqual('foo.~1~', tt.final_name(orphan_tid))
3659
3709
self.assertEqual('brz-orphans',
3660
tt.final_name(tt.final_parent(orphan_tid)))
3710
tt.final_name(tt.final_parent(orphan_tid)))
3662
3712
def test_never_orphan(self):
3663
3713
wt = self.make_branch_and_tree('.')
3715
3766
def test_pre_commit_hooks(self):
3717
3769
def record_pre_transform(tree, tt):
3718
3770
calls.append((tree, tt))
3719
MutableTree.hooks.install_named_hook('pre_transform',
3720
record_pre_transform, "Pre transform")
3771
MutableTree.hooks.install_named_hook(
3772
'pre_transform', record_pre_transform, "Pre transform")
3721
3773
transform, root = self.get_transform()
3722
3774
old_root_id = transform.tree_file_id(root)
3723
3775
transform.apply()
3727
3779
def test_post_commit_hooks(self):
3729
3782
def record_post_transform(tree, tt):
3730
3783
calls.append((tree, tt))
3731
MutableTree.hooks.install_named_hook('post_transform',
3732
record_post_transform, "Post transform")
3784
MutableTree.hooks.install_named_hook(
3785
'post_transform', record_post_transform, "Post transform")
3733
3786
transform, root = self.get_transform()
3734
3787
old_root_id = transform.tree_file_id(root)
3735
3788
transform.apply()