phases: directly update the phase sets in advanceboundary
This is similar to what we do in retractboundary. There is no need to invalidate
the cache if we have everything at hand to update it.
import struct
import unittest
from mercurial.node import hex
try:
from mercurial import rustext
rustext.__name__ # trigger immediate actual import
except ImportError:
rustext = None
else:
from mercurial.rustext import revlog
# this would fail already without appropriate ancestor.__package__
from mercurial.rustext.ancestor import LazyAncestors
from mercurial.testing import revlog as revlogtesting
header = struct.unpack(">I", revlogtesting.data_non_inlined[:4])[0]
@unittest.skipIf(
rustext is None,
"rustext module revlog relies on is not available",
)
class RustRevlogIndexTest(revlogtesting.RevlogBasedTestBase):
def test_heads(self):
idx = self.parseindex()
rustidx = revlog.Index(revlogtesting.data_non_inlined, header)
self.assertEqual(rustidx.headrevs(), idx.headrevs())
def test_len(self):
idx = self.parseindex()
rustidx = revlog.Index(revlogtesting.data_non_inlined, header)
self.assertEqual(len(rustidx), len(idx))
def test_ancestors(self):
rustidx = revlog.Index(revlogtesting.data_non_inlined, header)
lazy = LazyAncestors(rustidx, [3], 0, True)
# we have two more references to the index:
# - in its inner iterator for __contains__ and __bool__
# - in the LazyAncestors instance itself (to spawn new iterators)
self.assertTrue(2 in lazy)
self.assertTrue(bool(lazy))
self.assertEqual(list(lazy), [3, 2, 1, 0])
# a second time to validate that we spawn new iterators
self.assertEqual(list(lazy), [3, 2, 1, 0])
# let's check bool for an empty one
self.assertFalse(LazyAncestors(rustidx, [0], 0, False))
@unittest.skipIf(
rustext is None,
"rustext module revlog relies on is not available",
)
class RustRevlogNodeTreeClassTest(revlogtesting.RustRevlogBasedTestBase):
def test_standalone_nodetree(self):
idx = self.parserustindex()
nt = revlog.NodeTree(idx)
for i in range(4):
nt.insert(i)
bin_nodes = [entry[7] for entry in idx]
hex_nodes = [hex(n) for n in bin_nodes]
for i, node in enumerate(hex_nodes):
self.assertEqual(nt.prefix_rev_lookup(node), i)
self.assertEqual(nt.prefix_rev_lookup(node[:5]), i)
# all 4 revisions in idx (standard data set) have different
# first nybbles in their Node IDs,
# hence `nt.shortest()` should return 1 for them, except when
# the leading nybble is 0 (ambiguity with NULL_NODE)
for i, (bin_node, hex_node) in enumerate(zip(bin_nodes, hex_nodes)):
shortest = nt.shortest(bin_node)
expected = 2 if hex_node[0] == ord('0') else 1
self.assertEqual(shortest, expected)
self.assertEqual(nt.prefix_rev_lookup(hex_node[:shortest]), i)
# test invalidation (generation poisoning) detection
del idx[3]
self.assertTrue(nt.is_invalidated())
if __name__ == '__main__':
import silenttestrunner
silenttestrunner.main(__name__)