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
256
f_len = len(f_text)
242
257
null_stat = dirstate.DirState.NULLSTAT
244
'':(('', '', 'TREE_ROOT'), [
245
('d', '', 0, False, null_stat),
246
('d', '', 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),
259
b'': ((b'', b'', b'TREE_ROOT'), [
260
(b'd', b'', 0, False, null_stat),
261
(b'd', b'', 0, False, revision_id),
263
b'a': ((b'', b'a', b'a-id'), [
264
(b'f', b'', 0, False, null_stat),
265
(b'f', a_sha, a_len, False, revision_id),
267
b'b': ((b'', b'b', b'b-id'), [
268
(b'd', b'', 0, False, null_stat),
269
(b'd', b'', 0, False, revision_id),
271
b'b/c': ((b'b', b'c', b'c-id'), [
272
(b'f', b'', 0, False, null_stat),
273
(b'f', c_sha, c_len, False, revision_id),
275
b'b/d': ((b'b', b'd', b'd-id'), [
276
(b'd', b'', 0, False, null_stat),
277
(b'd', b'', 0, False, revision_id),
279
b'b/d/e': ((b'b/d', b'e', b'e-id'), [
280
(b'f', b'', 0, False, null_stat),
281
(b'f', e_sha, e_len, False, revision_id),
283
b'b-c': ((b'', b'b-c', b'b-c-id'), [
284
(b'f', b'', 0, False, null_stat),
285
(b'f', b_c_sha, b_c_len, False, revision_id),
287
b'f': ((b'', b'f', b'f-id'), [
288
(b'f', b'', 0, False, null_stat),
289
(b'f', f_sha, f_len, False, revision_id),
277
292
state = dirstate.DirState.from_tree(tree, 'dirstate')
900
971
"""Set the root file id in a dirstate with parents"""
901
972
mt = self.make_branch_and_tree('mt')
902
973
# 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')
974
mt.set_root_id(b'TREE_ROOT')
975
mt.commit('foo', rev_id=b'parent-revid')
976
rt = mt.branch.repository.revision_tree(b'parent-revid')
906
977
state = dirstate.DirState.initialize('dirstate')
907
978
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=''))
980
state.set_parent_trees([(b'parent-revid', rt)], ghosts=[])
981
root_entry = ((b'', b'', b'TREE_ROOT'),
982
[(b'd', b'', 0, False, b'x' * 32),
983
(b'd', b'', 0, False, b'parent-revid')])
984
self.assertEqual(root_entry, state._get_entry(0, path_utf8=b''))
914
985
self.assertEqual(root_entry,
915
state._get_entry(0, fileid_utf8='TREE_ROOT'))
986
state._get_entry(0, fileid_utf8=b'TREE_ROOT'))
916
987
self.assertEqual((None, None),
917
state._get_entry(0, fileid_utf8='Asecond-root-id'))
918
state.set_path_id('', 'Asecond-root-id')
988
state._get_entry(0, fileid_utf8=b'Asecond-root-id'))
989
state.set_path_id(b'', b'Asecond-root-id')
919
990
state._validate()
920
991
# 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, '')])
992
old_root_entry = ((b'', b'', b'TREE_ROOT'),
993
[(b'a', b'', 0, False, b''),
994
(b'd', b'', 0, False, b'parent-revid')])
995
new_root_entry = ((b'', b'', b'Asecond-root-id'),
996
[(b'd', b'', 0, False, b''),
997
(b'a', b'', 0, False, b'')])
927
998
expected_rows = [new_root_entry, old_root_entry]
928
999
state._validate()
929
1000
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=''))
1002
new_root_entry, state._get_entry(0, path_utf8=b''))
1004
old_root_entry, state._get_entry(1, path_utf8=b''))
932
1005
self.assertEqual((None, None),
933
state._get_entry(0, fileid_utf8='TREE_ROOT'))
1006
state._get_entry(0, fileid_utf8=b'TREE_ROOT'))
934
1007
self.assertEqual(old_root_entry,
935
state._get_entry(1, fileid_utf8='TREE_ROOT'))
1008
state._get_entry(1, fileid_utf8=b'TREE_ROOT'))
936
1009
self.assertEqual(new_root_entry,
937
state._get_entry(0, fileid_utf8='Asecond-root-id'))
1010
state._get_entry(0, fileid_utf8=b'Asecond-root-id'))
938
1011
self.assertEqual((None, None),
939
state._get_entry(1, fileid_utf8='Asecond-root-id'))
1012
state._get_entry(1, fileid_utf8=b'Asecond-root-id'))
940
1013
# should work across save too
1400
1532
def test_simple_structure(self):
1401
1533
state = self.create_dirstate_with_root_and_subdir()
1402
1534
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)
1535
self.assertBlockRowIndexEqual(
1536
1, 0, True, True, state, b'', b'subdir', 0)
1537
self.assertBlockRowIndexEqual(
1538
1, 0, True, False, state, b'', b'bdir', 0)
1539
self.assertBlockRowIndexEqual(
1540
1, 1, True, False, state, b'', b'zdir', 0)
1541
self.assertBlockRowIndexEqual(
1542
2, 0, False, False, state, b'a', b'foo', 0)
1407
1543
self.assertBlockRowIndexEqual(2, 0, False, False, state,
1544
b'subdir', b'foo', 0)
1410
1546
def test_complex_structure_exists(self):
1411
1547
state = self.create_complex_dirstate()
1412
1548
self.addCleanup(state.unlock)
1413
1549
# 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)
1550
self.assertBlockRowIndexEqual(0, 0, True, True, state, b'', b'', 0)
1551
self.assertBlockRowIndexEqual(1, 0, True, True, state, b'', b'a', 0)
1552
self.assertBlockRowIndexEqual(1, 1, True, True, state, b'', b'b', 0)
1553
self.assertBlockRowIndexEqual(1, 2, True, True, state, b'', b'c', 0)
1554
self.assertBlockRowIndexEqual(1, 3, True, True, state, b'', b'd', 0)
1555
self.assertBlockRowIndexEqual(2, 0, True, True, state, b'a', b'e', 0)
1556
self.assertBlockRowIndexEqual(2, 1, True, True, state, b'a', b'f', 0)
1557
self.assertBlockRowIndexEqual(3, 0, True, True, state, b'b', b'g', 0)
1422
1558
self.assertBlockRowIndexEqual(3, 1, True, True, state,
1423
'b', 'h\xc3\xa5', 0)
1559
b'b', b'h\xc3\xa5', 0)
1425
1561
def test_complex_structure_missing(self):
1426
1562
state = self.create_complex_dirstate()
1427
1563
self.addCleanup(state.unlock)
1428
1564
# Make sure things would be inserted in the right locations
1429
1565
# '_' 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)
1566
self.assertBlockRowIndexEqual(0, 0, True, True, state, b'', b'', 0)
1567
self.assertBlockRowIndexEqual(1, 0, True, False, state, b'', b'_', 0)
1568
self.assertBlockRowIndexEqual(1, 1, True, False, state, b'', b'aa', 0)
1433
1569
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)
1570
b'', b'h\xc3\xa5', 0)
1571
self.assertBlockRowIndexEqual(2, 0, False, False, state, b'_', b'a', 0)
1572
self.assertBlockRowIndexEqual(
1573
3, 0, False, False, state, b'aa', b'a', 0)
1574
self.assertBlockRowIndexEqual(
1575
4, 0, False, False, state, b'bb', b'a', 0)
1438
1576
# This would be inserted between a/ and b/
1439
self.assertBlockRowIndexEqual(3, 0, False, False, state, 'a/e', 'a', 0)
1577
self.assertBlockRowIndexEqual(
1578
3, 0, False, False, state, b'a/e', b'a', 0)
1440
1579
# Put at the end
1441
self.assertBlockRowIndexEqual(4, 0, False, False, state, 'e', 'a', 0)
1580
self.assertBlockRowIndexEqual(4, 0, False, False, state, b'e', b'a', 0)
1444
1583
class TestGetEntry(TestCaseWithDirState):
1455
1594
def test_simple_structure(self):
1456
1595
state = self.create_dirstate_with_root_and_subdir()
1457
1596
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)
1597
self.assertEntryEqual(b'', b'', b'a-root-value', state, b'', 0)
1598
self.assertEntryEqual(
1599
b'', b'subdir', b'subdir-id', state, b'subdir', 0)
1600
self.assertEntryEqual(None, None, None, state, b'missing', 0)
1601
self.assertEntryEqual(None, None, None, state, b'missing/foo', 0)
1602
self.assertEntryEqual(None, None, None, state, b'subdir/foo', 0)
1464
1604
def test_complex_structure_exists(self):
1465
1605
state = self.create_complex_dirstate()
1466
1606
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,
1607
self.assertEntryEqual(b'', b'', b'a-root-value', state, b'', 0)
1608
self.assertEntryEqual(b'', b'a', b'a-dir', state, b'a', 0)
1609
self.assertEntryEqual(b'', b'b', b'b-dir', state, b'b', 0)
1610
self.assertEntryEqual(b'', b'c', b'c-file', state, b'c', 0)
1611
self.assertEntryEqual(b'', b'd', b'd-file', state, b'd', 0)
1612
self.assertEntryEqual(b'a', b'e', b'e-dir', state, b'a/e', 0)
1613
self.assertEntryEqual(b'a', b'f', b'f-file', state, b'a/f', 0)
1614
self.assertEntryEqual(b'b', b'g', b'g-file', state, b'b/g', 0)
1615
self.assertEntryEqual(b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file', state,
1478
1618
def test_complex_structure_missing(self):
1479
1619
state = self.create_complex_dirstate()
1480
1620
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)
1621
self.assertEntryEqual(None, None, None, state, b'_', 0)
1622
self.assertEntryEqual(None, None, None, state, b'_\xc3\xa5', 0)
1623
self.assertEntryEqual(None, None, None, state, b'a/b', 0)
1624
self.assertEntryEqual(None, None, None, state, b'c/d', 0)
1486
1626
def test_get_entry_uninitialized(self):
1487
1627
"""Calling get_entry will load data if it needs to"""
1529
1669
:return: The dirstate, still write-locked.
1531
packed_stat = 'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1532
null_sha = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1671
packed_stat = b'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
1672
null_sha = b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1533
1673
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'),
1674
root_entry = (b'', b'', b'a-root-value'), [
1675
(b'd', b'', 0, False, packed_stat),
1676
(b'd', b'', 0, False, b'parent-revid'),
1678
a_entry = (b'', b'a', b'a-dir'), [
1679
(b'd', b'', 0, False, packed_stat),
1680
(b'd', b'', 0, False, b'parent-revid'),
1682
b_entry = (b'', b'b', b'b-dir'), [
1683
(b'd', b'', 0, False, packed_stat),
1684
(b'd', b'', 0, False, b'parent-revid'),
1686
c_entry = (b'', b'c', b'c-file'), [
1687
(b'f', null_sha, 10, False, packed_stat),
1688
(b'r', b'b/j', 0, False, b''),
1690
d_entry = (b'', b'd', b'd-file'), [
1691
(b'f', null_sha, 20, False, packed_stat),
1692
(b'f', b'd', 20, False, b'parent-revid'),
1694
e_entry = (b'a', b'e', b'e-dir'), [
1695
(b'd', b'', 0, False, packed_stat),
1696
(b'd', b'', 0, False, b'parent-revid'),
1698
f_entry = (b'a', b'f', b'f-file'), [
1699
(b'f', null_sha, 30, False, packed_stat),
1700
(b'f', b'f', 20, False, b'parent-revid'),
1702
g_entry = (b'b', b'g', b'g-file'), [
1703
(b'f', null_sha, 30, False, packed_stat),
1704
NULL_PARENT_DETAILS,
1706
h_entry1 = (b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file1'), [
1707
(b'f', null_sha, 40, False, packed_stat),
1708
NULL_PARENT_DETAILS,
1710
h_entry2 = (b'b', b'h\xc3\xa5', b'h-\xc3\xa5-file2'), [
1711
NULL_PARENT_DETAILS,
1712
(b'f', b'h', 20, False, b'parent-revid'),
1714
i_entry = (b'b', b'i', b'i-file'), [
1715
NULL_PARENT_DETAILS,
1716
(b'f', b'h', 20, False, b'parent-revid'),
1718
j_entry = (b'b', b'j', b'c-file'), [
1719
(b'r', b'c', 0, False, b''),
1720
(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]))
1723
dirblocks.append((b'', [root_entry]))
1724
dirblocks.append((b'', [a_entry, b_entry, c_entry, d_entry]))
1725
dirblocks.append((b'a', [e_entry, f_entry]))
1727
(b'b', [g_entry, h_entry1, h_entry2, i_entry, j_entry]))
1587
1728
state = dirstate.DirState.initialize('dirstate')
1588
1729
state._validate()
1590
state._set_data(['parent'], dirblocks)
1731
state._set_data([b'parent'], dirblocks)
1874
2017
tree, state, expected = self.create_basic_dirstate()
1876
2019
# 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'])
2020
self.assertBisect(expected, [[b'']], state, [b''])
2021
self.assertBisect(expected, [[b'a']], state, [b'a'])
2022
self.assertBisect(expected, [[b'b']], state, [b'b'])
2023
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2024
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2025
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2026
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2027
self.assertBisect(expected, [[b'f']], state, [b'f'])
1886
2029
def test_bisect_multi(self):
1887
2030
"""Bisect can be used to find multiple records at the same time."""
1888
2031
tree, state, expected = self.create_basic_dirstate()
1889
2032
# 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'])
2033
self.assertBisect(expected, [[b'a'], [b'b'], [b'f']],
2034
state, [b'a', b'b', b'f'])
2035
self.assertBisect(expected, [[b'f'], [b'b/d'], [b'b/d/e']],
2036
state, [b'f', b'b/d', b'b/d/e'])
2037
self.assertBisect(expected, [[b'b'], [b'b-c'], [b'b/c']],
2038
state, [b'b', b'b-c', b'b/c'])
1897
2040
def test_bisect_one_page(self):
1898
2041
"""Test bisect when there is only 1 page to read"""
1899
2042
tree, state, expected = self.create_basic_dirstate()
1900
2043
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'])
2044
self.assertBisect(expected, [[b'']], state, [b''])
2045
self.assertBisect(expected, [[b'a']], state, [b'a'])
2046
self.assertBisect(expected, [[b'b']], state, [b'b'])
2047
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2048
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2049
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2050
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2051
self.assertBisect(expected, [[b'f']], state, [b'f'])
2052
self.assertBisect(expected, [[b'a'], [b'b'], [b'f']],
2053
state, [b'a', b'b', b'f'])
2054
self.assertBisect(expected, [[b'b/d'], [b'b/d/e'], [b'f']],
2055
state, [b'b/d', b'b/d/e', b'f'])
2056
self.assertBisect(expected, [[b'b'], [b'b/c'], [b'b-c']],
2057
state, [b'b', b'b/c', b'b-c'])
1916
2059
def test_bisect_duplicate_paths(self):
1917
2060
"""When bisecting for a path, handle multiple entries."""
1918
2061
tree, state, expected = self.create_duplicated_dirstate()
1920
2063
# 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'])
2064
self.assertBisect(expected, [[b'']], state, [b''])
2065
self.assertBisect(expected, [[b'a', b'a2']], state, [b'a'])
2066
self.assertBisect(expected, [[b'b', b'b2']], state, [b'b'])
2067
self.assertBisect(expected, [[b'b/c', b'b/c2']], state, [b'b/c'])
2068
self.assertBisect(expected, [[b'b/d', b'b/d2']], state, [b'b/d'])
2069
self.assertBisect(expected, [[b'b/d/e', b'b/d/e2']],
2071
self.assertBisect(expected, [[b'b-c', b'b-c2']], state, [b'b-c'])
2072
self.assertBisect(expected, [[b'f', b'f2']], state, [b'f'])
1931
2074
def test_bisect_page_size_too_small(self):
1932
2075
"""If the page size is too small, we will auto increase it."""
1933
2076
tree, state, expected = self.create_basic_dirstate()
1934
2077
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'])
2078
self.assertBisect(expected, [None], state, [b'b/e'])
2079
self.assertBisect(expected, [[b'a']], state, [b'a'])
2080
self.assertBisect(expected, [[b'b']], state, [b'b'])
2081
self.assertBisect(expected, [[b'b/c']], state, [b'b/c'])
2082
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2083
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2084
self.assertBisect(expected, [[b'b-c']], state, [b'b-c'])
2085
self.assertBisect(expected, [[b'f']], state, [b'f'])
1944
2087
def test_bisect_missing(self):
1945
2088
"""Test that bisect return None if it cannot find a path."""
1946
2089
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'])
2090
self.assertBisect(expected, [None], state, [b'foo'])
2091
self.assertBisect(expected, [None], state, [b'b/foo'])
2092
self.assertBisect(expected, [None], state, [b'bar/foo'])
2093
self.assertBisect(expected, [None], state, [b'b-c/foo'])
1952
self.assertBisect(expected, [['a'], None, ['b/d']],
1953
state, ['a', 'foo', 'b/d'])
2095
self.assertBisect(expected, [[b'a'], None, [b'b/d']],
2096
state, [b'a', b'foo', b'b/d'])
1955
2098
def test_bisect_rename(self):
1956
2099
"""Check that we find a renamed row."""
1957
2100
tree, state, expected = self.create_renamed_dirstate()
1959
2102
# 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'])
2103
self.assertBisect(expected, [[b'a']], state, [b'a'])
2104
self.assertBisect(expected, [[b'b/g']], state, [b'b/g'])
2105
self.assertBisect(expected, [[b'b/d']], state, [b'b/d'])
2106
self.assertBisect(expected, [[b'h']], state, [b'h'])
1965
2108
# 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'])
2109
self.assertBisect(expected, [[b'b/d/e']], state, [b'b/d/e'])
2110
self.assertBisect(expected, [[b'h/e']], state, [b'h/e'])
1969
2112
def test_bisect_dirblocks(self):
1970
2113
tree, state, expected = self.create_duplicated_dirstate()
1971
2114
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'])
2115
[[b'', b'a', b'a2', b'b', b'b2',
2116
b'b-c', b'b-c2', b'f', b'f2']],
2118
self.assertBisectDirBlocks(expected,
2119
[[b'b/c', b'b/c2', b'b/d', b'b/d2']], state, [b'b'])
2120
self.assertBisectDirBlocks(expected,
2121
[[b'b/d/e', b'b/d/e2']], state, [b'b/d'])
2122
self.assertBisectDirBlocks(expected,
2123
[[b'', b'a', b'a2', b'b', b'b2', b'b-c', b'b-c2', b'f', b'f2'],
2124
[b'b/c', b'b/c2', b'b/d', b'b/d2'],
2125
[b'b/d/e', b'b/d/e2'],
2126
], state, [b'', b'b', b'b/d'])
1984
2128
def test_bisect_dirblocks_missing(self):
1985
2129
tree, state, expected = self.create_basic_dirstate()
1986
self.assertBisectDirBlocks(expected, [['b/d/e'], None],
1987
state, ['b/d', 'b/e'])
2130
self.assertBisectDirBlocks(expected, [[b'b/d/e'], None],
2131
state, [b'b/d', b'b/e'])
1988
2132
# 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'])
2133
self.assertBisectDirBlocks(expected, [None], state, [b'a'])
2134
self.assertBisectDirBlocks(expected, [None], state, [b'b/c'])
2135
self.assertBisectDirBlocks(expected, [None], state, [b'c'])
2136
self.assertBisectDirBlocks(expected, [None], state, [b'b/d/e'])
2137
self.assertBisectDirBlocks(expected, [None], state, [b'f'])
1995
2139
def test_bisect_recursive_each(self):
1996
2140
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',
2141
self.assertBisectRecursive(expected, [b'a'], state, [b'a'])
2142
self.assertBisectRecursive(expected, [b'b/c'], state, [b'b/c'])
2143
self.assertBisectRecursive(expected, [b'b/d/e'], state, [b'b/d/e'])
2144
self.assertBisectRecursive(expected, [b'b-c'], state, [b'b-c'])
2145
self.assertBisectRecursive(expected, [b'b/d', b'b/d/e'],
2147
self.assertBisectRecursive(expected, [b'b', b'b/c', b'b/d', b'b/d/e'],
2149
self.assertBisectRecursive(expected, [b'', b'a', b'b', b'b-c', b'f', b'b/c',
2009
2153
def test_bisect_recursive_multiple(self):
2010
2154
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'])
2155
self.assertBisectRecursive(
2156
expected, [b'a', b'b/c'], state, [b'a', b'b/c'])
2157
self.assertBisectRecursive(expected, [b'b/d', b'b/d/e'],
2158
state, [b'b/d', b'b/d/e'])
2015
2160
def test_bisect_recursive_missing(self):
2016
2161
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'])
2162
self.assertBisectRecursive(expected, [], state, [b'd'])
2163
self.assertBisectRecursive(expected, [], state, [b'b/e'])
2164
self.assertBisectRecursive(expected, [], state, [b'g'])
2165
self.assertBisectRecursive(expected, [b'a'], state, [b'a', b'g'])
2022
2167
def test_bisect_recursive_renamed(self):
2023
2168
tree, state, expected = self.create_renamed_dirstate()
2025
2170
# 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'])
2171
self.assertBisectRecursive(expected, [b'a', b'b/g'], state, [b'a'])
2172
self.assertBisectRecursive(expected, [b'a', b'b/g'], state, [b'b/g'])
2028
2173
# Looking in the containing directory should find the rename target,
2029
2174
# 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'],
2175
self.assertBisectRecursive(expected, [b'a', b'b', b'b/c', b'b/d',
2176
b'b/d/e', b'b/g', b'h', b'h/e'],
2035
2180
class TestDirstateValidation(TestCaseWithDirState):
2141
2286
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),
2288
packed_stat = b'AAAAREUHaIpFB2iKAAADAQAtkqUAAIGk'
2289
root_entry_direntry = (b'', b'', b'a-root-value'), [
2290
(b'd', b'', 0, False, packed_stat),
2291
(b'd', b'', 0, False, packed_stat),
2292
(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),
2294
expected_root_entry_direntry = (b'', b'', b'a-root-value'), [
2295
(b'd', b'', 0, False, packed_stat),
2296
(b'd', b'', 0, False, packed_stat),
2154
dirblocks.append(('', [root_entry_direntry]))
2155
dirblocks.append(('', []))
2299
dirblocks.append((b'', [root_entry_direntry]))
2300
dirblocks.append((b'', []))
2157
2302
state = self.create_empty_dirstate()
2158
2303
self.addCleanup(state.unlock)
2159
state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2304
state._set_data([b'parent-id', b'merged-id'], dirblocks[:])
2160
2305
state._validate()
2162
2307
# This should strip of the extra column
2163
2308
state._discard_merge_parents()
2164
2309
state._validate()
2165
expected_dirblocks = [('', [expected_root_entry_direntry]), ('', [])]
2310
expected_dirblocks = [(b'', [expected_root_entry_direntry]), (b'', [])]
2166
2311
self.assertEqual(expected_dirblocks, state._dirblocks)
2168
2313
def test_discard_absent(self):
2169
2314
"""If entries are only in a merge, discard should remove the entries"""
2170
2315
null_stat = dirstate.DirState.NULLSTAT
2171
present_dir = ('d', '', 0, False, null_stat)
2172
present_file = ('f', '', 0, False, null_stat)
2316
present_dir = (b'd', b'', 0, False, null_stat)
2317
present_file = (b'f', b'', 0, False, null_stat)
2173
2318
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,
2179
[absent, absent, present_file]),
2181
[present_file, present_file, present_file]),
2319
root_key = (b'', b'', b'a-root-value')
2320
file_in_root_key = (b'', b'file-in-root', b'a-file-id')
2321
file_in_merged_key = (b'', b'file-in-merged', b'b-file-id')
2322
dirblocks = [(b'', [(root_key, [present_dir, present_dir, present_dir])]),
2323
(b'', [(file_in_merged_key,
2324
[absent, absent, present_file]),
2326
[present_file, present_file, present_file]),
2185
2330
state = self.create_empty_dirstate()
2186
2331
self.addCleanup(state.unlock)
2187
state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2332
state._set_data([b'parent-id', b'merged-id'], dirblocks[:])
2188
2333
state._validate()
2190
exp_dirblocks = [('', [(root_key, [present_dir, present_dir])]),
2191
('', [(file_in_root_key,
2192
[present_file, present_file]),
2335
exp_dirblocks = [(b'', [(root_key, [present_dir, present_dir])]),
2336
(b'', [(file_in_root_key,
2337
[present_file, present_file]),
2195
2340
state._discard_merge_parents()
2196
2341
state._validate()
2197
2342
self.assertEqual(exp_dirblocks, state._dirblocks)
2199
2344
def test_discard_renamed(self):
2200
2345
null_stat = dirstate.DirState.NULLSTAT
2201
present_dir = ('d', '', 0, False, null_stat)
2202
present_file = ('f', '', 0, False, null_stat)
2346
present_dir = (b'd', b'', 0, False, null_stat)
2347
present_file = (b'f', b'', 0, False, null_stat)
2203
2348
absent = dirstate.DirState.NULL_PARENT_DETAILS
2204
root_key = ('', '', 'a-root-value')
2205
file_in_root_key = ('', 'file-in-root', 'a-file-id')
2349
root_key = (b'', b'', b'a-root-value')
2350
file_in_root_key = (b'', b'file-in-root', b'a-file-id')
2206
2351
# Renamed relative to parent
2207
file_rename_s_key = ('', 'file-s', 'b-file-id')
2208
file_rename_t_key = ('', 'file-t', 'b-file-id')
2352
file_rename_s_key = (b'', b'file-s', b'b-file-id')
2353
file_rename_t_key = (b'', b'file-t', b'b-file-id')
2209
2354
# And one that is renamed between the parents, but absent in this
2210
key_in_1 = ('', 'file-in-1', 'c-file-id')
2211
key_in_2 = ('', 'file-in-2', 'c-file-id')
2355
key_in_1 = (b'', b'file-in-1', b'c-file-id')
2356
key_in_2 = (b'', b'file-in-2', b'c-file-id')
2214
('', [(root_key, [present_dir, present_dir, present_dir])]),
2216
[absent, present_file, ('r', 'file-in-2', 'c-file-id')]),
2218
[absent, ('r', 'file-in-1', 'c-file-id'), present_file]),
2220
[present_file, present_file, present_file]),
2222
[('r', 'file-t', 'b-file-id'), absent, present_file]),
2224
[present_file, absent, ('r', 'file-s', 'b-file-id')]),
2359
(b'', [(root_key, [present_dir, present_dir, present_dir])]),
2361
[absent, present_file, (b'r', b'file-in-2', b'c-file-id')]),
2363
[absent, (b'r', b'file-in-1', b'c-file-id'), present_file]),
2365
[present_file, present_file, present_file]),
2367
[(b'r', b'file-t', b'b-file-id'), absent, present_file]),
2369
[present_file, absent, (b'r', b'file-s', b'b-file-id')]),
2227
2372
exp_dirblocks = [
2228
('', [(root_key, [present_dir, present_dir])]),
2229
('', [(key_in_1, [absent, present_file]),
2230
(file_in_root_key, [present_file, present_file]),
2231
(file_rename_t_key, [present_file, absent]),
2373
(b'', [(root_key, [present_dir, present_dir])]),
2374
(b'', [(key_in_1, [absent, present_file]),
2375
(file_in_root_key, [present_file, present_file]),
2376
(file_rename_t_key, [present_file, absent]),
2234
2379
state = self.create_empty_dirstate()
2235
2380
self.addCleanup(state.unlock)
2236
state._set_data(['parent-id', 'merged-id'], dirblocks[:])
2381
state._set_data([b'parent-id', b'merged-id'], dirblocks[:])
2237
2382
state._validate()
2239
2384
state._discard_merge_parents()
2320
2465
self.assertTrue(len(statvalue) >= 10)
2321
2466
self.assertEqual(len(text), statvalue.st_size)
2322
2467
self.assertEqual(expected_sha, sha1)
2470
class _Repo(object):
2471
"""A minimal api to get InventoryRevisionTree to work."""
2474
default_format = controldir.format_registry.make_controldir('default')
2475
self._format = default_format.repository_format
2477
def lock_read(self):
2484
class TestUpdateBasisByDelta(tests.TestCase):
2486
def path_to_ie(self, path, file_id, rev_id, dir_ids):
2487
if path.endswith('/'):
2492
dirname, basename = osutils.split(path)
2494
dir_id = dir_ids[dirname]
2496
dir_id = osutils.basename(dirname).encode('utf-8') + b'-id'
2498
ie = inventory.InventoryDirectory(file_id, basename, dir_id)
2499
dir_ids[path] = file_id
2501
ie = inventory.InventoryFile(file_id, basename, dir_id)
2504
ie.revision = rev_id
2507
def create_tree_from_shape(self, rev_id, shape):
2508
dir_ids = {'': b'root-id'}
2509
inv = inventory.Inventory(b'root-id', rev_id)
2512
path, file_id = info
2515
path, file_id, ie_rev_id = info
2517
# Replace the root entry
2518
del inv._byid[inv.root.file_id]
2519
inv.root.file_id = file_id
2520
inv._byid[file_id] = inv.root
2521
dir_ids[''] = file_id
2523
inv.add(self.path_to_ie(path, file_id, ie_rev_id, dir_ids))
2524
return inventorytree.InventoryRevisionTree(_Repo(), inv, rev_id)
2526
def create_empty_dirstate(self):
2527
fd, path = tempfile.mkstemp(prefix='bzr-dirstate')
2528
self.addCleanup(os.remove, path)
2530
state = dirstate.DirState.initialize(path)
2531
self.addCleanup(state.unlock)
2534
def create_inv_delta(self, delta, rev_id):
2535
"""Translate a 'delta shape' into an actual InventoryDelta"""
2536
dir_ids = {'': b'root-id'}
2538
for old_path, new_path, file_id in delta:
2539
if old_path is not None and old_path.endswith('/'):
2540
# Don't have to actually do anything for this, because only
2541
# new_path creates InventoryEntries
2542
old_path = old_path[:-1]
2543
if new_path is None: # Delete
2544
inv_delta.append((old_path, None, file_id, None))
2546
ie = self.path_to_ie(new_path, file_id, rev_id, dir_ids)
2547
inv_delta.append((old_path, new_path, file_id, ie))
2550
def assertUpdate(self, active, basis, target):
2551
"""Assert that update_basis_by_delta works how we want.
2553
Set up a DirState object with active_shape for tree 0, basis_shape for
2554
tree 1. Then apply the delta from basis_shape to target_shape,
2555
and assert that the DirState is still valid, and that its stored
2556
content matches the target_shape.
2558
active_tree = self.create_tree_from_shape(b'active', active)
2559
basis_tree = self.create_tree_from_shape(b'basis', basis)
2560
target_tree = self.create_tree_from_shape(b'target', target)
2561
state = self.create_empty_dirstate()
2562
state.set_state_from_scratch(active_tree.root_inventory,
2563
[(b'basis', basis_tree)], [])
2564
delta = target_tree.root_inventory._make_delta(
2565
basis_tree.root_inventory)
2566
state.update_basis_by_delta(delta, b'target')
2568
dirstate_tree = workingtree_4.DirStateRevisionTree(state,
2570
# The target now that delta has been applied should match the
2572
self.assertEqual([], list(dirstate_tree.iter_changes(target_tree)))
2573
# And the dirblock state should be identical to the state if we created
2575
state2 = self.create_empty_dirstate()
2576
state2.set_state_from_scratch(active_tree.root_inventory,
2577
[(b'target', target_tree)], [])
2578
self.assertEqual(state2._dirblocks, state._dirblocks)
2581
def assertBadDelta(self, active, basis, delta):
2582
"""Test that we raise InconsistentDelta when appropriate.
2584
:param active: The active tree shape
2585
:param basis: The basis tree shape
2586
:param delta: A description of the delta to apply. Similar to the form
2587
for regular inventory deltas, but omitting the InventoryEntry.
2588
So adding a file is: (None, 'path', b'file-id')
2589
Adding a directory is: (None, 'path/', b'dir-id')
2590
Renaming a dir is: ('old/', 'new/', b'dir-id')
2593
active_tree = self.create_tree_from_shape(b'active', active)
2594
basis_tree = self.create_tree_from_shape(b'basis', basis)
2595
inv_delta = self.create_inv_delta(delta, b'target')
2596
state = self.create_empty_dirstate()
2597
state.set_state_from_scratch(active_tree.root_inventory,
2598
[(b'basis', basis_tree)], [])
2599
self.assertRaises(errors.InconsistentDelta,
2600
state.update_basis_by_delta, inv_delta, b'target')
2602
## state.update_basis_by_delta(inv_delta, b'target')
2603
# except errors.InconsistentDelta, e:
2604
## import pdb; pdb.set_trace()
2606
## import pdb; pdb.set_trace()
2607
self.assertTrue(state._changes_aborted)
2609
def test_remove_file_matching_active_state(self):
2610
state = self.assertUpdate(
2612
basis=[('file', b'file-id')],
2616
def test_remove_file_present_in_active_state(self):
2617
state = self.assertUpdate(
2618
active=[('file', b'file-id')],
2619
basis=[('file', b'file-id')],
2623
def test_remove_file_present_elsewhere_in_active_state(self):
2624
state = self.assertUpdate(
2625
active=[('other-file', b'file-id')],
2626
basis=[('file', b'file-id')],
2630
def test_remove_file_active_state_has_diff_file(self):
2631
state = self.assertUpdate(
2632
active=[('file', b'file-id-2')],
2633
basis=[('file', b'file-id')],
2637
def test_remove_file_active_state_has_diff_file_and_file_elsewhere(self):
2638
state = self.assertUpdate(
2639
active=[('file', b'file-id-2'),
2640
('other-file', b'file-id')],
2641
basis=[('file', b'file-id')],
2645
def test_add_file_matching_active_state(self):
2646
state = self.assertUpdate(
2647
active=[('file', b'file-id')],
2649
target=[('file', b'file-id')],
2652
def test_add_file_in_empty_dir_not_matching_active_state(self):
2653
state = self.assertUpdate(
2655
basis=[('dir/', b'dir-id')],
2656
target=[('dir/', b'dir-id', b'basis'), ('dir/file', b'file-id')],
2659
def test_add_file_missing_in_active_state(self):
2660
state = self.assertUpdate(
2663
target=[('file', b'file-id')],
2666
def test_add_file_elsewhere_in_active_state(self):
2667
state = self.assertUpdate(
2668
active=[('other-file', b'file-id')],
2670
target=[('file', b'file-id')],
2673
def test_add_file_active_state_has_diff_file_and_file_elsewhere(self):
2674
state = self.assertUpdate(
2675
active=[('other-file', b'file-id'),
2676
('file', b'file-id-2')],
2678
target=[('file', b'file-id')],
2681
def test_rename_file_matching_active_state(self):
2682
state = self.assertUpdate(
2683
active=[('other-file', b'file-id')],
2684
basis=[('file', b'file-id')],
2685
target=[('other-file', b'file-id')],
2688
def test_rename_file_missing_in_active_state(self):
2689
state = self.assertUpdate(
2691
basis=[('file', b'file-id')],
2692
target=[('other-file', b'file-id')],
2695
def test_rename_file_present_elsewhere_in_active_state(self):
2696
state = self.assertUpdate(
2697
active=[('third', b'file-id')],
2698
basis=[('file', b'file-id')],
2699
target=[('other-file', b'file-id')],
2702
def test_rename_file_active_state_has_diff_source_file(self):
2703
state = self.assertUpdate(
2704
active=[('file', b'file-id-2')],
2705
basis=[('file', b'file-id')],
2706
target=[('other-file', b'file-id')],
2709
def test_rename_file_active_state_has_diff_target_file(self):
2710
state = self.assertUpdate(
2711
active=[('other-file', b'file-id-2')],
2712
basis=[('file', b'file-id')],
2713
target=[('other-file', b'file-id')],
2716
def test_rename_file_active_has_swapped_files(self):
2717
state = self.assertUpdate(
2718
active=[('file', b'file-id'),
2719
('other-file', b'file-id-2')],
2720
basis=[('file', b'file-id'),
2721
('other-file', b'file-id-2')],
2722
target=[('file', b'file-id-2'),
2723
('other-file', b'file-id')])
2725
def test_rename_file_basis_has_swapped_files(self):
2726
state = self.assertUpdate(
2727
active=[('file', b'file-id'),
2728
('other-file', b'file-id-2')],
2729
basis=[('file', b'file-id-2'),
2730
('other-file', b'file-id')],
2731
target=[('file', b'file-id'),
2732
('other-file', b'file-id-2')])
2734
def test_rename_directory_with_contents(self):
2735
state = self.assertUpdate( # active matches basis
2736
active=[('dir1/', b'dir-id'),
2737
('dir1/file', b'file-id')],
2738
basis=[('dir1/', b'dir-id'),
2739
('dir1/file', b'file-id')],
2740
target=[('dir2/', b'dir-id'),
2741
('dir2/file', b'file-id')])
2742
state = self.assertUpdate( # active matches target
2743
active=[('dir2/', b'dir-id'),
2744
('dir2/file', b'file-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')])
2749
state = self.assertUpdate( # active empty
2751
basis=[('dir1/', b'dir-id'),
2752
('dir1/file', b'file-id')],
2753
target=[('dir2/', b'dir-id'),
2754
('dir2/file', b'file-id')])
2755
state = self.assertUpdate( # active present at other location
2756
active=[('dir3/', b'dir-id'),
2757
('dir3/file', b'file-id')],
2758
basis=[('dir1/', b'dir-id'),
2759
('dir1/file', b'file-id')],
2760
target=[('dir2/', b'dir-id'),
2761
('dir2/file', b'file-id')])
2762
state = self.assertUpdate( # active has different ids
2763
active=[('dir1/', b'dir1-id'),
2764
('dir1/file', b'file1-id'),
2765
('dir2/', b'dir2-id'),
2766
('dir2/file', b'file2-id')],
2767
basis=[('dir1/', b'dir-id'),
2768
('dir1/file', b'file-id')],
2769
target=[('dir2/', b'dir-id'),
2770
('dir2/file', b'file-id')])
2772
def test_invalid_file_not_present(self):
2773
state = self.assertBadDelta(
2774
active=[('file', b'file-id')],
2775
basis=[('file', b'file-id')],
2776
delta=[('other-file', 'file', b'file-id')])
2778
def test_invalid_new_id_same_path(self):
2779
# The bad entry comes after
2780
state = self.assertBadDelta(
2781
active=[('file', b'file-id')],
2782
basis=[('file', b'file-id')],
2783
delta=[(None, 'file', b'file-id-2')])
2784
# The bad entry comes first
2785
state = self.assertBadDelta(
2786
active=[('file', b'file-id-2')],
2787
basis=[('file', b'file-id-2')],
2788
delta=[(None, 'file', b'file-id')])
2790
def test_invalid_existing_id(self):
2791
state = self.assertBadDelta(
2792
active=[('file', b'file-id')],
2793
basis=[('file', b'file-id')],
2794
delta=[(None, 'file', b'file-id')])
2796
def test_invalid_parent_missing(self):
2797
state = self.assertBadDelta(
2800
delta=[(None, 'path/path2', b'file-id')])
2801
# Note: we force the active tree to have the directory, by knowing how
2802
# path_to_ie handles entries with missing parents
2803
state = self.assertBadDelta(
2804
active=[('path/', b'path-id')],
2806
delta=[(None, 'path/path2', b'file-id')])
2807
state = self.assertBadDelta(
2808
active=[('path/', b'path-id'),
2809
('path/path2', b'file-id')],
2811
delta=[(None, 'path/path2', b'file-id')])
2813
def test_renamed_dir_same_path(self):
2814
# We replace the parent directory, with another parent dir. But the C
2815
# file doesn't look like it has been moved.
2816
state = self.assertUpdate( # Same as basis
2817
active=[('dir/', b'A-id'),
2818
('dir/B', b'B-id')],
2819
basis=[('dir/', b'A-id'),
2820
('dir/B', b'B-id')],
2821
target=[('dir/', b'C-id'),
2822
('dir/B', b'B-id')])
2823
state = self.assertUpdate( # Same as target
2824
active=[('dir/', b'C-id'),
2825
('dir/B', b'B-id')],
2826
basis=[('dir/', b'A-id'),
2827
('dir/B', b'B-id')],
2828
target=[('dir/', b'C-id'),
2829
('dir/B', b'B-id')])
2830
state = self.assertUpdate( # empty active
2832
basis=[('dir/', b'A-id'),
2833
('dir/B', b'B-id')],
2834
target=[('dir/', b'C-id'),
2835
('dir/B', b'B-id')])
2836
state = self.assertUpdate( # different active
2837
active=[('dir/', b'D-id'),
2838
('dir/B', b'B-id')],
2839
basis=[('dir/', b'A-id'),
2840
('dir/B', b'B-id')],
2841
target=[('dir/', b'C-id'),
2842
('dir/B', b'B-id')])
2844
def test_parent_child_swap(self):
2845
state = self.assertUpdate( # Same as basis
2846
active=[('A/', b'A-id'),
2848
('A/B/C', b'C-id')],
2849
basis=[('A/', b'A-id'),
2851
('A/B/C', b'C-id')],
2852
target=[('A/', b'B-id'),
2854
('A/B/C', b'C-id')])
2855
state = self.assertUpdate( # Same as target
2856
active=[('A/', b'B-id'),
2858
('A/B/C', b'C-id')],
2859
basis=[('A/', b'A-id'),
2861
('A/B/C', b'C-id')],
2862
target=[('A/', b'B-id'),
2864
('A/B/C', b'C-id')])
2865
state = self.assertUpdate( # empty active
2867
basis=[('A/', b'A-id'),
2869
('A/B/C', b'C-id')],
2870
target=[('A/', b'B-id'),
2872
('A/B/C', b'C-id')])
2873
state = self.assertUpdate( # different active
2874
active=[('D/', b'A-id'),
2877
basis=[('A/', b'A-id'),
2879
('A/B/C', b'C-id')],
2880
target=[('A/', b'B-id'),
2882
('A/B/C', b'C-id')])
2884
def test_change_root_id(self):
2885
state = self.assertUpdate( # same as basis
2886
active=[('', b'root-id'),
2887
('file', b'file-id')],
2888
basis=[('', b'root-id'),
2889
('file', b'file-id')],
2890
target=[('', b'target-root-id'),
2891
('file', b'file-id')])
2892
state = self.assertUpdate( # same as target
2893
active=[('', b'target-root-id'),
2894
('file', b'file-id')],
2895
basis=[('', b'root-id'),
2896
('file', b'file-id')],
2897
target=[('', b'target-root-id'),
2898
('file', b'root-id')])
2899
state = self.assertUpdate( # all different
2900
active=[('', b'active-root-id'),
2901
('file', b'file-id')],
2902
basis=[('', b'root-id'),
2903
('file', b'file-id')],
2904
target=[('', b'target-root-id'),
2905
('file', b'root-id')])
2907
def test_change_file_absent_in_active(self):
2908
state = self.assertUpdate(
2910
basis=[('file', b'file-id')],
2911
target=[('file', b'file-id')])
2913
def test_invalid_changed_file(self):
2914
state = self.assertBadDelta( # Not present in basis
2915
active=[('file', b'file-id')],
2917
delta=[('file', 'file', b'file-id')])
2918
state = self.assertBadDelta( # present at another location in basis
2919
active=[('file', b'file-id')],
2920
basis=[('other-file', b'file-id')],
2921
delta=[('file', 'file', b'file-id')])