##// END OF EJS Templates
sidedata: add a function for _processflagsraw usage...
marmoute -
r43304:e8bc4c3d default
parent child Browse files
Show More
@@ -1,75 +1,79
1 # sidedata.py - Logic around store extra data alongside revlog revisions
1 # sidedata.py - Logic around store extra data alongside revlog revisions
2 #
2 #
3 # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net)
3 # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net)
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7 """core code for "sidedata" support
7 """core code for "sidedata" support
8
8
9 The "sidedata" are stored alongside the revision without actually being part of
9 The "sidedata" are stored alongside the revision without actually being part of
10 its content and not affecting its hash. It's main use cases is to cache
10 its content and not affecting its hash. It's main use cases is to cache
11 important information related to a changesets.
11 important information related to a changesets.
12
12
13 The current implementation is experimental and subject to changes. Do not rely
13 The current implementation is experimental and subject to changes. Do not rely
14 on it in production.
14 on it in production.
15
15
16 Sidedata are stored in the revlog itself, withing the revision rawtext. They
16 Sidedata are stored in the revlog itself, withing the revision rawtext. They
17 are inserted, removed from it using the flagprocessors mechanism. The following
17 are inserted, removed from it using the flagprocessors mechanism. The following
18 format is currently used::
18 format is currently used::
19
19
20 initial header:
20 initial header:
21 <number of sidedata; 2 bytes>
21 <number of sidedata; 2 bytes>
22 sidedata (repeated N times):
22 sidedata (repeated N times):
23 <sidedata-key; 2 bytes>
23 <sidedata-key; 2 bytes>
24 <sidedata-entry-length: 4 bytes>
24 <sidedata-entry-length: 4 bytes>
25 <sidedata-content-sha1-digest: 20 bytes>
25 <sidedata-content-sha1-digest: 20 bytes>
26 <sidedata-content; X bytes>
26 <sidedata-content; X bytes>
27 normal raw text:
27 normal raw text:
28 <all bytes remaining in the rawtext>
28 <all bytes remaining in the rawtext>
29
29
30 This is a simple and effective format. It should be enought to experiment with
30 This is a simple and effective format. It should be enought to experiment with
31 the concept.
31 the concept.
32 """
32 """
33
33
34 from __future__ import absolute_import
34 from __future__ import absolute_import
35
35
36 import hashlib
36 import hashlib
37 import struct
37 import struct
38
38
39 from .. import error
39 from .. import error
40
40
41 SIDEDATA_HEADER = struct.Struct('>H')
41 SIDEDATA_HEADER = struct.Struct('>H')
42 SIDEDATA_ENTRY = struct.Struct('>HL20s')
42 SIDEDATA_ENTRY = struct.Struct('>HL20s')
43
43
44 def sidedatawriteprocessor(rl, text, sidedata):
44 def sidedatawriteprocessor(rl, text, sidedata):
45 sidedata = list(sidedata.items())
45 sidedata = list(sidedata.items())
46 sidedata.sort()
46 sidedata.sort()
47 rawtext = [SIDEDATA_HEADER.pack(len(sidedata))]
47 rawtext = [SIDEDATA_HEADER.pack(len(sidedata))]
48 for key, value in sidedata:
48 for key, value in sidedata:
49 digest = hashlib.sha1(value).digest()
49 digest = hashlib.sha1(value).digest()
50 rawtext.append(SIDEDATA_ENTRY.pack(key, len(value), digest))
50 rawtext.append(SIDEDATA_ENTRY.pack(key, len(value), digest))
51 for key, value in sidedata:
51 for key, value in sidedata:
52 rawtext.append(value)
52 rawtext.append(value)
53 rawtext.append(bytes(text))
53 rawtext.append(bytes(text))
54 return ''.join(rawtext), False
54 return ''.join(rawtext), False
55
55
56 def sidedatareadprocessor(rl, text):
56 def sidedatareadprocessor(rl, text):
57 sidedata = {}
57 sidedata = {}
58 offset = 0
58 offset = 0
59 nbentry, = SIDEDATA_HEADER.unpack(text[:SIDEDATA_HEADER.size])
59 nbentry, = SIDEDATA_HEADER.unpack(text[:SIDEDATA_HEADER.size])
60 offset += SIDEDATA_HEADER.size
60 offset += SIDEDATA_HEADER.size
61 dataoffset = SIDEDATA_HEADER.size + (SIDEDATA_ENTRY.size * nbentry)
61 dataoffset = SIDEDATA_HEADER.size + (SIDEDATA_ENTRY.size * nbentry)
62 for i in range(nbentry):
62 for i in range(nbentry):
63 nextoffset = offset + SIDEDATA_ENTRY.size
63 nextoffset = offset + SIDEDATA_ENTRY.size
64 key, size, storeddigest = SIDEDATA_ENTRY.unpack(text[offset:nextoffset])
64 key, size, storeddigest = SIDEDATA_ENTRY.unpack(text[offset:nextoffset])
65 offset = nextoffset
65 offset = nextoffset
66 # read the data associated with that entry
66 # read the data associated with that entry
67 nextdataoffset = dataoffset + size
67 nextdataoffset = dataoffset + size
68 entrytext = text[dataoffset:nextdataoffset]
68 entrytext = text[dataoffset:nextdataoffset]
69 readdigest = hashlib.sha1(entrytext).digest()
69 readdigest = hashlib.sha1(entrytext).digest()
70 if storeddigest != readdigest:
70 if storeddigest != readdigest:
71 raise error.SidedataHashError(key, storeddigest, readdigest)
71 raise error.SidedataHashError(key, storeddigest, readdigest)
72 sidedata[key] = entrytext
72 sidedata[key] = entrytext
73 dataoffset = nextdataoffset
73 dataoffset = nextdataoffset
74 text = text[dataoffset:]
74 text = text[dataoffset:]
75 return text, True, sidedata
75 return text, True, sidedata
76
77 def sidedatarawprocessor(rl, text):
78 # side data modifies rawtext and prevent rawtext hash validation
79 return False
General Comments 0
You need to be logged in to leave comments. Login now