##// END OF EJS Templates
sidedata: move to new sidedata storage in revlogv2...
Raphaël Gomès -
r47443:3d740058 default
parent child Browse files
Show More
@@ -116,10 +116,10 b' def readfromstore(self, text):'
116 if hgmeta or text.startswith(b'\1\n'):
116 if hgmeta or text.startswith(b'\1\n'):
117 text = storageutil.packmeta(hgmeta, text)
117 text = storageutil.packmeta(hgmeta, text)
118
118
119 return (text, True, {})
119 return (text, True)
120
120
121
121
122 def writetostore(self, text, sidedata):
122 def writetostore(self, text):
123 # hg filelog metadata (includes rename, etc)
123 # hg filelog metadata (includes rename, etc)
124 hgmeta, offset = storageutil.parsemeta(text)
124 hgmeta, offset = storageutil.parsemeta(text)
125 if offset and offset > 0:
125 if offset and offset > 0:
@@ -155,12 +155,12 b' class remotefilelog(object):'
155 # text passed to "addrevision" includes hg filelog metadata header
155 # text passed to "addrevision" includes hg filelog metadata header
156 if node is None:
156 if node is None:
157 node = storageutil.hashrevisionsha1(text, p1, p2)
157 node = storageutil.hashrevisionsha1(text, p1, p2)
158 if sidedata is None:
159 sidedata = {}
160
158
161 meta, metaoffset = storageutil.parsemeta(text)
159 meta, metaoffset = storageutil.parsemeta(text)
162 rawtext, validatehash = flagutil.processflagswrite(
160 rawtext, validatehash = flagutil.processflagswrite(
163 self, text, flags, sidedata=sidedata
161 self,
162 text,
163 flags,
164 )
164 )
165 return self.addrawrevision(
165 return self.addrawrevision(
166 rawtext,
166 rawtext,
@@ -120,10 +120,10 b" rustrevlog = policy.importrust('revlog')"
120
120
121 # Flag processors for REVIDX_ELLIPSIS.
121 # Flag processors for REVIDX_ELLIPSIS.
122 def ellipsisreadprocessor(rl, text):
122 def ellipsisreadprocessor(rl, text):
123 return text, False, {}
123 return text, False
124
124
125
125
126 def ellipsiswriteprocessor(rl, text, sidedata):
126 def ellipsiswriteprocessor(rl, text):
127 return text, False
127 return text, False
128
128
129
129
@@ -554,8 +554,6 b' class revlog(object):'
554 if self._mmaplargeindex and b'mmapindexthreshold' in opts:
554 if self._mmaplargeindex and b'mmapindexthreshold' in opts:
555 mmapindexthreshold = opts[b'mmapindexthreshold']
555 mmapindexthreshold = opts[b'mmapindexthreshold']
556 self.hassidedata = bool(opts.get(b'side-data', False))
556 self.hassidedata = bool(opts.get(b'side-data', False))
557 if self.hassidedata:
558 self._flagprocessors[REVIDX_SIDEDATA] = sidedatautil.processors
559 self._sparserevlog = bool(opts.get(b'sparse-revlog', False))
557 self._sparserevlog = bool(opts.get(b'sparse-revlog', False))
560 withsparseread = bool(opts.get(b'with-sparse-read', False))
558 withsparseread = bool(opts.get(b'with-sparse-read', False))
561 # sparse-revlog forces sparse-read
559 # sparse-revlog forces sparse-read
@@ -856,6 +854,11 b' class revlog(object):'
856 def length(self, rev):
854 def length(self, rev):
857 return self.index[rev][1]
855 return self.index[rev][1]
858
856
857 def sidedata_length(self, rev):
858 if self.version & 0xFFFF != REVLOGV2:
859 return 0
860 return self.index[rev][9]
861
859 def rawsize(self, rev):
862 def rawsize(self, rev):
860 """return the length of the uncompressed text for a given revision"""
863 """return the length of the uncompressed text for a given revision"""
861 l = self.index[rev][2]
864 l = self.index[rev][2]
@@ -917,7 +920,7 b' class revlog(object):'
917 # Derived from index values.
920 # Derived from index values.
918
921
919 def end(self, rev):
922 def end(self, rev):
920 return self.start(rev) + self.length(rev)
923 return self.start(rev) + self.length(rev) + self.sidedata_length(rev)
921
924
922 def parents(self, node):
925 def parents(self, node):
923 i = self.index
926 i = self.index
@@ -1853,7 +1856,7 b' class revlog(object):'
1853 elif operation == b'read':
1856 elif operation == b'read':
1854 return flagutil.processflagsread(self, text, flags)
1857 return flagutil.processflagsread(self, text, flags)
1855 else: # write operation
1858 else: # write operation
1856 return flagutil.processflagswrite(self, text, flags, None)
1859 return flagutil.processflagswrite(self, text, flags)
1857
1860
1858 def revision(self, nodeorrev, _df=None, raw=False):
1861 def revision(self, nodeorrev, _df=None, raw=False):
1859 """return an uncompressed revision of a given node or revision
1862 """return an uncompressed revision of a given node or revision
@@ -1898,10 +1901,17 b' class revlog(object):'
1898 # revision or might need to be processed to retrieve the revision.
1901 # revision or might need to be processed to retrieve the revision.
1899 rev, rawtext, validated = self._rawtext(node, rev, _df=_df)
1902 rev, rawtext, validated = self._rawtext(node, rev, _df=_df)
1900
1903
1904 if self.version & 0xFFFF == REVLOGV2:
1905 if rev is None:
1906 rev = self.rev(node)
1907 sidedata = self._sidedata(rev)
1908 else:
1909 sidedata = {}
1910
1901 if raw and validated:
1911 if raw and validated:
1902 # if we don't want to process the raw text and that raw
1912 # if we don't want to process the raw text and that raw
1903 # text is cached, we can exit early.
1913 # text is cached, we can exit early.
1904 return rawtext, {}
1914 return rawtext, sidedata
1905 if rev is None:
1915 if rev is None:
1906 rev = self.rev(node)
1916 rev = self.rev(node)
1907 # the revlog's flag for this revision
1917 # the revlog's flag for this revision
@@ -1910,20 +1920,14 b' class revlog(object):'
1910
1920
1911 if validated and flags == REVIDX_DEFAULT_FLAGS:
1921 if validated and flags == REVIDX_DEFAULT_FLAGS:
1912 # no extra flags set, no flag processor runs, text = rawtext
1922 # no extra flags set, no flag processor runs, text = rawtext
1913 return rawtext, {}
1923 return rawtext, sidedata
1914
1924
1915 sidedata = {}
1916 if raw:
1925 if raw:
1917 validatehash = flagutil.processflagsraw(self, rawtext, flags)
1926 validatehash = flagutil.processflagsraw(self, rawtext, flags)
1918 text = rawtext
1927 text = rawtext
1919 else:
1928 else:
1920 try:
1929 r = flagutil.processflagsread(self, rawtext, flags)
1921 r = flagutil.processflagsread(self, rawtext, flags)
1930 text, validatehash = r
1922 except error.SidedataHashError as exc:
1923 msg = _(b"integrity check failed on %s:%s sidedata key %d")
1924 msg %= (self.indexfile, pycompat.bytestr(rev), exc.sidedatakey)
1925 raise error.RevlogError(msg)
1926 text, validatehash, sidedata = r
1927 if validatehash:
1931 if validatehash:
1928 self.checkhash(text, node, rev=rev)
1932 self.checkhash(text, node, rev=rev)
1929 if not validated:
1933 if not validated:
@@ -1974,6 +1978,21 b' class revlog(object):'
1974 del basetext # let us have a chance to free memory early
1978 del basetext # let us have a chance to free memory early
1975 return (rev, rawtext, False)
1979 return (rev, rawtext, False)
1976
1980
1981 def _sidedata(self, rev):
1982 """Return the sidedata for a given revision number."""
1983 index_entry = self.index[rev]
1984 sidedata_offset = index_entry[8]
1985 sidedata_size = index_entry[9]
1986
1987 if self._inline:
1988 sidedata_offset += self._io.size * (1 + rev)
1989 if sidedata_size == 0:
1990 return {}
1991
1992 segment = self._getsegment(sidedata_offset, sidedata_size)
1993 sidedata = sidedatautil.deserialize_sidedata(segment)
1994 return sidedata
1995
1977 def rawdata(self, nodeorrev, _df=None):
1996 def rawdata(self, nodeorrev, _df=None):
1978 """return an uncompressed raw data of a given node or revision number.
1997 """return an uncompressed raw data of a given node or revision number.
1979
1998
@@ -2107,20 +2126,15 b' class revlog(object):'
2107
2126
2108 if sidedata is None:
2127 if sidedata is None:
2109 sidedata = {}
2128 sidedata = {}
2110 flags = flags & ~REVIDX_SIDEDATA
2111 elif not self.hassidedata:
2129 elif not self.hassidedata:
2112 raise error.ProgrammingError(
2130 raise error.ProgrammingError(
2113 _(b"trying to add sidedata to a revlog who don't support them")
2131 _(b"trying to add sidedata to a revlog who don't support them")
2114 )
2132 )
2115 else:
2116 flags |= REVIDX_SIDEDATA
2117
2133
2118 if flags:
2134 if flags:
2119 node = node or self.hash(text, p1, p2)
2135 node = node or self.hash(text, p1, p2)
2120
2136
2121 rawtext, validatehash = flagutil.processflagswrite(
2137 rawtext, validatehash = flagutil.processflagswrite(self, text, flags)
2122 self, text, flags, sidedata=sidedata
2123 )
2124
2138
2125 # If the flag processor modifies the revision data, ignore any provided
2139 # If the flag processor modifies the revision data, ignore any provided
2126 # cachedelta.
2140 # cachedelta.
@@ -2153,6 +2167,7 b' class revlog(object):'
2153 flags,
2167 flags,
2154 cachedelta=cachedelta,
2168 cachedelta=cachedelta,
2155 deltacomputer=deltacomputer,
2169 deltacomputer=deltacomputer,
2170 sidedata=sidedata,
2156 )
2171 )
2157
2172
2158 def addrawrevision(
2173 def addrawrevision(
@@ -2166,6 +2181,7 b' class revlog(object):'
2166 flags,
2181 flags,
2167 cachedelta=None,
2182 cachedelta=None,
2168 deltacomputer=None,
2183 deltacomputer=None,
2184 sidedata=None,
2169 ):
2185 ):
2170 """add a raw revision with known flags, node and parents
2186 """add a raw revision with known flags, node and parents
2171 useful when reusing a revision not stored in this revlog (ex: received
2187 useful when reusing a revision not stored in this revlog (ex: received
@@ -2188,6 +2204,7 b' class revlog(object):'
2188 ifh,
2204 ifh,
2189 dfh,
2205 dfh,
2190 deltacomputer=deltacomputer,
2206 deltacomputer=deltacomputer,
2207 sidedata=sidedata,
2191 )
2208 )
2192 finally:
2209 finally:
2193 if dfh:
2210 if dfh:
@@ -2281,6 +2298,7 b' class revlog(object):'
2281 dfh,
2298 dfh,
2282 alwayscache=False,
2299 alwayscache=False,
2283 deltacomputer=None,
2300 deltacomputer=None,
2301 sidedata=None,
2284 ):
2302 ):
2285 """internal function to add revisions to the log
2303 """internal function to add revisions to the log
2286
2304
@@ -2350,6 +2368,16 b' class revlog(object):'
2350
2368
2351 deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
2369 deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
2352
2370
2371 if sidedata:
2372 serialized_sidedata = sidedatautil.serialize_sidedata(sidedata)
2373 sidedata_offset = offset + deltainfo.deltalen
2374 else:
2375 serialized_sidedata = b""
2376 # Don't store the offset if the sidedata is empty, that way
2377 # we can easily detect empty sidedata and they will be no different
2378 # than ones we manually add.
2379 sidedata_offset = 0
2380
2353 e = (
2381 e = (
2354 offset_type(offset, flags),
2382 offset_type(offset, flags),
2355 deltainfo.deltalen,
2383 deltainfo.deltalen,
@@ -2359,18 +2387,24 b' class revlog(object):'
2359 p1r,
2387 p1r,
2360 p2r,
2388 p2r,
2361 node,
2389 node,
2362 0,
2390 sidedata_offset,
2363 0,
2391 len(serialized_sidedata),
2364 )
2392 )
2365
2393
2366 if self.version & 0xFFFF != REVLOGV2:
2394 if self.version & 0xFFFF != REVLOGV2:
2367 e = e[:8]
2395 e = e[:8]
2368
2396
2369 self.index.append(e)
2397 self.index.append(e)
2370
2371 entry = self._io.packentry(e, self.node, self.version, curr)
2398 entry = self._io.packentry(e, self.node, self.version, curr)
2372 self._writeentry(
2399 self._writeentry(
2373 transaction, ifh, dfh, entry, deltainfo.data, link, offset
2400 transaction,
2401 ifh,
2402 dfh,
2403 entry,
2404 deltainfo.data,
2405 link,
2406 offset,
2407 serialized_sidedata,
2374 )
2408 )
2375
2409
2376 rawtext = btext[0]
2410 rawtext = btext[0]
@@ -2383,7 +2417,9 b' class revlog(object):'
2383 self._chainbasecache[curr] = deltainfo.chainbase
2417 self._chainbasecache[curr] = deltainfo.chainbase
2384 return curr
2418 return curr
2385
2419
2386 def _writeentry(self, transaction, ifh, dfh, entry, data, link, offset):
2420 def _writeentry(
2421 self, transaction, ifh, dfh, entry, data, link, offset, sidedata
2422 ):
2387 # Files opened in a+ mode have inconsistent behavior on various
2423 # Files opened in a+ mode have inconsistent behavior on various
2388 # platforms. Windows requires that a file positioning call be made
2424 # platforms. Windows requires that a file positioning call be made
2389 # when the file handle transitions between reads and writes. See
2425 # when the file handle transitions between reads and writes. See
@@ -2407,6 +2443,8 b' class revlog(object):'
2407 if data[0]:
2443 if data[0]:
2408 dfh.write(data[0])
2444 dfh.write(data[0])
2409 dfh.write(data[1])
2445 dfh.write(data[1])
2446 if sidedata:
2447 dfh.write(sidedata)
2410 ifh.write(entry)
2448 ifh.write(entry)
2411 else:
2449 else:
2412 offset += curr * self._io.size
2450 offset += curr * self._io.size
@@ -2414,6 +2452,8 b' class revlog(object):'
2414 ifh.write(entry)
2452 ifh.write(entry)
2415 ifh.write(data[0])
2453 ifh.write(data[0])
2416 ifh.write(data[1])
2454 ifh.write(data[1])
2455 if sidedata:
2456 ifh.write(sidedata)
2417 self._enforceinlinesize(transaction, ifh)
2457 self._enforceinlinesize(transaction, ifh)
2418 nodemaputil.setup_persistent_nodemap(transaction, self)
2458 nodemaputil.setup_persistent_nodemap(transaction, self)
2419
2459
@@ -84,7 +84,7 b' def insertflagprocessor(flag, processor,'
84 flagprocessors[flag] = processor
84 flagprocessors[flag] = processor
85
85
86
86
87 def processflagswrite(revlog, text, flags, sidedata):
87 def processflagswrite(revlog, text, flags):
88 """Inspect revision data flags and applies write transformations defined
88 """Inspect revision data flags and applies write transformations defined
89 by registered flag processors.
89 by registered flag processors.
90
90
@@ -100,9 +100,12 b' def processflagswrite(revlog, text, flag'
100 processed text and ``validatehash`` is a bool indicating whether the
100 processed text and ``validatehash`` is a bool indicating whether the
101 returned text should be checked for hash integrity.
101 returned text should be checked for hash integrity.
102 """
102 """
103 return _processflagsfunc(revlog, text, flags, b'write', sidedata=sidedata)[
103 return _processflagsfunc(
104 :2
104 revlog,
105 ]
105 text,
106 flags,
107 b'write',
108 )[:2]
106
109
107
110
108 def processflagsread(revlog, text, flags):
111 def processflagsread(revlog, text, flags):
@@ -145,14 +148,14 b' def processflagsraw(revlog, text, flags)'
145 return _processflagsfunc(revlog, text, flags, b'raw')[1]
148 return _processflagsfunc(revlog, text, flags, b'raw')[1]
146
149
147
150
148 def _processflagsfunc(revlog, text, flags, operation, sidedata=None):
151 def _processflagsfunc(revlog, text, flags, operation):
149 """internal function to process flag on a revlog
152 """internal function to process flag on a revlog
150
153
151 This function is private to this module, code should never needs to call it
154 This function is private to this module, code should never needs to call it
152 directly."""
155 directly."""
153 # fast path: no flag processors will run
156 # fast path: no flag processors will run
154 if flags == 0:
157 if flags == 0:
155 return text, True, {}
158 return text, True
156 if operation not in (b'read', b'write', b'raw'):
159 if operation not in (b'read', b'write', b'raw'):
157 raise error.ProgrammingError(_(b"invalid '%s' operation") % operation)
160 raise error.ProgrammingError(_(b"invalid '%s' operation") % operation)
158 # Check all flags are known.
161 # Check all flags are known.
@@ -168,7 +171,6 b' def _processflagsfunc(revlog, text, flag'
168 if operation == b'write':
171 if operation == b'write':
169 orderedflags = reversed(orderedflags)
172 orderedflags = reversed(orderedflags)
170
173
171 outsidedata = {}
172 for flag in orderedflags:
174 for flag in orderedflags:
173 # If a flagprocessor has been registered for a known flag, apply the
175 # If a flagprocessor has been registered for a known flag, apply the
174 # related operation transform and update result tuple.
176 # related operation transform and update result tuple.
@@ -186,10 +188,9 b' def _processflagsfunc(revlog, text, flag'
186 if operation == b'raw':
188 if operation == b'raw':
187 vhash = rawtransform(revlog, text)
189 vhash = rawtransform(revlog, text)
188 elif operation == b'read':
190 elif operation == b'read':
189 text, vhash, s = readtransform(revlog, text)
191 text, vhash = readtransform(revlog, text)
190 outsidedata.update(s)
191 else: # write operation
192 else: # write operation
192 text, vhash = writetransform(revlog, text, sidedata)
193 text, vhash = writetransform(revlog, text)
193 validatehash = validatehash and vhash
194 validatehash = validatehash and vhash
194
195
195 return text, validatehash, outsidedata
196 return text, validatehash
@@ -13,9 +13,8 b' important information related to a chang'
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, within the revision rawtext. They
16 Sidedata are stored in the revlog itself, thanks to a new version of the
17 are inserted and removed from it using the flagprocessors mechanism. The following
17 revlog. The following format is currently used::
18 format is currently used::
19
18
20 initial header:
19 initial header:
21 <number of sidedata; 2 bytes>
20 <number of sidedata; 2 bytes>
@@ -60,48 +59,35 b" SIDEDATA_HEADER = struct.Struct('>H')"
60 SIDEDATA_ENTRY = struct.Struct('>HL20s')
59 SIDEDATA_ENTRY = struct.Struct('>HL20s')
61
60
62
61
63 def sidedatawriteprocessor(rl, text, sidedata):
62 def serialize_sidedata(sidedata):
64 sidedata = list(sidedata.items())
63 sidedata = list(sidedata.items())
65 sidedata.sort()
64 sidedata.sort()
66 rawtext = [SIDEDATA_HEADER.pack(len(sidedata))]
65 buf = [SIDEDATA_HEADER.pack(len(sidedata))]
67 for key, value in sidedata:
66 for key, value in sidedata:
68 digest = hashutil.sha1(value).digest()
67 digest = hashutil.sha1(value).digest()
69 rawtext.append(SIDEDATA_ENTRY.pack(key, len(value), digest))
68 buf.append(SIDEDATA_ENTRY.pack(key, len(value), digest))
70 for key, value in sidedata:
69 for key, value in sidedata:
71 rawtext.append(value)
70 buf.append(value)
72 rawtext.append(bytes(text))
71 buf = b''.join(buf)
73 return b''.join(rawtext), False
72 return buf
74
73
75
74
76 def sidedatareadprocessor(rl, text):
75 def deserialize_sidedata(blob):
77 sidedata = {}
76 sidedata = {}
78 offset = 0
77 offset = 0
79 (nbentry,) = SIDEDATA_HEADER.unpack(text[: SIDEDATA_HEADER.size])
78 (nbentry,) = SIDEDATA_HEADER.unpack(blob[: SIDEDATA_HEADER.size])
80 offset += SIDEDATA_HEADER.size
79 offset += SIDEDATA_HEADER.size
81 dataoffset = SIDEDATA_HEADER.size + (SIDEDATA_ENTRY.size * nbentry)
80 dataoffset = SIDEDATA_HEADER.size + (SIDEDATA_ENTRY.size * nbentry)
82 for i in range(nbentry):
81 for i in range(nbentry):
83 nextoffset = offset + SIDEDATA_ENTRY.size
82 nextoffset = offset + SIDEDATA_ENTRY.size
84 key, size, storeddigest = SIDEDATA_ENTRY.unpack(text[offset:nextoffset])
83 key, size, storeddigest = SIDEDATA_ENTRY.unpack(blob[offset:nextoffset])
85 offset = nextoffset
84 offset = nextoffset
86 # read the data associated with that entry
85 # read the data associated with that entry
87 nextdataoffset = dataoffset + size
86 nextdataoffset = dataoffset + size
88 entrytext = text[dataoffset:nextdataoffset]
87 entrytext = bytes(blob[dataoffset:nextdataoffset])
89 readdigest = hashutil.sha1(entrytext).digest()
88 readdigest = hashutil.sha1(entrytext).digest()
90 if storeddigest != readdigest:
89 if storeddigest != readdigest:
91 raise error.SidedataHashError(key, storeddigest, readdigest)
90 raise error.SidedataHashError(key, storeddigest, readdigest)
92 sidedata[key] = entrytext
91 sidedata[key] = entrytext
93 dataoffset = nextdataoffset
92 dataoffset = nextdataoffset
94 text = text[dataoffset:]
93 return sidedata
95 return text, True, sidedata
96
97
98 def sidedatarawprocessor(rl, text):
99 # side data modifies rawtext and prevent rawtext hash validation
100 return False
101
102
103 processors = (
104 sidedatareadprocessor,
105 sidedatawriteprocessor,
106 sidedatarawprocessor,
107 )
@@ -31,28 +31,28 b' def bypass(self, text):'
31 return False
31 return False
32
32
33
33
34 def noopdonothing(self, text, sidedata):
34 def noopdonothing(self, text):
35 return (text, True)
35 return (text, True)
36
36
37
37
38 def noopdonothingread(self, text):
38 def noopdonothingread(self, text):
39 return (text, True, {})
39 return (text, True)
40
40
41
41
42 def b64encode(self, text, sidedata):
42 def b64encode(self, text):
43 return (base64.b64encode(text), False)
43 return (base64.b64encode(text), False)
44
44
45
45
46 def b64decode(self, text):
46 def b64decode(self, text):
47 return (base64.b64decode(text), True, {})
47 return (base64.b64decode(text), True)
48
48
49
49
50 def gzipcompress(self, text, sidedata):
50 def gzipcompress(self, text):
51 return (zlib.compress(text), False)
51 return (zlib.compress(text), False)
52
52
53
53
54 def gzipdecompress(self, text):
54 def gzipdecompress(self, text):
55 return (zlib.decompress(text), True, {})
55 return (zlib.decompress(text), True)
56
56
57
57
58 def supportedoutgoingversions(orig, repo):
58 def supportedoutgoingversions(orig, repo):
@@ -300,7 +300,7 b' class filestorage(object):'
300 text = rawtext
300 text = rawtext
301 else:
301 else:
302 r = flagutil.processflagsread(self, rawtext, flags)
302 r = flagutil.processflagsread(self, rawtext, flags)
303 text, validatehash, sidedata = r
303 text, validatehash = r
304 if validatehash:
304 if validatehash:
305 self.checkhash(text, node, rev=rev)
305 self.checkhash(text, node, rev=rev)
306
306
@@ -271,12 +271,13 b' copy information on to the filelog'
271 $ hg ci --amend -m 'copy a to j, v2'
271 $ hg ci --amend -m 'copy a to j, v2'
272 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
272 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob)
273 $ hg debugsidedata -c -v -- -1
273 $ hg debugsidedata -c -v -- -1
274 1 sidedata entries
274 1 sidedata entries (missing-correct-output !)
275 entry-0014 size 24
275 entry-0014 size 24 (missing-correct-output !)
276 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj'
276 '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj' (missing-correct-output !)
277 #endif
277 #endif
278 $ hg showcopies --config experimental.copies.read-from=filelog-only
278 $ hg showcopies --config experimental.copies.read-from=filelog-only
279 a -> j
279 a -> j (sidedata missing-correct-output !)
280 a -> j (no-sidedata !)
280 The entries should be written to extras even if they're empty (so the client
281 The entries should be written to extras even if they're empty (so the client
281 won't have to fall back to reading from filelogs)
282 won't have to fall back to reading from filelogs)
282 $ echo x >> j
283 $ echo x >> j
@@ -354,7 +355,8 b' with no fallback.'
354 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob)
355 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob)
355 $ hg st --change . --copies
356 $ hg st --change . --copies
356 A b
357 A b
357 a
358 a (sidedata missing-correct-output !)
359 a (no-sidedata !)
358 R a
360 R a
359 $ cd ..
361 $ cd ..
360
362
@@ -51,10 +51,10 b' def abort(msg):'
51 def readprocessor(self, rawtext):
51 def readprocessor(self, rawtext):
52 # True: the returned text could be used to verify hash
52 # True: the returned text could be used to verify hash
53 text = rawtext[len(_extheader) :].replace(b'i', b'1')
53 text = rawtext[len(_extheader) :].replace(b'i', b'1')
54 return text, True, {}
54 return text, True
55
55
56
56
57 def writeprocessor(self, text, sidedata):
57 def writeprocessor(self, text):
58 # False: the returned rawtext shouldn't be used to verify hash
58 # False: the returned rawtext shouldn't be used to verify hash
59 rawtext = _extheader + text.replace(b'1', b'i')
59 rawtext = _extheader + text.replace(b'1', b'i')
60 return rawtext, False
60 return rawtext, False
@@ -293,7 +293,7 b' def writecases(rlog, tr):'
293
293
294 # Verify text, rawtext, and rawsize
294 # Verify text, rawtext, and rawsize
295 if isext:
295 if isext:
296 rawtext = writeprocessor(None, text, {})[0]
296 rawtext = writeprocessor(None, text)[0]
297 else:
297 else:
298 rawtext = text
298 rawtext = text
299 if rlog.rawsize(rev) != len(rawtext):
299 if rlog.rawsize(rev) != len(rawtext):
@@ -40,19 +40,20 b' def wrapaddrevision('
40 return orig(self, text, transaction, link, p1, p2, *args, **kwargs)
40 return orig(self, text, transaction, link, p1, p2, *args, **kwargs)
41
41
42
42
43 def wraprevision(orig, self, nodeorrev, *args, **kwargs):
43 def wrap_revisiondata(orig, self, nodeorrev, *args, **kwargs):
44 text = orig(self, nodeorrev, *args, **kwargs)
44 text, sd = orig(self, nodeorrev, *args, **kwargs)
45 if getattr(self, 'sidedatanocheck', False):
45 if getattr(self, 'sidedatanocheck', False):
46 return text
46 return text, sd
47 if self.version & 0xFFFF != 2:
48 return text, sd
47 if nodeorrev != nullrev and nodeorrev != nullid:
49 if nodeorrev != nullrev and nodeorrev != nullid:
48 sd = self.sidedata(nodeorrev)
49 if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]:
50 if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]:
50 raise RuntimeError('text size mismatch')
51 raise RuntimeError('text size mismatch')
51 expected = sd[sidedata.SD_TEST2]
52 expected = sd[sidedata.SD_TEST2]
52 got = hashlib.sha256(text).digest()
53 got = hashlib.sha256(text).digest()
53 if got != expected:
54 if got != expected:
54 raise RuntimeError('sha256 mismatch')
55 raise RuntimeError('sha256 mismatch')
55 return text
56 return text, sd
56
57
57
58
58 def wrapgetsidedatacompanion(orig, srcrepo, dstrepo):
59 def wrapgetsidedatacompanion(orig, srcrepo, dstrepo):
@@ -81,7 +82,7 b' def wrapgetsidedatacompanion(orig, srcre'
81
82
82 def extsetup(ui):
83 def extsetup(ui):
83 extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision)
84 extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision)
84 extensions.wrapfunction(revlog.revlog, 'revision', wraprevision)
85 extensions.wrapfunction(revlog.revlog, '_revisiondata', wrap_revisiondata)
85 extensions.wrapfunction(
86 extensions.wrapfunction(
86 upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion
87 upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion
87 )
88 )
General Comments 0
You need to be logged in to leave comments. Login now