comparison mercurial/testing/storage.py @ 40054:801ccd8e67c0

revlog: clear revision cache on hash verification failure The revision cache is populated after raw revision fulltext is retrieved but before hash verification. If hash verification fails, the revision cache will be populated and subsequent operations to retrieve the invalid fulltext may return the cached fulltext instead of raising. This commit changes hash verification so it will invalidate the revision cache if the cached node fails hash verification. The side-effect is that subsequent operations to request the revision text - even the raw revision text - will always fail. The new behavior is consistent and is definitely less wrong. There is an open question of whether revision(raw=True) should validate hashes. But I'm going to punt on this problem. We can always change behavior later. And to be honest, I'm not sure we should expose raw=True on the storage interface at all. Another day... Differential Revision: https://phab.mercurial-scm.org/D4867
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 03 Oct 2018 10:57:35 -0700
parents cdf61ab1f54c
children 324b4b10351e
comparison
equal deleted inserted replaced
40053:8c692a6b5ad1 40054:801ccd8e67c0
879 879
880 # revision() raises since it performs hash verification. 880 # revision() raises since it performs hash verification.
881 with self.assertRaises(error.StorageError): 881 with self.assertRaises(error.StorageError):
882 f.revision(node1) 882 f.revision(node1)
883 883
884 # revision(raw=True) still verifies hashes. 884 # raw=True still verifies because there are no special storage
885 # TODO this is buggy because of cache interaction. 885 # settings.
886 self.assertEqual(f.revision(node1, raw=True), fulltext1) 886 with self.assertRaises(error.StorageError):
887 f.revision(node1, raw=True)
887 888
888 # read() behaves like revision(). 889 # read() behaves like revision().
889 # TODO this is buggy because of cache interaction. 890 with self.assertRaises(error.StorageError):
890 f.read(node1) 891 f.read(node1)
891 892
892 # We can't test renamed() here because some backends may not require 893 # We can't test renamed() here because some backends may not require
893 # reading/validating the fulltext to return rename metadata. 894 # reading/validating the fulltext to return rename metadata.
894 895
895 def testbadnoderevisionraw(self): 896 def testbadnoderevisionraw(self):
929 rawtext=fulltext1) 930 rawtext=fulltext1)
930 931
931 with self.assertRaises(error.StorageError): 932 with self.assertRaises(error.StorageError):
932 f.read(node1) 933 f.read(node1)
933 934
934 # TODO this should raise error.StorageError. 935 with self.assertRaises(error.StorageError):
935 f.read(node1) 936 f.read(node1)
936 937
937 def testbadnodedelta(self): 938 def testbadnodedelta(self):
938 f = self._makefilefn() 939 f = self._makefilefn()
939 940
940 fulltext0 = b'foo\n' * 31 941 fulltext0 = b'foo\n' * 31
984 self.assertTrue(f.iscensored(1)) 985 self.assertTrue(f.iscensored(1))
985 986
986 with self.assertRaises(error.CensoredNodeError): 987 with self.assertRaises(error.CensoredNodeError):
987 f.revision(1) 988 f.revision(1)
988 989
989 self.assertEqual(f.revision(1, raw=True), stored1) 990 with self.assertRaises(error.CensoredNodeError):
991 f.revision(1, raw=True)
990 992
991 with self.assertRaises(error.CensoredNodeError): 993 with self.assertRaises(error.CensoredNodeError):
992 f.read(1) 994 f.read(1)
993 995
994 def testcensoredrawrevision(self): 996 def testcensoredrawrevision(self):