diff -r 502e795b55ac -r ba8e508a8e69 mercurial/revlog.py --- a/mercurial/revlog.py Mon Feb 15 11:08:28 2021 +0100 +++ b/mercurial/revlog.py Fri Feb 19 11:24:50 2021 +0100 @@ -3205,3 +3205,54 @@ ) return d + + def rewrite_sidedata(self, helpers, startrev, endrev): + if self.version & 0xFFFF != REVLOGV2: + return + # inline are not yet supported because they suffer from an issue when + # rewriting them (since it's not an append-only operation). + # See issue6485. + assert not self._inline + if not helpers[1] and not helpers[2]: + # Nothing to generate or remove + return + + new_entries = [] + # append the new sidedata + with self._datafp(b'a+') as fp: + # Maybe this bug still exists, see revlog._writeentry + fp.seek(0, os.SEEK_END) + current_offset = fp.tell() + for rev in range(startrev, endrev + 1): + entry = self.index[rev] + new_sidedata = storageutil.run_sidedata_helpers( + store=self, + sidedata_helpers=helpers, + sidedata={}, + rev=rev, + ) + + serialized_sidedata = sidedatautil.serialize_sidedata( + new_sidedata + ) + if entry[8] != 0 or entry[9] != 0: + # rewriting entries that already have sidedata is not + # supported yet, because it introduces garbage data in the + # revlog. + msg = "Rewriting existing sidedata is not supported yet" + raise error.Abort(msg) + entry = entry[:8] + entry += (current_offset, len(serialized_sidedata)) + + fp.write(serialized_sidedata) + new_entries.append(entry) + current_offset += len(serialized_sidedata) + + # rewrite the new index entries + with self._indexfp(b'w+') as fp: + fp.seek(startrev * self._io.size) + for i, entry in enumerate(new_entries): + rev = startrev + i + self.index.replace_sidedata_info(rev, entry[8], entry[9]) + packed = self._io.packentry(entry, self.node, self.version, rev) + fp.write(packed)