124
138
:return: The dirstate, still write-locked.
126
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
127
null_sha = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
128
root_entry = ('', '', 'a-root-value'), [
129
('d', '', 0, False, packed_stat),
131
a_entry = ('', 'a', 'a-dir'), [
132
('d', '', 0, False, packed_stat),
134
b_entry = ('', 'b', 'b-dir'), [
135
('d', '', 0, False, packed_stat),
137
c_entry = ('', 'c', 'c-file'), [
138
('f', null_sha, 10, False, packed_stat),
140
d_entry = ('', 'd', 'd-file'), [
141
('f', null_sha, 20, False, packed_stat),
143
e_entry = ('a', 'e', 'e-dir'), [
144
('d', '', 0, False, packed_stat),
146
f_entry = ('a', 'f', 'f-file'), [
147
('f', null_sha, 30, False, packed_stat),
149
g_entry = ('b', 'g', 'g-file'), [
150
('f', null_sha, 30, False, packed_stat),
152
h_entry = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file'), [
153
('f', null_sha, 40, False, packed_stat),
140
packed_stat = b'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
141
null_sha = b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
142
root_entry = (b'', b'', b'a-root-value'), [
143
(b'd', b'', 0, False, packed_stat),
145
a_entry = (b'', b'a', b'a-dir'), [
146
(b'd', b'', 0, False, packed_stat),
148
b_entry = (b'', b'b', b'b-dir'), [
149
(b'd', b'', 0, False, packed_stat),
151
c_entry = (b'', b'c', b'c-file'), [
152
(b'f', null_sha, 10, False, packed_stat),
154
d_entry = (b'', b'd', b'd-file'), [
155
(b'f', null_sha, 20, False, packed_stat),
157
e_entry = (b'a', b'e', b'e-dir'), [
158
(b'd', b'', 0, False, packed_stat),
160
f_entry = (b'a', b'f', b'f-file'), [
161
(b'f', null_sha, 30, False, packed_stat),
163
g_entry = (b'b', b'g', b'g-file'), [
164
(b'f', null_sha, 30, False, packed_stat),
166
h_entry = (b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file'), [
167
(b'f', null_sha, 40, False, packed_stat),
156
dirblocks.append(('', [root_entry]))
157
dirblocks.append(('', [a_entry, b_entry, c_entry, d_entry]))
158
dirblocks.append(('a', [e_entry, f_entry]))
159
dirblocks.append(('b', [g_entry, h_entry]))
170
dirblocks.append((b'', [root_entry]))
171
dirblocks.append((b'', [a_entry, b_entry, c_entry, d_entry]))
172
dirblocks.append((b'a', [e_entry, f_entry]))
173
dirblocks.append((b'b', [g_entry, h_entry]))
160
174
state = dirstate.DirState.initialize('dirstate')
161
175
state._validate()
241
255
f_len = len(f_text)
242
256
null_stat = dirstate.DirState.NULLSTAT
244
'':(('', '', 'TREE_ROOT'), [
245
('d', '', 0, False, null_stat),
246
('d', '', 0, False, revision_id),
258
b'': ((b'', b'', b'TREE_ROOT'), [
259
(b'd', b'', 0, False, null_stat),
260
(b'd', b'', 0, False, revision_id),
248
'a':(('', 'a', 'a-id'), [
249
('f', '', 0, False, null_stat),
250
('f', a_sha, a_len, False, revision_id),
252
'b':(('', 'b', 'b-id'), [
253
('d', '', 0, False, null_stat),
254
('d', '', 0, False, revision_id),
256
'b/c':(('b', 'c', 'c-id'), [
257
('f', '', 0, False, null_stat),
258
('f', c_sha, c_len, False, revision_id),
260
'b/d':(('b', 'd', 'd-id'), [
261
('d', '', 0, False, null_stat),
262
('d', '', 0, False, revision_id),
264
'b/d/e':(('b/d', 'e', 'e-id'), [
265
('f', '', 0, False, null_stat),
266
('f', e_sha, e_len, False, revision_id),
268
'b-c':(('', 'b-c', 'b-c-id'), [
269
('f', '', 0, False, null_stat),
270
('f', b_c_sha, b_c_len, False, revision_id),
272
'f':(('', 'f', 'f-id'), [
273
('f', '', 0, False, null_stat),
274
('f', f_sha, f_len, False, revision_id),
262
b'a': ((b'', b'a', b'a-id'), [
263
(b'f', b'', 0, False, null_stat),
264
(b'f', a_sha, a_len, False, revision_id),
266
b'b': ((b'', b'b', b'b-id'), [
267
(b'd', b'', 0, False, null_stat),
268
(b'd', b'', 0, False, revision_id),
270
b'b/c': ((b'b', b'c', b'c-id'), [
271
(b'f', b'', 0, False, null_stat),
272
(b'f', c_sha, c_len, False, revision_id),
274
b'b/d': ((b'b', b'd', b'd-id'), [
275
(b'd', b'', 0, False, null_stat),
276
(b'd', b'', 0, False, revision_id),
278
b'b/d/e': ((b'b/d', b'e', b'e-id'), [
279
(b'f', b'', 0, False, null_stat),
280
(b'f', e_sha, e_len, False, revision_id),
282
b'b-c': ((b'', b'b-c', b'b-c-id'), [
283
(b'f', b'', 0, False, null_stat),
284
(b'f', b_c_sha, b_c_len, False, revision_id),
286
b'f': ((b'', b'f', b'f-id'), [
287
(b'f', b'', 0, False, null_stat),
288
(b'f', f_sha, f_len, False, revision_id),
277
291
state = dirstate.DirState.from_tree(tree, 'dirstate')
900
966
"""Set the root file id in a dirstate with parents"""
901
967
mt = self.make_branch_and_tree('mt')
902
968
# in case the default tree format uses a different root id
903
mt.set_root_id('TREE_ROOT')
904
mt.commit('foo', rev_id='parent-revid')
905
rt = mt.branch.repository.revision_tree('parent-revid')
969
mt.set_root_id(b'TREE_ROOT')
970
mt.commit('foo', rev_id=b'parent-revid')
971
rt = mt.branch.repository.revision_tree(b'parent-revid')
906
972
state = dirstate.DirState.initialize('dirstate')
907
973
state._validate()
909
state.set_parent_trees([('parent-revid', rt)], ghosts=[])
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=''))
975
state.set_parent_trees([(b'parent-revid', rt)], ghosts=[])
976
root_entry = ((b'', b'', b'TREE_ROOT'),
977
[(b'd', b'', 0, False, b'x'*32),
978
(b'd', b'', 0, False, b'parent-revid')])
979
self.assertEqual(root_entry, state._get_entry(0, path_utf8=b''))
914
980
self.assertEqual(root_entry,
915
state._get_entry(0, fileid_utf8='TREE_ROOT'))
981
state._get_entry(0, fileid_utf8=b'TREE_ROOT'))
916
982
self.assertEqual((None, None),
917
state._get_entry(0, fileid_utf8='Asecond-root-id'))
918
state.set_path_id('', 'Asecond-root-id')
983
state._get_entry(0, fileid_utf8=b'Asecond-root-id'))
984
state.set_path_id(b'', b'Asecond-root-id')
919
985
state._validate()
920
986
# now see that it is what we expected
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, '')])
987
old_root_entry = ((b'', b'', b'TREE_ROOT'),
988
[(b'a', b'', 0, False, b''),
989
(b'd', b'', 0, False, b'parent-revid')])
990
new_root_entry = ((b'', b'', b'Asecond-root-id'),
991
[(b'd', b'', 0, False, b''),
992
(b'a', b'', 0, False, b'')])
927
993
expected_rows = [new_root_entry, old_root_entry]
928
994
state._validate()
929
995
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=''))
996
self.assertEqual(new_root_entry, state._get_entry(0, path_utf8=b''))
997
self.assertEqual(old_root_entry, state._get_entry(1, path_utf8=b''))
932
998
self.assertEqual((None, None),
933
state._get_entry(0, fileid_utf8='TREE_ROOT'))
999
state._get_entry(0, fileid_utf8=b'TREE_ROOT'))
934
1000
self.assertEqual(old_root_entry,
935
state._get_entry(1, fileid_utf8='TREE_ROOT'))
1001
state._get_entry(1, fileid_utf8=b'TREE_ROOT'))
936
1002
self.assertEqual(new_root_entry,
937
state._get_entry(0, fileid_utf8='Asecond-root-id'))
1003
state._get_entry(0, fileid_utf8=b'Asecond-root-id'))
938
1004
self.assertEqual((None, None),
939
state._get_entry(1, fileid_utf8='Asecond-root-id'))
1005
state._get_entry(1, fileid_utf8=b'Asecond-root-id'))
940
1006
# should work across save too
1400
1522
def test_simple_structure(self):
1401
1523
state = self.create_dirstate_with_root_and_subdir()
1402
1524
self.addCleanup(state.unlock)
1403
self.assertBlockRowIndexEqual(1, 0, True, True, state, '', 'subdir', 0)
1404
self.assertBlockRowIndexEqual(1, 0, True, False, state, '', 'bdir', 0)
1405
self.assertBlockRowIndexEqual(1, 1, True, False, state, '', 'zdir', 0)
1406
self.assertBlockRowIndexEqual(2, 0, False, False, state, 'a', 'foo', 0)
1525
self.assertBlockRowIndexEqual(1, 0, True, True, state, b'', b'subdir', 0)
1526
self.assertBlockRowIndexEqual(1, 0, True, False, state, b'', b'bdir', 0)
1527
self.assertBlockRowIndexEqual(1, 1, True, False, state, b'', b'zdir', 0)
1528
self.assertBlockRowIndexEqual(2, 0, False, False, state, b'a', b'foo', 0)
1407
1529
self.assertBlockRowIndexEqual(2, 0, False, False, state,
1530
b'subdir', b'foo', 0)
1410
1532
def test_complex_structure_exists(self):
1411
1533
state = self.create_complex_dirstate()
1412
1534
self.addCleanup(state.unlock)
1413
1535
# Make sure we can find everything that exists
1414
self.assertBlockRowIndexEqual(0, 0, True, True, state, '', '', 0)
1415
self.assertBlockRowIndexEqual(1, 0, True, True, state, '', 'a', 0)
1416
self.assertBlockRowIndexEqual(1, 1, True, True, state, '', 'b', 0)
1417
self.assertBlockRowIndexEqual(1, 2, True, True, state, '', 'c', 0)
1418
self.assertBlockRowIndexEqual(1, 3, True, True, state, '', 'd', 0)
1419
self.assertBlockRowIndexEqual(2, 0, True, True, state, 'a', 'e', 0)
1420
self.assertBlockRowIndexEqual(2, 1, True, True, state, 'a', 'f', 0)
1421
self.assertBlockRowIndexEqual(3, 0, True, True, state, 'b', 'g', 0)
1536
self.assertBlockRowIndexEqual(0, 0, True, True, state, b'', b'', 0)
1537
self.assertBlockRowIndexEqual(1, 0, True, True, state, b'', b'a', 0)
1538
self.assertBlockRowIndexEqual(1, 1, True, True, state, b'', b'b', 0)
1539
self.assertBlockRowIndexEqual(1, 2, True, True, state, b'', b'c', 0)
1540
self.assertBlockRowIndexEqual(1, 3, True, True, state, b'', b'd', 0)
1541
self.assertBlockRowIndexEqual(2, 0, True, True, state, b'a', b'e', 0)
1542
self.assertBlockRowIndexEqual(2, 1, True, True, state, b'a', b'f', 0)
1543
self.assertBlockRowIndexEqual(3, 0, True, True, state, b'b', b'g', 0)
1422
1544
self.assertBlockRowIndexEqual(3, 1, True, True, state,
1423
'b', 'h\xc3\xa5', 0)
1545
b'b', b'h\xc3\xa5', 0)
1425
1547
def test_complex_structure_missing(self):
1426
1548
state = self.create_complex_dirstate()
1427
1549
self.addCleanup(state.unlock)
1428
1550
# Make sure things would be inserted in the right locations
1429
1551
# '_' comes before 'a'
1430
self.assertBlockRowIndexEqual(0, 0, True, True, state, '', '', 0)
1431
self.assertBlockRowIndexEqual(1, 0, True, False, state, '', '_', 0)
1432
self.assertBlockRowIndexEqual(1, 1, True, False, state, '', 'aa', 0)
1552
self.assertBlockRowIndexEqual(0, 0, True, True, state, b'', b'', 0)
1553
self.assertBlockRowIndexEqual(1, 0, True, False, state, b'', b'_', 0)
1554
self.assertBlockRowIndexEqual(1, 1, True, False, state, b'', b'aa', 0)
1433
1555
self.assertBlockRowIndexEqual(1, 4, True, False, state,
1435
self.assertBlockRowIndexEqual(2, 0, False, False, state, '_', 'a', 0)
1436
self.assertBlockRowIndexEqual(3, 0, False, False, state, 'aa', 'a', 0)
1437
self.assertBlockRowIndexEqual(4, 0, False, False, state, 'bb', 'a', 0)
1556
b'', b'h\xc3\xa5', 0)
1557
self.assertBlockRowIndexEqual(2, 0, False, False, state, b'_', b'a', 0)
1558
self.assertBlockRowIndexEqual(3, 0, False, False, state, b'aa', b'a', 0)
1559
self.assertBlockRowIndexEqual(4, 0, False, False, state, b'bb', b'a', 0)
1438
1560
# This would be inserted between a/ and b/
1439
self.assertBlockRowIndexEqual(3, 0, False, False, state, 'a/e', 'a', 0)
1561
self.assertBlockRowIndexEqual(3, 0, False, False, state, b'a/e', b'a', 0)
1440
1562
# Put at the end
1441
self.assertBlockRowIndexEqual(4, 0, False, False, state, 'e', 'a', 0)
1563
self.assertBlockRowIndexEqual(4, 0, False, False, state, b'e', b'a', 0)
1444
1566
class TestGetEntry(TestCaseWithDirState):
1455
1577
def test_simple_structure(self):
1456
1578
state = self.create_dirstate_with_root_and_subdir()
1457
1579
self.addCleanup(state.unlock)
1458
self.assertEntryEqual('', '', 'a-root-value', state, '', 0)
1459
self.assertEntryEqual('', 'subdir', 'subdir-id', state, 'subdir', 0)
1460
self.assertEntryEqual(None, None, None, state, 'missing', 0)
1461
self.assertEntryEqual(None, None, None, state, 'missing/foo', 0)
1462
self.assertEntryEqual(None, None, None, state, 'subdir/foo', 0)
1580
self.assertEntryEqual(b'', b'', b'a-root-value', state, b'', 0)
1581
self.assertEntryEqual(b'', b'subdir', b'subdir-id', state, b'subdir', 0)
1582
self.assertEntryEqual(None, None, None, state, b'missing', 0)
1583
self.assertEntryEqual(None, None, None, state, b'missing/foo', 0)
1584
self.assertEntryEqual(None, None, None, state, b'subdir/foo', 0)
1464
1586
def test_complex_structure_exists(self):
1465
1587
state = self.create_complex_dirstate()
1466
1588
self.addCleanup(state.unlock)
1467
self.assertEntryEqual('', '', 'a-root-value', state, '', 0)
1468
self.assertEntryEqual('', 'a', 'a-dir', state, 'a', 0)
1469
self.assertEntryEqual('', 'b', 'b-dir', state, 'b', 0)
1470
self.assertEntryEqual('', 'c', 'c-file', state, 'c', 0)
1471
self.assertEntryEqual('', 'd', 'd-file', state, 'd', 0)
1472
self.assertEntryEqual('a', 'e', 'e-dir', state, 'a/e', 0)
1473
self.assertEntryEqual('a', 'f', 'f-file', state, 'a/f', 0)
1474
self.assertEntryEqual('b', 'g', 'g-file', state, 'b/g', 0)
1475
self.assertEntryEqual('b', 'h\xc3\xa5', 'h-\xc3\xa5-file', state,
1589
self.assertEntryEqual(b'', b'', b'a-root-value', state, b'', 0)
1590
self.assertEntryEqual(b'', b'a', b'a-dir', state, b'a', 0)
1591
self.assertEntryEqual(b'', b'b', b'b-dir', state, b'b', 0)
1592
self.assertEntryEqual(b'', b'c', b'c-file', state, b'c', 0)
1593
self.assertEntryEqual(b'', b'd', b'd-file', state, b'd', 0)
1594
self.assertEntryEqual(b'a', b'e', b'e-dir', state, b'a/e', 0)
1595
self.assertEntryEqual(b'a', b'f', b'f-file', state, b'a/f', 0)
1596
self.assertEntryEqual(b'b', b'g', b'g-file', state, b'b/g', 0)
1597
self.assertEntryEqual(b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file', state,
1478
1600
def test_complex_structure_missing(self):
1479
1601
state = self.create_complex_dirstate()
1480
1602
self.addCleanup(state.unlock)
1481
self.assertEntryEqual(None, None, None, state, '_', 0)
1482
self.assertEntryEqual(None, None, None, state, '_\xc3\xa5', 0)
1483
self.assertEntryEqual(None, None, None, state, 'a/b', 0)
1484
self.assertEntryEqual(None, None, None, state, 'c/d', 0)
1603
self.assertEntryEqual(None, None, None, state, b'_', 0)
1604
self.assertEntryEqual(None, None, None, state, b'_\xc3\xa5', 0)
1605
self.assertEntryEqual(None, None, None, state, b'a/b', 0)
1606
self.assertEntryEqual(None, None, None, state, b'c/d', 0)
1486
1608
def test_get_entry_uninitialized(self):
1487
1609
"""Calling get_entry will load data if it needs to"""
1529
1651
:return: The dirstate, still write-locked.
1531
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1532
null_sha = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1653
packed_stat = b'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1654
null_sha = b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1533
1655
NULL_PARENT_DETAILS = dirstate.DirState.NULL_PARENT_DETAILS
1534
root_entry = ('', '', 'a-root-value'), [
1535
('d', '', 0, False, packed_stat),
1536
('d', '', 0, False, 'parent-revid'),
1538
a_entry = ('', 'a', 'a-dir'), [
1539
('d', '', 0, False, packed_stat),
1540
('d', '', 0, False, 'parent-revid'),
1542
b_entry = ('', 'b', 'b-dir'), [
1543
('d', '', 0, False, packed_stat),
1544
('d', '', 0, False, 'parent-revid'),
1546
c_entry = ('', 'c', 'c-file'), [
1547
('f', null_sha, 10, False, packed_stat),
1548
('r', 'b/j', 0, False, ''),
1550
d_entry = ('', 'd', 'd-file'), [
1551
('f', null_sha, 20, False, packed_stat),
1552
('f', 'd', 20, False, 'parent-revid'),
1554
e_entry = ('a', 'e', 'e-dir'), [
1555
('d', '', 0, False, packed_stat),
1556
('d', '', 0, False, 'parent-revid'),
1558
f_entry = ('a', 'f', 'f-file'), [
1559
('f', null_sha, 30, False, packed_stat),
1560
('f', 'f', 20, False, 'parent-revid'),
1562
g_entry = ('b', 'g', 'g-file'), [
1563
('f', null_sha, 30, False, packed_stat),
1564
NULL_PARENT_DETAILS,
1566
h_entry1 = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file1'), [
1567
('f', null_sha, 40, False, packed_stat),
1568
NULL_PARENT_DETAILS,
1570
h_entry2 = ('b', 'h\xc3\xa5', 'h-\xc3\xa5-file2'), [
1571
NULL_PARENT_DETAILS,
1572
('f', 'h', 20, False, 'parent-revid'),
1574
i_entry = ('b', 'i', 'i-file'), [
1575
NULL_PARENT_DETAILS,
1576
('f', 'h', 20, False, 'parent-revid'),
1578
j_entry = ('b', 'j', 'c-file'), [
1579
('r', 'c', 0, False, ''),
1580
('f', 'j', 20, False, 'parent-revid'),
1656
root_entry = (b'', b'', b'a-root-value'), [
1657
(b'd', b'', 0, False, packed_stat),
1658
(b'd', b'', 0, False, b'parent-revid'),
1660
a_entry = (b'', b'a', b'a-dir'), [
1661
(b'd', b'', 0, False, packed_stat),
1662
(b'd', b'', 0, False, b'parent-revid'),
1664
b_entry = (b'', b'b', b'b-dir'), [
1665
(b'd', b'', 0, False, packed_stat),
1666
(b'd', b'', 0, False, b'parent-revid'),
1668
c_entry = (b'', b'c', b'c-file'), [
1669
(b'f', null_sha, 10, False, packed_stat),
1670
(b'r', b'b/j', 0, False, b''),
1672
d_entry = (b'', b'd', b'd-file'), [
1673
(b'f', null_sha, 20, False, packed_stat),
1674
(b'f', b'd', 20, False, b'parent-revid'),
1676
e_entry = (b'a', b'e', b'e-dir'), [
1677
(b'd', b'', 0, False, packed_stat),
1678
(b'd', b'', 0, False, b'parent-revid'),
1680
f_entry = (b'a', b'f', b'f-file'), [
1681
(b'f', null_sha, 30, False, packed_stat),
1682
(b'f', b'f', 20, False, b'parent-revid'),
1684
g_entry = (b'b', b'g', b'g-file'), [
1685
(b'f', null_sha, 30, False, packed_stat),
1686
NULL_PARENT_DETAILS,
1688
h_entry1 = (b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file1'), [
1689
(b'f', null_sha, 40, False, packed_stat),
1690
NULL_PARENT_DETAILS,
1692
h_entry2 = (b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file2'), [
1693
NULL_PARENT_DETAILS,
1694
(b'f', b'h', 20, False, b'parent-revid'),
1696
i_entry = (b'b', b'i', b'i-file'), [
1697
NULL_PARENT_DETAILS,
1698
(b'f', b'h', 20, False, b'parent-revid'),
1700
j_entry = (b'b', b'j', b'c-file'), [
1701
(b'r', b'c', 0, False, b''),
1702
(b'f', b'j', 20, False, b'parent-revid'),
1583
dirblocks.append(('', [root_entry]))
1584
dirblocks.append(('', [a_entry, b_entry, c_entry, d_entry]))
1585
dirblocks.append(('a', [e_entry, f_entry]))
1586
dirblocks.append(('b', [g_entry, h_entry1, h_entry2, i_entry, j_entry]))
1705
dirblocks.append((b'', [root_entry]))
1706
dirblocks.append((b'', [a_entry, b_entry, c_entry, d_entry]))
1707
dirblocks.append((b'a', [e_entry, f_entry]))
1708
dirblocks.append((b'b', [g_entry, h_entry1, h_entry2, i_entry, j_entry]))
1587
1709
state = dirstate.DirState.initialize('dirstate')
1588
1710
state._validate()
1590
state._set_data(['parent'], dirblocks)
1712
state._set_data([b'parent'], dirblocks)
1874
1997
tree, state, expected = self.create_basic_dirstate()
1876
1999
# Bisect should return the rows for the specified files.
1877
self.assertBisect(expected, [['']], state, [''])
1878
self.assertBisect(expected, [['a']], state, ['a'])
1879
self.assertBisect(expected, [['b']], state, ['b'])
1880
self.assertBisect(expected, [['b/c']], state, ['b/c'])
1881
self.assertBisect(expected, [['b/d']], state, ['b/d'])
1882
self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1883
self.assertBisect(expected, [['b-c']], state, ['b-c'])
1884
self.assertBisect(expected, [['f']], state, ['f'])
2000
self.assertBisect(expected, [[b'']], state, [b''])
2001
self.assertBisect(expected, [[b'a']], state, [b'a'])
2002
self.assertBisect(expected, [[b'b']], state, [b'b'])
2003
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2004
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2005
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2006
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2007
self.assertBisect(expected, [[b'f']], state, [b'f'])
1886
2009
def test_bisect_multi(self):
1887
2010
"""Bisect can be used to find multiple records at the same time."""
1888
2011
tree, state, expected = self.create_basic_dirstate()
1889
2012
# Bisect should be capable of finding multiple entries at the same time
1890
self.assertBisect(expected, [['a'], ['b'], ['f']],
1891
state, ['a', 'b', 'f'])
1892
self.assertBisect(expected, [['f'], ['b/d'], ['b/d/e']],
1893
state, ['f', 'b/d', 'b/d/e'])
1894
self.assertBisect(expected, [['b'], ['b-c'], ['b/c']],
1895
state, ['b', 'b-c', 'b/c'])
2013
self.assertBisect(expected, [[b'a'], [b'b'], [b'f']],
2014
state, [b'a', b'b', b'f'])
2015
self.assertBisect(expected, [[b'f'], [b'b/d'], [b'b/d/e']],
2016
state, [b'f', b'b/d', b'b/d/e'])
2017
self.assertBisect(expected, [[b'b'], [b'b-c'], [b'b/c']],
2018
state, [b'b', b'b-c', b'b/c'])
1897
2020
def test_bisect_one_page(self):
1898
2021
"""Test bisect when there is only 1 page to read"""
1899
2022
tree, state, expected = self.create_basic_dirstate()
1900
2023
state._bisect_page_size = 5000
1901
self.assertBisect(expected,[['']], state, [''])
1902
self.assertBisect(expected,[['a']], state, ['a'])
1903
self.assertBisect(expected,[['b']], state, ['b'])
1904
self.assertBisect(expected,[['b/c']], state, ['b/c'])
1905
self.assertBisect(expected,[['b/d']], state, ['b/d'])
1906
self.assertBisect(expected,[['b/d/e']], state, ['b/d/e'])
1907
self.assertBisect(expected,[['b-c']], state, ['b-c'])
1908
self.assertBisect(expected,[['f']], state, ['f'])
1909
self.assertBisect(expected,[['a'], ['b'], ['f']],
1910
state, ['a', 'b', 'f'])
1911
self.assertBisect(expected, [['b/d'], ['b/d/e'], ['f']],
1912
state, ['b/d', 'b/d/e', 'f'])
1913
self.assertBisect(expected, [['b'], ['b/c'], ['b-c']],
1914
state, ['b', 'b/c', 'b-c'])
2024
self.assertBisect(expected, [[b'']], state, [b''])
2025
self.assertBisect(expected, [[b'a']], state, [b'a'])
2026
self.assertBisect(expected, [[b'b']], state, [b'b'])
2027
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2028
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2029
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2030
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2031
self.assertBisect(expected, [[b'f']], state, [b'f'])
2032
self.assertBisect(expected, [[b'a'], [b'b'], [b'f']],
2033
state, [b'a', b'b', b'f'])
2034
self.assertBisect(expected, [[b'b/d'], [b'b/d/e'], [b'f']],
2035
state, [b'b/d', b'b/d/e', b'f'])
2036
self.assertBisect(expected, [[b'b'], [b'b/c'], [b'b-c']],
2037
state, [b'b', b'b/c', b'b-c'])
1916
2039
def test_bisect_duplicate_paths(self):
1917
2040
"""When bisecting for a path, handle multiple entries."""
1918
2041
tree, state, expected = self.create_duplicated_dirstate()
1920
2043
# Now make sure that both records are properly returned.
1921
self.assertBisect(expected, [['']], state, [''])
1922
self.assertBisect(expected, [['a', 'a2']], state, ['a'])
1923
self.assertBisect(expected, [['b', 'b2']], state, ['b'])
1924
self.assertBisect(expected, [['b/c', 'b/c2']], state, ['b/c'])
1925
self.assertBisect(expected, [['b/d', 'b/d2']], state, ['b/d'])
1926
self.assertBisect(expected, [['b/d/e', 'b/d/e2']],
1928
self.assertBisect(expected, [['b-c', 'b-c2']], state, ['b-c'])
1929
self.assertBisect(expected, [['f', 'f2']], state, ['f'])
2044
self.assertBisect(expected, [[b'']], state, [b''])
2045
self.assertBisect(expected, [[b'a', b'a2']], state, [b'a'])
2046
self.assertBisect(expected, [[b'b', b'b2']], state, [b'b'])
2047
self.assertBisect(expected, [[b'b/c', b'b/c2']], state, [b'b/c'])
2048
self.assertBisect(expected, [[b'b/d', b'b/d2']], state, [b'b/d'])
2049
self.assertBisect(expected, [[b'b/d/e', b'b/d/e2']],
2051
self.assertBisect(expected, [[b'b-c', b'b-c2']], state, [b'b-c'])
2052
self.assertBisect(expected, [[b'f', b'f2']], state, [b'f'])
1931
2054
def test_bisect_page_size_too_small(self):
1932
2055
"""If the page size is too small, we will auto increase it."""
1933
2056
tree, state, expected = self.create_basic_dirstate()
1934
2057
state._bisect_page_size = 50
1935
self.assertBisect(expected, [None], state, ['b/e'])
1936
self.assertBisect(expected, [['a']], state, ['a'])
1937
self.assertBisect(expected, [['b']], state, ['b'])
1938
self.assertBisect(expected, [['b/c']], state, ['b/c'])
1939
self.assertBisect(expected, [['b/d']], state, ['b/d'])
1940
self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1941
self.assertBisect(expected, [['b-c']], state, ['b-c'])
1942
self.assertBisect(expected, [['f']], state, ['f'])
2058
self.assertBisect(expected, [None], state, [b'b/e'])
2059
self.assertBisect(expected, [[b'a']], state, [b'a'])
2060
self.assertBisect(expected, [[b'b']], state, [b'b'])
2061
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2062
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2063
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2064
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2065
self.assertBisect(expected, [[b'f']], state, [b'f'])
1944
2067
def test_bisect_missing(self):
1945
2068
"""Test that bisect return None if it cannot find a path."""
1946
2069
tree, state, expected = self.create_basic_dirstate()
1947
self.assertBisect(expected, [None], state, ['foo'])
1948
self.assertBisect(expected, [None], state, ['b/foo'])
1949
self.assertBisect(expected, [None], state, ['bar/foo'])
1950
self.assertBisect(expected, [None], state, ['b-c/foo'])
2070
self.assertBisect(expected, [None], state, [b'foo'])
2071
self.assertBisect(expected, [None], state, [b'b/foo'])
2072
self.assertBisect(expected, [None], state, [b'bar/foo'])
2073
self.assertBisect(expected, [None], state, [b'b-c/foo'])
1952
self.assertBisect(expected, [['a'], None, ['b/d']],
1953
state, ['a', 'foo', 'b/d'])
2075
self.assertBisect(expected, [[b'a'], None, [b'b/d']],
2076
state, [b'a', b'foo', b'b/d'])
1955
2078
def test_bisect_rename(self):
1956
2079
"""Check that we find a renamed row."""
1957
2080
tree, state, expected = self.create_renamed_dirstate()
1959
2082
# Search for the pre and post renamed entries
1960
self.assertBisect(expected, [['a']], state, ['a'])
1961
self.assertBisect(expected, [['b/g']], state, ['b/g'])
1962
self.assertBisect(expected, [['b/d']], state, ['b/d'])
1963
self.assertBisect(expected, [['h']], state, ['h'])
2083
self.assertBisect(expected, [[b'a']], state, [b'a'])
2084
self.assertBisect(expected, [[b'b/g']], state, [b'b/g'])
2085
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2086
self.assertBisect(expected, [[b'h']], state, [b'h'])
1965
2088
# What about b/d/e? shouldn't that also get 2 directory entries?
1966
self.assertBisect(expected, [['b/d/e']], state, ['b/d/e'])
1967
self.assertBisect(expected, [['h/e']], state, ['h/e'])
2089
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2090
self.assertBisect(expected, [[b'h/e']], state, [b'h/e'])
1969
2092
def test_bisect_dirblocks(self):
1970
2093
tree, state, expected = self.create_duplicated_dirstate()
1971
2094
self.assertBisectDirBlocks(expected,
1972
[['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2']],
1974
self.assertBisectDirBlocks(expected,
1975
[['b/c', 'b/c2', 'b/d', 'b/d2']], state, ['b'])
1976
self.assertBisectDirBlocks(expected,
1977
[['b/d/e', 'b/d/e2']], state, ['b/d'])
1978
self.assertBisectDirBlocks(expected,
1979
[['', 'a', 'a2', 'b', 'b2', 'b-c', 'b-c2', 'f', 'f2'],
1980
['b/c', 'b/c2', 'b/d', 'b/d2'],
1981
['b/d/e', 'b/d/e2'],
1982
], state, ['', 'b', 'b/d'])
2095
[[b'', b'a', b'a2', b'b', b'b2', b'b-c', b'b-c2', b'f', b'f2']],
2097
self.assertBisectDirBlocks(expected,
2098
[[b'b/c', b'b/c2', b'b/d', b'b/d2']], state, [b'b'])
2099
self.assertBisectDirBlocks(expected,
2100
[[b'b/d/e', b'b/d/e2']], state, [b'b/d'])
2101
self.assertBisectDirBlocks(expected,
2102
[[b'', b'a', b'a2', b'b', b'b2', b'b-c', b'b-c2', b'f', b'f2'],
2103
[b'b/c', b'b/c2', b'b/d', b'b/d2'],
2104
[b'b/d/e', b'b/d/e2'],
2105
], state, [b'', b'b', b'b/d'])
1984
2107
def test_bisect_dirblocks_missing(self):
1985
2108
tree, state, expected = self.create_basic_dirstate()
1986
self.assertBisectDirBlocks(expected, [['b/d/e'], None],
1987
state, ['b/d', 'b/e'])
2109
self.assertBisectDirBlocks(expected, [[b'b/d/e'], None],
2110
state, [b'b/d', b'b/e'])
1988
2111
# Files don't show up in this search
1989
self.assertBisectDirBlocks(expected, [None], state, ['a'])
1990
self.assertBisectDirBlocks(expected, [None], state, ['b/c'])
1991
self.assertBisectDirBlocks(expected, [None], state, ['c'])
1992
self.assertBisectDirBlocks(expected, [None], state, ['b/d/e'])
1993
self.assertBisectDirBlocks(expected, [None], state, ['f'])
2112
self.assertBisectDirBlocks(expected, [None], state, [b'a'])
2113
self.assertBisectDirBlocks(expected, [None], state, [b'b/c'])
2114
self.assertBisectDirBlocks(expected, [None], state, [b'c'])
2115
self.assertBisectDirBlocks(expected, [None], state, [b'b/d/e'])
2116
self.assertBisectDirBlocks(expected, [None], state, [b'f'])
1995
2118
def test_bisect_recursive_each(self):
1996
2119
tree, state, expected = self.create_basic_dirstate()
1997
self.assertBisectRecursive(expected, ['a'], state, ['a'])
1998
self.assertBisectRecursive(expected, ['b/c'], state, ['b/c'])
1999
self.assertBisectRecursive(expected, ['b/d/e'], state, ['b/d/e'])
2000
self.assertBisectRecursive(expected, ['b-c'], state, ['b-c'])
2001
self.assertBisectRecursive(expected, ['b/d', 'b/d/e'],
2003
self.assertBisectRecursive(expected, ['b', 'b/c', 'b/d', 'b/d/e'],
2005
self.assertBisectRecursive(expected, ['', 'a', 'b', 'b-c', 'f', 'b/c',
2120
self.assertBisectRecursive(expected, [b'a'], state, [b'a'])
2121
self.assertBisectRecursive(expected, [b'b/c'], state, [b'b/c'])
2122
self.assertBisectRecursive(expected, [b'b/d/e'], state, [b'b/d/e'])
2123
self.assertBisectRecursive(expected, [b'b-c'], state, [b'b-c'])
2124
self.assertBisectRecursive(expected, [b'b/d', b'b/d/e'],
2126
self.assertBisectRecursive(expected, [b'b', b'b/c', b'b/d', b'b/d/e'],
2128
self.assertBisectRecursive(expected, [b'', b'a', b'b', b'b-c', b'f', b'b/c',
2009
2132
def test_bisect_recursive_multiple(self):
2010
2133
tree, state, expected = self.create_basic_dirstate()
2011
self.assertBisectRecursive(expected, ['a', 'b/c'], state, ['a', 'b/c'])
2012
self.assertBisectRecursive(expected, ['b/d', 'b/d/e'],
2013
state, ['b/d', 'b/d/e'])
2134
self.assertBisectRecursive(expected, [b'a', b'b/c'], state, [b'a', b'b/c'])
2135
self.assertBisectRecursive(expected, [b'b/d', b'b/d/e'],
2136
state, [b'b/d', b'b/d/e'])
2015
2138
def test_bisect_recursive_missing(self):
2016
2139
tree, state, expected = self.create_basic_dirstate()
2017
self.assertBisectRecursive(expected, [], state, ['d'])
2018
self.assertBisectRecursive(expected, [], state, ['b/e'])
2019
self.assertBisectRecursive(expected, [], state, ['g'])
2020
self.assertBisectRecursive(expected, ['a'], state, ['a', 'g'])
2140
self.assertBisectRecursive(expected, [], state, [b'd'])
2141
self.assertBisectRecursive(expected, [], state, [b'b/e'])
2142
self.assertBisectRecursive(expected, [], state, [b'g'])
2143
self.assertBisectRecursive(expected, [b'a'], state, [b'a', b'g'])
2022
2145
def test_bisect_recursive_renamed(self):
2023
2146
tree, state, expected = self.create_renamed_dirstate()
2025
2148
# Looking for either renamed item should find the other
2026
self.assertBisectRecursive(expected, ['a', 'b/g'], state, ['a'])
2027
self.assertBisectRecursive(expected, ['a', 'b/g'], state, ['b/g'])
2149
self.assertBisectRecursive(expected, [b'a', b'b/g'], state, [b'a'])
2150
self.assertBisectRecursive(expected, [b'a', b'b/g'], state, [b'b/g'])
2028
2151
# Looking in the containing directory should find the rename target,
2029
2152
# and anything in a subdir of the renamed target.
2030
self.assertBisectRecursive(expected, ['a', 'b', 'b/c', 'b/d',
2031
'b/d/e', 'b/g', 'h', 'h/e'],
2153
self.assertBisectRecursive(expected, [b'a', b'b', b'b/c', b'b/d',
2154
b'b/d/e', b'b/g', b'h', b'h/e'],
2035
2158
class TestDirstateValidation(TestCaseWithDirState):
2141
2264
def test_discard_simple(self):
2143
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2144
root_entry_direntry = ('', '', 'a-root-value'), [
2145
('d', '', 0, False, packed_stat),
2146
('d', '', 0, False, packed_stat),
2147
('d', '', 0, False, packed_stat),
2266
packed_stat = b'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2267
root_entry_direntry = (b'', b'', b'a-root-value'), [
2268
(b'd', b'', 0, False, packed_stat),
2269
(b'd', b'', 0, False, packed_stat),
2270
(b'd', b'', 0, False, packed_stat),
2149
expected_root_entry_direntry = ('', '', 'a-root-value'), [
2150
('d', '', 0, False, packed_stat),
2151
('d', '', 0, False, packed_stat),
2272
expected_root_entry_direntry = (b'', b'', b'a-root-value'), [
2273
(b'd', b'', 0, False, packed_stat),
2274
(b'd', b'', 0, False, packed_stat),
2154
dirblocks.append(('', [root_entry_direntry]))
2155
dirblocks.append(('', []))
2277
dirblocks.append((b'', [root_entry_direntry]))
2278
dirblocks.append((b'', []))
2157
2280
state = self.create_empty_dirstate()
2158
2281
self.addCleanup(state.unlock)
2159
state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2282
state._set_data([b'parent-id', b'merged-id'], dirblocks[:])
2160
2283
state._validate()
2162
2285
# This should strip of the extra column
2163
2286
state._discard_merge_parents()
2164
2287
state._validate()
2165
expected_dirblocks = [('', [expected_root_entry_direntry]), ('', [])]
2288
expected_dirblocks = [(b'', [expected_root_entry_direntry]), (b'', [])]
2166
2289
self.assertEqual(expected_dirblocks, state._dirblocks)
2168
2291
def test_discard_absent(self):
2169
2292
"""If entries are only in a merge, discard should remove the entries"""
2170
2293
null_stat = dirstate.DirState.NULLSTAT
2171
present_dir = ('d', '', 0, False, null_stat)
2172
present_file = ('f', '', 0, False, null_stat)
2294
present_dir = (b'd', b'', 0, False, null_stat)
2295
present_file = (b'f', b'', 0, False, null_stat)
2173
2296
absent = dirstate.DirState.NULL_PARENT_DETAILS
2174
root_key = ('', '', 'a-root-value')
2175
file_in_root_key = ('', 'file-in-root', 'a-file-id')
2176
file_in_merged_key = ('', 'file-in-merged', 'b-file-id')
2177
dirblocks = [('', [(root_key, [present_dir, present_dir, present_dir])]),
2178
('', [(file_in_merged_key,
2297
root_key = (b'', b'', b'a-root-value')
2298
file_in_root_key = (b'', b'file-in-root', b'a-file-id')
2299
file_in_merged_key = (b'', b'file-in-merged', b'b-file-id')
2300
dirblocks = [(b'', [(root_key, [present_dir, present_dir, present_dir])]),
2301
(b'', [(file_in_merged_key,
2179
2302
[absent, absent, present_file]),
2180
2303
(file_in_root_key,
2181
2304
[present_file, present_file, present_file]),
2320
2443
self.assertTrue(len(statvalue) >= 10)
2321
2444
self.assertEqual(len(text), statvalue.st_size)
2322
2445
self.assertEqual(expected_sha, sha1)
2448
class _Repo(object):
2449
"""A minimal api to get InventoryRevisionTree to work."""
2452
default_format = controldir.format_registry.make_controldir('default')
2453
self._format = default_format.repository_format
2455
def lock_read(self):
2462
class TestUpdateBasisByDelta(tests.TestCase):
2464
def path_to_ie(self, path, file_id, rev_id, dir_ids):
2465
if path.endswith('/'):
2470
dirname, basename = osutils.split(path)
2472
dir_id = dir_ids[dirname]
2474
dir_id = osutils.basename(dirname).encode('utf-8') + b'-id'
2476
ie = inventory.InventoryDirectory(file_id, basename, dir_id)
2477
dir_ids[path] = file_id
2479
ie = inventory.InventoryFile(file_id, basename, dir_id)
2482
ie.revision = rev_id
2485
def create_tree_from_shape(self, rev_id, shape):
2486
dir_ids = {'': b'root-id'}
2487
inv = inventory.Inventory(b'root-id', rev_id)
2490
path, file_id = info
2493
path, file_id, ie_rev_id = info
2495
# Replace the root entry
2496
del inv._byid[inv.root.file_id]
2497
inv.root.file_id = file_id
2498
inv._byid[file_id] = inv.root
2499
dir_ids[''] = file_id
2501
inv.add(self.path_to_ie(path, file_id, ie_rev_id, dir_ids))
2502
return inventorytree.InventoryRevisionTree(_Repo(), inv, rev_id)
2504
def create_empty_dirstate(self):
2505
fd, path = tempfile.mkstemp(prefix='bzr-dirstate')
2506
self.addCleanup(os.remove, path)
2508
state = dirstate.DirState.initialize(path)
2509
self.addCleanup(state.unlock)
2512
def create_inv_delta(self, delta, rev_id):
2513
"""Translate a 'delta shape' into an actual InventoryDelta"""
2514
dir_ids = {'': b'root-id'}
2516
for old_path, new_path, file_id in delta:
2517
if old_path is not None and old_path.endswith('/'):
2518
# Don't have to actually do anything for this, because only
2519
# new_path creates InventoryEntries
2520
old_path = old_path[:-1]
2521
if new_path is None: # Delete
2522
inv_delta.append((old_path, None, file_id, None))
2524
ie = self.path_to_ie(new_path, file_id, rev_id, dir_ids)
2525
inv_delta.append((old_path, new_path, file_id, ie))
2528
def assertUpdate(self, active, basis, target):
2529
"""Assert that update_basis_by_delta works how we want.
2531
Set up a DirState object with active_shape for tree 0, basis_shape for
2532
tree 1. Then apply the delta from basis_shape to target_shape,
2533
and assert that the DirState is still valid, and that its stored
2534
content matches the target_shape.
2536
active_tree = self.create_tree_from_shape(b'active', active)
2537
basis_tree = self.create_tree_from_shape(b'basis', basis)
2538
target_tree = self.create_tree_from_shape(b'target', target)
2539
state = self.create_empty_dirstate()
2540
state.set_state_from_scratch(active_tree.root_inventory,
2541
[(b'basis', basis_tree)], [])
2542
delta = target_tree.root_inventory._make_delta(
2543
basis_tree.root_inventory)
2544
state.update_basis_by_delta(delta, b'target')
2546
dirstate_tree = workingtree_4.DirStateRevisionTree(state,
2548
# The target now that delta has been applied should match the
2550
self.assertEqual([], list(dirstate_tree.iter_changes(target_tree)))
2551
# And the dirblock state should be identical to the state if we created
2553
state2 = self.create_empty_dirstate()
2554
state2.set_state_from_scratch(active_tree.root_inventory,
2555
[(b'target', target_tree)], [])
2556
self.assertEqual(state2._dirblocks, state._dirblocks)
2559
def assertBadDelta(self, active, basis, delta):
2560
"""Test that we raise InconsistentDelta when appropriate.
2562
:param active: The active tree shape
2563
:param basis: The basis tree shape
2564
:param delta: A description of the delta to apply. Similar to the form
2565
for regular inventory deltas, but omitting the InventoryEntry.
2566
So adding a file is: (None, 'path', b'file-id')
2567
Adding a directory is: (None, 'path/', b'dir-id')
2568
Renaming a dir is: ('old/', 'new/', b'dir-id')
2571
active_tree = self.create_tree_from_shape(b'active', active)
2572
basis_tree = self.create_tree_from_shape(b'basis', basis)
2573
inv_delta = self.create_inv_delta(delta, b'target')
2574
state = self.create_empty_dirstate()
2575
state.set_state_from_scratch(active_tree.root_inventory,
2576
[(b'basis', basis_tree)], [])
2577
self.assertRaises(errors.InconsistentDelta,
2578
state.update_basis_by_delta, inv_delta, b'target')
2580
## state.update_basis_by_delta(inv_delta, b'target')
2581
## except errors.InconsistentDelta, e:
2582
## import pdb; pdb.set_trace()
2584
## import pdb; pdb.set_trace()
2585
self.assertTrue(state._changes_aborted)
2587
def test_remove_file_matching_active_state(self):
2588
state = self.assertUpdate(
2590
basis =[('file', b'file-id')],
2594
def test_remove_file_present_in_active_state(self):
2595
state = self.assertUpdate(
2596
active=[('file', b'file-id')],
2597
basis =[('file', b'file-id')],
2601
def test_remove_file_present_elsewhere_in_active_state(self):
2602
state = self.assertUpdate(
2603
active=[('other-file', b'file-id')],
2604
basis =[('file', b'file-id')],
2608
def test_remove_file_active_state_has_diff_file(self):
2609
state = self.assertUpdate(
2610
active=[('file', b'file-id-2')],
2611
basis =[('file', b'file-id')],
2615
def test_remove_file_active_state_has_diff_file_and_file_elsewhere(self):
2616
state = self.assertUpdate(
2617
active=[('file', b'file-id-2'),
2618
('other-file', b'file-id')],
2619
basis =[('file', b'file-id')],
2623
def test_add_file_matching_active_state(self):
2624
state = self.assertUpdate(
2625
active=[('file', b'file-id')],
2627
target=[('file', b'file-id')],
2630
def test_add_file_in_empty_dir_not_matching_active_state(self):
2631
state = self.assertUpdate(
2633
basis=[('dir/', b'dir-id')],
2634
target=[('dir/', b'dir-id', b'basis'), ('dir/file', b'file-id')],
2637
def test_add_file_missing_in_active_state(self):
2638
state = self.assertUpdate(
2641
target=[('file', b'file-id')],
2644
def test_add_file_elsewhere_in_active_state(self):
2645
state = self.assertUpdate(
2646
active=[('other-file', b'file-id')],
2648
target=[('file', b'file-id')],
2651
def test_add_file_active_state_has_diff_file_and_file_elsewhere(self):
2652
state = self.assertUpdate(
2653
active=[('other-file', b'file-id'),
2654
('file', b'file-id-2')],
2656
target=[('file', b'file-id')],
2659
def test_rename_file_matching_active_state(self):
2660
state = self.assertUpdate(
2661
active=[('other-file', b'file-id')],
2662
basis =[('file', b'file-id')],
2663
target=[('other-file', b'file-id')],
2666
def test_rename_file_missing_in_active_state(self):
2667
state = self.assertUpdate(
2669
basis =[('file', b'file-id')],
2670
target=[('other-file', b'file-id')],
2673
def test_rename_file_present_elsewhere_in_active_state(self):
2674
state = self.assertUpdate(
2675
active=[('third', b'file-id')],
2676
basis =[('file', b'file-id')],
2677
target=[('other-file', b'file-id')],
2680
def test_rename_file_active_state_has_diff_source_file(self):
2681
state = self.assertUpdate(
2682
active=[('file', b'file-id-2')],
2683
basis =[('file', b'file-id')],
2684
target=[('other-file', b'file-id')],
2687
def test_rename_file_active_state_has_diff_target_file(self):
2688
state = self.assertUpdate(
2689
active=[('other-file', b'file-id-2')],
2690
basis =[('file', b'file-id')],
2691
target=[('other-file', b'file-id')],
2694
def test_rename_file_active_has_swapped_files(self):
2695
state = self.assertUpdate(
2696
active=[('file', b'file-id'),
2697
('other-file', b'file-id-2')],
2698
basis= [('file', b'file-id'),
2699
('other-file', b'file-id-2')],
2700
target=[('file', b'file-id-2'),
2701
('other-file', b'file-id')])
2703
def test_rename_file_basis_has_swapped_files(self):
2704
state = self.assertUpdate(
2705
active=[('file', b'file-id'),
2706
('other-file', b'file-id-2')],
2707
basis= [('file', b'file-id-2'),
2708
('other-file', b'file-id')],
2709
target=[('file', b'file-id'),
2710
('other-file', b'file-id-2')])
2712
def test_rename_directory_with_contents(self):
2713
state = self.assertUpdate( # active matches basis
2714
active=[('dir1/', b'dir-id'),
2715
('dir1/file', b'file-id')],
2716
basis= [('dir1/', b'dir-id'),
2717
('dir1/file', b'file-id')],
2718
target=[('dir2/', b'dir-id'),
2719
('dir2/file', b'file-id')])
2720
state = self.assertUpdate( # active matches target
2721
active=[('dir2/', b'dir-id'),
2722
('dir2/file', b'file-id')],
2723
basis= [('dir1/', b'dir-id'),
2724
('dir1/file', b'file-id')],
2725
target=[('dir2/', b'dir-id'),
2726
('dir2/file', b'file-id')])
2727
state = self.assertUpdate( # active empty
2729
basis= [('dir1/', b'dir-id'),
2730
('dir1/file', b'file-id')],
2731
target=[('dir2/', b'dir-id'),
2732
('dir2/file', b'file-id')])
2733
state = self.assertUpdate( # active present at other location
2734
active=[('dir3/', b'dir-id'),
2735
('dir3/file', b'file-id')],
2736
basis= [('dir1/', b'dir-id'),
2737
('dir1/file', b'file-id')],
2738
target=[('dir2/', b'dir-id'),
2739
('dir2/file', b'file-id')])
2740
state = self.assertUpdate( # active has different ids
2741
active=[('dir1/', b'dir1-id'),
2742
('dir1/file', b'file1-id'),
2743
('dir2/', b'dir2-id'),
2744
('dir2/file', b'file2-id')],
2745
basis= [('dir1/', b'dir-id'),
2746
('dir1/file', b'file-id')],
2747
target=[('dir2/', b'dir-id'),
2748
('dir2/file', b'file-id')])
2750
def test_invalid_file_not_present(self):
2751
state = self.assertBadDelta(
2752
active=[('file', b'file-id')],
2753
basis= [('file', b'file-id')],
2754
delta=[('other-file', 'file', b'file-id')])
2756
def test_invalid_new_id_same_path(self):
2757
# The bad entry comes after
2758
state = self.assertBadDelta(
2759
active=[('file', b'file-id')],
2760
basis= [('file', b'file-id')],
2761
delta=[(None, 'file', b'file-id-2')])
2762
# The bad entry comes first
2763
state = self.assertBadDelta(
2764
active=[('file', b'file-id-2')],
2765
basis=[('file', b'file-id-2')],
2766
delta=[(None, 'file', b'file-id')])
2768
def test_invalid_existing_id(self):
2769
state = self.assertBadDelta(
2770
active=[('file', b'file-id')],
2771
basis= [('file', b'file-id')],
2772
delta=[(None, 'file', b'file-id')])
2774
def test_invalid_parent_missing(self):
2775
state = self.assertBadDelta(
2778
delta=[(None, 'path/path2', b'file-id')])
2779
# Note: we force the active tree to have the directory, by knowing how
2780
# path_to_ie handles entries with missing parents
2781
state = self.assertBadDelta(
2782
active=[('path/', b'path-id')],
2784
delta=[(None, 'path/path2', b'file-id')])
2785
state = self.assertBadDelta(
2786
active=[('path/', b'path-id'),
2787
('path/path2', b'file-id')],
2789
delta=[(None, 'path/path2', b'file-id')])
2791
def test_renamed_dir_same_path(self):
2792
# We replace the parent directory, with another parent dir. But the C
2793
# file doesn't look like it has been moved.
2794
state = self.assertUpdate(# Same as basis
2795
active=[('dir/', b'A-id'),
2796
('dir/B', b'B-id')],
2797
basis= [('dir/', b'A-id'),
2798
('dir/B', b'B-id')],
2799
target=[('dir/', b'C-id'),
2800
('dir/B', b'B-id')])
2801
state = self.assertUpdate(# Same as target
2802
active=[('dir/', b'C-id'),
2803
('dir/B', b'B-id')],
2804
basis= [('dir/', b'A-id'),
2805
('dir/B', b'B-id')],
2806
target=[('dir/', b'C-id'),
2807
('dir/B', b'B-id')])
2808
state = self.assertUpdate(# empty active
2810
basis= [('dir/', b'A-id'),
2811
('dir/B', b'B-id')],
2812
target=[('dir/', b'C-id'),
2813
('dir/B', b'B-id')])
2814
state = self.assertUpdate(# different active
2815
active=[('dir/', b'D-id'),
2816
('dir/B', b'B-id')],
2817
basis= [('dir/', b'A-id'),
2818
('dir/B', b'B-id')],
2819
target=[('dir/', b'C-id'),
2820
('dir/B', b'B-id')])
2822
def test_parent_child_swap(self):
2823
state = self.assertUpdate(# Same as basis
2824
active=[('A/', b'A-id'),
2826
('A/B/C', b'C-id')],
2827
basis= [('A/', b'A-id'),
2829
('A/B/C', b'C-id')],
2830
target=[('A/', b'B-id'),
2832
('A/B/C', b'C-id')])
2833
state = self.assertUpdate(# Same as target
2834
active=[('A/', b'B-id'),
2836
('A/B/C', b'C-id')],
2837
basis= [('A/', b'A-id'),
2839
('A/B/C', b'C-id')],
2840
target=[('A/', b'B-id'),
2842
('A/B/C', b'C-id')])
2843
state = self.assertUpdate(# empty active
2845
basis= [('A/', b'A-id'),
2847
('A/B/C', b'C-id')],
2848
target=[('A/', b'B-id'),
2850
('A/B/C', b'C-id')])
2851
state = self.assertUpdate(# different active
2852
active=[('D/', b'A-id'),
2855
basis= [('A/', b'A-id'),
2857
('A/B/C', b'C-id')],
2858
target=[('A/', b'B-id'),
2860
('A/B/C', b'C-id')])
2862
def test_change_root_id(self):
2863
state = self.assertUpdate( # same as basis
2864
active=[('', b'root-id'),
2865
('file', b'file-id')],
2866
basis= [('', b'root-id'),
2867
('file', b'file-id')],
2868
target=[('', b'target-root-id'),
2869
('file', b'file-id')])
2870
state = self.assertUpdate( # same as target
2871
active=[('', b'target-root-id'),
2872
('file', b'file-id')],
2873
basis= [('', b'root-id'),
2874
('file', b'file-id')],
2875
target=[('', b'target-root-id'),
2876
('file', b'root-id')])
2877
state = self.assertUpdate( # all different
2878
active=[('', b'active-root-id'),
2879
('file', b'file-id')],
2880
basis= [('', b'root-id'),
2881
('file', b'file-id')],
2882
target=[('', b'target-root-id'),
2883
('file', b'root-id')])
2885
def test_change_file_absent_in_active(self):
2886
state = self.assertUpdate(
2888
basis= [('file', b'file-id')],
2889
target=[('file', b'file-id')])
2891
def test_invalid_changed_file(self):
2892
state = self.assertBadDelta( # Not present in basis
2893
active=[('file', b'file-id')],
2895
delta=[('file', 'file', b'file-id')])
2896
state = self.assertBadDelta( # present at another location in basis
2897
active=[('file', b'file-id')],
2898
basis= [('other-file', b'file-id')],
2899
delta=[('file', 'file', b'file-id')])