##// END OF EJS Templates
storageutil: new module for storage primitives (API)...
Gregory Szorc -
r39913:f8eb71f9 default
parent child Browse files
Show More
@@ -0,0 +1,41
1 # storageutil.py - Storage functionality agnostic of backend implementation.
2 #
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7
8 from __future__ import absolute_import
9
10 import hashlib
11
12 from ..node import (
13 nullid,
14 )
15
16 _nullhash = hashlib.sha1(nullid)
17
18 def hashrevisionsha1(text, p1, p2):
19 """Compute the SHA-1 for revision data and its parents.
20
21 This hash combines both the current file contents and its history
22 in a manner that makes it easy to distinguish nodes with the same
23 content in the revision graph.
24 """
25 # As of now, if one of the parent node is null, p2 is null
26 if p2 == nullid:
27 # deep copy of a hash is faster than creating one
28 s = _nullhash.copy()
29 s.update(p1)
30 else:
31 # none of the parent nodes are nullid
32 if p1 < p2:
33 a = p1
34 b = p2
35 else:
36 a = p2
37 b = p1
38 s = hashlib.sha1(a)
39 s.update(b)
40 s.update(text)
41 return s.digest()
@@ -16,7 +16,6 from __future__ import absolute_import
16 import collections
16 import collections
17 import contextlib
17 import contextlib
18 import errno
18 import errno
19 import hashlib
20 import os
19 import os
21 import re
20 import re
22 import struct
21 import struct
@@ -74,6 +73,7 from .revlogutils import (
74 )
73 )
75 from .utils import (
74 from .utils import (
76 interfaceutil,
75 interfaceutil,
76 storageutil,
77 stringutil,
77 stringutil,
78 )
78 )
79
79
@@ -197,33 +197,6 def offset_type(offset, type):
197 raise ValueError('unknown revlog index flags')
197 raise ValueError('unknown revlog index flags')
198 return int(int(offset) << 16 | type)
198 return int(int(offset) << 16 | type)
199
199
200 _nullhash = hashlib.sha1(nullid)
201
202 def hash(text, p1, p2):
203 """generate a hash from the given text and its parent hashes
204
205 This hash combines both the current file contents and its history
206 in a manner that makes it easy to distinguish nodes with the same
207 content in the revision graph.
208 """
209 # As of now, if one of the parent node is null, p2 is null
210 if p2 == nullid:
211 # deep copy of a hash is faster than creating one
212 s = _nullhash.copy()
213 s.update(p1)
214 else:
215 # none of the parent nodes are nullid
216 if p1 < p2:
217 a = p1
218 b = p2
219 else:
220 a = p2
221 b = p1
222 s = hashlib.sha1(a)
223 s.update(b)
224 s.update(text)
225 return s.digest()
226
227 @attr.s(slots=True, frozen=True)
200 @attr.s(slots=True, frozen=True)
228 class _revisioninfo(object):
201 class _revisioninfo(object):
229 """Information about a revision that allows building its fulltext
202 """Information about a revision that allows building its fulltext
@@ -1383,7 +1356,7 class revlog(object):
1383 returns True if text is different than what is stored.
1356 returns True if text is different than what is stored.
1384 """
1357 """
1385 p1, p2 = self.parents(node)
1358 p1, p2 = self.parents(node)
1386 return hash(text, p1, p2) != node
1359 return storageutil.hashrevisionsha1(text, p1, p2) != node
1387
1360
1388 def _cachesegment(self, offset, data):
1361 def _cachesegment(self, offset, data):
1389 """Add a segment to the revlog cache.
1362 """Add a segment to the revlog cache.
@@ -1672,7 +1645,7 class revlog(object):
1672 Available as a function so that subclasses can replace the hash
1645 Available as a function so that subclasses can replace the hash
1673 as needed.
1646 as needed.
1674 """
1647 """
1675 return hash(text, p1, p2)
1648 return storageutil.hashrevisionsha1(text, p1, p2)
1676
1649
1677 def _processflags(self, text, flags, operation, raw=False):
1650 def _processflags(self, text, flags, operation, raw=False):
1678 """Inspect revision data flags and applies transforms defined by
1651 """Inspect revision data flags and applies transforms defined by
@@ -40,6 +40,7 from mercurial import (
40 )
40 )
41 from mercurial.utils import (
41 from mercurial.utils import (
42 interfaceutil,
42 interfaceutil,
43 storageutil,
43 )
44 )
44
45
45 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
46 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
@@ -285,7 +286,7 class filestorage(object):
285 def checkhash(self, text, node, p1=None, p2=None, rev=None):
286 def checkhash(self, text, node, p1=None, p2=None, rev=None):
286 if p1 is None and p2 is None:
287 if p1 is None and p2 is None:
287 p1, p2 = self.parents(node)
288 p1, p2 = self.parents(node)
288 if node != revlog.hash(text, p1, p2):
289 if node != storageutil.hashrevisionsha1(text, p1, p2):
289 raise simplestoreerror(_("integrity check failed on %s") %
290 raise simplestoreerror(_("integrity check failed on %s") %
290 self._path)
291 self._path)
291
292
@@ -342,7 +343,7 class filestorage(object):
342
343
343 p1, p2 = self.parents(node)
344 p1, p2 = self.parents(node)
344
345
345 if revlog.hash(t, p1, p2) == node:
346 if storageutil.hashrevisionsha1(t, p1, p2) == node:
346 return False
347 return False
347
348
348 if self.iscensored(self.rev(node)):
349 if self.iscensored(self.rev(node)):
@@ -420,11 +421,11 class filestorage(object):
420 validatenode(p2)
421 validatenode(p2)
421
422
422 if flags:
423 if flags:
423 node = node or revlog.hash(text, p1, p2)
424 node = node or storageutil.hashrevisionsha1(text, p1, p2)
424
425
425 rawtext, validatehash = self._processflags(text, flags, 'write')
426 rawtext, validatehash = self._processflags(text, flags, 'write')
426
427
427 node = node or revlog.hash(text, p1, p2)
428 node = node or storageutil.hashrevisionsha1(text, p1, p2)
428
429
429 if node in self._indexbynode:
430 if node in self._indexbynode:
430 return node
431 return node
General Comments 0
You need to be logged in to leave comments. Login now