48
44
# set_path_id setting id when state is in memory modified
51
class TestCaseWithDirState(TestCaseWithTransport):
47
def load_tests(basic_tests, module, loader):
48
suite = loader.suiteClass()
49
dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
50
basic_tests, tests.condition_isinstance(TestCaseWithDirState))
51
tests.multiply_tests(dir_reader_tests,
52
test_osutils.dir_reader_scenarios(), suite)
53
suite.addTest(remaining_tests)
57
class TestCaseWithDirState(tests.TestCaseWithTransport):
52
58
"""Helper functions for creating DirState objects with various content."""
61
_dir_reader_class = None
62
_native_to_unicode = None # Not used yet
65
tests.TestCaseWithTransport.setUp(self)
67
self.overrideAttr(osutils,
68
'_selected_dir_reader', self._dir_reader_class())
54
70
def create_empty_dirstate(self):
55
71
"""Return a locked but empty dirstate"""
56
72
state = dirstate.DirState.initialize('dirstate')
397
413
(('', '', tree.get_root_id()), # common details
398
414
[('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
399
415
('d', '', 0, False, rev_id), # first parent details
400
('d', '', 0, False, rev_id2), # second parent details
416
('d', '', 0, False, rev_id), # second parent details
402
418
state = dirstate.DirState.from_tree(tree, 'dirstate')
403
419
self.check_state_with_reopen(expected_result, state)
478
494
(('', '', tree.get_root_id()), # common details
479
495
[('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
480
496
('d', '', 0, False, rev_id), # first parent details
481
('d', '', 0, False, rev_id2), # second parent details
497
('d', '', 0, False, rev_id), # second parent details
483
499
(('', 'a file', 'a-file-id'), # common
484
500
[('f', '', 0, False, dirstate.DirState.NULLSTAT), # current
852
867
state = dirstate.DirState.initialize('dirstate')
854
869
# check precondition to be sure the state does change appropriately.
856
[(('', '', 'TREE_ROOT'), [('d', '', 0, False,
857
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')])],
858
list(state._iter_entries()))
859
state.set_path_id('', 'foobarbaz')
861
(('', '', 'foobarbaz'), [('d', '', 0, False,
862
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')])]
870
root_entry = (('', '', 'TREE_ROOT'), [('d', '', 0, False, 'x'*32)])
871
self.assertEqual([root_entry], list(state._iter_entries()))
872
self.assertEqual(root_entry, state._get_entry(0, path_utf8=''))
873
self.assertEqual(root_entry,
874
state._get_entry(0, fileid_utf8='TREE_ROOT'))
875
self.assertEqual((None, None),
876
state._get_entry(0, fileid_utf8='second-root-id'))
877
state.set_path_id('', 'second-root-id')
878
new_root_entry = (('', '', 'second-root-id'),
879
[('d', '', 0, False, 'x'*32)])
880
expected_rows = [new_root_entry]
863
881
self.assertEqual(expected_rows, list(state._iter_entries()))
882
self.assertEqual(new_root_entry, state._get_entry(0, path_utf8=''))
883
self.assertEqual(new_root_entry,
884
state._get_entry(0, fileid_utf8='second-root-id'))
885
self.assertEqual((None, None),
886
state._get_entry(0, fileid_utf8='TREE_ROOT'))
864
887
# should work across save too
884
907
state._validate()
886
909
state.set_parent_trees([('parent-revid', rt)], ghosts=[])
887
state.set_path_id('', 'foobarbaz')
910
root_entry = (('', '', 'TREE_ROOT'),
911
[('d', '', 0, False, 'x'*32),
912
('d', '', 0, False, 'parent-revid')])
913
self.assertEqual(root_entry, state._get_entry(0, path_utf8=''))
914
self.assertEqual(root_entry,
915
state._get_entry(0, fileid_utf8='TREE_ROOT'))
916
self.assertEqual((None, None),
917
state._get_entry(0, fileid_utf8='Asecond-root-id'))
918
state.set_path_id('', 'Asecond-root-id')
888
919
state._validate()
889
920
# now see that it is what we expected
891
(('', '', 'TREE_ROOT'),
892
[('a', '', 0, False, ''),
893
('d', '', 0, False, 'parent-revid'),
895
(('', '', 'foobarbaz'),
896
[('d', '', 0, False, ''),
897
('a', '', 0, False, ''),
921
old_root_entry = (('', '', 'TREE_ROOT'),
922
[('a', '', 0, False, ''),
923
('d', '', 0, False, 'parent-revid')])
924
new_root_entry = (('', '', 'Asecond-root-id'),
925
[('d', '', 0, False, ''),
926
('a', '', 0, False, '')])
927
expected_rows = [new_root_entry, old_root_entry]
900
928
state._validate()
901
929
self.assertEqual(expected_rows, list(state._iter_entries()))
930
self.assertEqual(new_root_entry, state._get_entry(0, path_utf8=''))
931
self.assertEqual(old_root_entry, state._get_entry(1, path_utf8=''))
932
self.assertEqual((None, None),
933
state._get_entry(0, fileid_utf8='TREE_ROOT'))
934
self.assertEqual(old_root_entry,
935
state._get_entry(1, fileid_utf8='TREE_ROOT'))
936
self.assertEqual(new_root_entry,
937
state._get_entry(0, fileid_utf8='Asecond-root-id'))
938
self.assertEqual((None, None),
939
state._get_entry(1, fileid_utf8='Asecond-root-id'))
902
940
# should work across save too
980
1017
[(('', '', root_id), [
981
1018
('d', '', 0, False, dirstate.DirState.NULLSTAT),
982
1019
('d', '', 0, False, revid1),
983
('d', '', 0, False, revid2)
1020
('d', '', 0, False, revid1)
985
1022
list(state._iter_entries()))
1014
1051
(('', '', root_id), [
1015
1052
('d', '', 0, False, dirstate.DirState.NULLSTAT),
1016
1053
('d', '', 0, False, revid1.encode('utf8')),
1017
('d', '', 0, False, revid2.encode('utf8'))
1054
('d', '', 0, False, revid1.encode('utf8'))
1019
1056
(('', 'a file', 'file-id'), [
1020
1057
('a', '', 0, False, ''),
1081
1116
self.build_tree(['unversioned/', 'unversioned/a file'])
1082
1117
state = dirstate.DirState.initialize('dirstate')
1084
self.assertRaises(errors.NotVersionedError, state.add,
1085
'unversioned/a file', 'a-file-id', 'file', None, None)
1118
self.addCleanup(state.unlock)
1119
self.assertRaises(errors.NotVersionedError, state.add,
1120
'unversioned/a file', 'a-file-id', 'file', None, None)
1089
1122
def test_add_directory_to_root_no_parents_all_data(self):
1090
1123
# The most trivial addition of a dir is when there are no parents and
1111
1144
state = dirstate.DirState.on_file('dirstate')
1112
1145
state.lock_read()
1146
self.addCleanup(state.unlock)
1113
1147
state._validate()
1115
self.assertEqual(expected_entries, list(state._iter_entries()))
1148
self.assertEqual(expected_entries, list(state._iter_entries()))
1119
def test_add_symlink_to_root_no_parents_all_data(self):
1150
def _test_add_symlink_to_root_no_parents_all_data(self, link_name, target):
1120
1151
# The most trivial addition of a symlink when there are no parents and
1121
1152
# its in the root and all data about the file is supplied
1122
1153
# bzr doesn't support fake symlinks on windows, yet.
1123
self.requireFeature(SymlinkFeature)
1124
os.symlink('target', 'a link')
1125
stat = os.lstat('a link')
1154
self.requireFeature(tests.SymlinkFeature)
1155
os.symlink(target, link_name)
1156
stat = os.lstat(link_name)
1126
1157
expected_entries = [
1127
1158
(('', '', 'TREE_ROOT'), [
1128
1159
('d', '', 0, False, dirstate.DirState.NULLSTAT), # current tree
1130
(('', 'a link', 'a link id'), [
1131
('l', 'target', 6, False, dirstate.pack_stat(stat)), # current tree
1161
(('', link_name.encode('UTF-8'), 'a link id'), [
1162
('l', target.encode('UTF-8'), stat[6],
1163
False, dirstate.pack_stat(stat)), # current tree
1134
1166
state = dirstate.DirState.initialize('dirstate')
1136
state.add('a link', 'a link id', 'symlink', stat, 'target')
1168
state.add(link_name, 'a link id', 'symlink', stat,
1169
target.encode('UTF-8'))
1137
1170
# having added it, it should be in the output of iter_entries.
1138
1171
self.assertEqual(expected_entries, list(state._iter_entries()))
1139
1172
# saving and reloading should not affect this.
1143
1176
state = dirstate.DirState.on_file('dirstate')
1144
1177
state.lock_read()
1146
self.assertEqual(expected_entries, list(state._iter_entries()))
1178
self.addCleanup(state.unlock)
1179
self.assertEqual(expected_entries, list(state._iter_entries()))
1181
def test_add_symlink_to_root_no_parents_all_data(self):
1182
self._test_add_symlink_to_root_no_parents_all_data('a link', 'target')
1184
def test_add_symlink_unicode_to_root_no_parents_all_data(self):
1185
self.requireFeature(tests.UnicodeFilenameFeature)
1186
self._test_add_symlink_to_root_no_parents_all_data(
1187
u'\N{Euro Sign}link', u'targ\N{Euro Sign}et')
1150
1189
def test_add_directory_and_child_no_parents_all_data(self):
1151
1190
# after adding a directory, we should be able to add children to it.
1200
1237
# now check we can read it back
1201
1238
state.lock_read()
1239
self.addCleanup(state.unlock)
1202
1240
state._validate()
1204
entry2 = state._get_entry(0, 'subdir-id', 'subdir')
1205
self.assertEqual(entry, entry2)
1206
self.assertEqual(entry, expected_entry)
1207
# and lookup by id should work too
1208
entry2 = state._get_entry(0, fileid_utf8='subdir-id')
1209
self.assertEqual(entry, expected_entry)
1241
entry2 = state._get_entry(0, 'subdir-id', 'subdir')
1242
self.assertEqual(entry, entry2)
1243
self.assertEqual(entry, expected_entry)
1244
# and lookup by id should work too
1245
entry2 = state._get_entry(0, fileid_utf8='subdir-id')
1246
self.assertEqual(entry, expected_entry)
1213
1248
def test_add_forbidden_names(self):
1214
1249
state = dirstate.DirState.initialize('dirstate')
1218
1253
self.assertRaises(errors.BzrError,
1219
1254
state.add, '..', 'ass-id', 'directory', None, None)
1256
def test_set_state_with_rename_b_a_bug_395556(self):
1257
# bug 395556 uncovered a bug where the dirstate ends up with a false
1258
# relocation record - in a tree with no parents there should be no
1259
# absent or relocated records. This then leads to further corruption
1260
# when a commit occurs, as the incorrect relocation gathers an
1261
# incorrect absent in tree 1, and future changes go to pot.
1262
tree1 = self.make_branch_and_tree('tree1')
1263
self.build_tree(['tree1/b'])
1266
tree1.add(['b'], ['b-id'])
1267
root_id = tree1.get_root_id()
1268
inv = tree1.inventory
1269
state = dirstate.DirState.initialize('dirstate')
1271
# Set the initial state with 'b'
1272
state.set_state_from_inventory(inv)
1273
inv.rename('b-id', root_id, 'a')
1274
# Set the new state with 'a', which currently corrupts.
1275
state.set_state_from_inventory(inv)
1276
expected_result1 = [('', '', root_id, 'd'),
1277
('', 'a', 'b-id', 'f'),
1280
for entry in state._iter_entries():
1281
values.append(entry[0] + entry[1][0][:1])
1282
self.assertEqual(expected_result1, values)
1222
1289
class TestGetLines(TestCaseWithDirState):
2220
2287
self.assertIsInstance(tree_data, str)
2222
2289
def test_unicode_symlink(self):
2223
# In general, the code base doesn't support a target that contains
2224
# non-ascii characters. So we just assert tha
2225
inv_entry = inventory.InventoryLink('link-file-id', 'name',
2290
inv_entry = inventory.InventoryLink('link-file-id',
2291
u'nam\N{Euro Sign}e',
2226
2292
'link-parent-id')
2227
2293
inv_entry.revision = 'link-revision-id'
2228
inv_entry.symlink_target = u'link-target'
2229
details = self.assertDetails(('l', 'link-target', 0, False,
2230
'link-revision-id'), inv_entry)
2233
class TestSHA1Provider(TestCaseInTempDir):
2294
target = u'link-targ\N{Euro Sign}t'
2295
inv_entry.symlink_target = target
2296
self.assertDetails(('l', target.encode('UTF-8'), 0, False,
2297
'link-revision-id'), inv_entry)
2300
class TestSHA1Provider(tests.TestCaseInTempDir):
2235
2302
def test_sha1provider_is_an_interface(self):
2236
2303
p = dirstate.SHA1Provider()