diff -r ced66295ea90 -r e9901d01d135 mercurial/revlog.py --- a/mercurial/revlog.py Tue Feb 23 22:58:30 2021 -0800 +++ b/mercurial/revlog.py Wed Feb 03 16:33:10 2021 -0800 @@ -421,6 +421,11 @@ If `upperboundcomp` is not None, this is the expected maximal gain from compression for the data content. + + `concurrencychecker` is an optional function that receives 3 arguments: a + file handle, a filename, and an expected position. It should check whether + the current position in the file handle is valid, and log/warn/fail (by + raising). """ _flagserrorclass = error.RevlogError @@ -435,6 +440,7 @@ censorable=False, upperboundcomp=None, persistentnodemap=False, + concurrencychecker=None, ): """ create a revlog object @@ -490,6 +496,8 @@ self._loadindex() + self._concurrencychecker = concurrencychecker + def _loadindex(self): mmapindexthreshold = None opts = self.opener.options @@ -2284,6 +2292,21 @@ curr = len(self) prev = curr - 1 offset = self.end(prev) + + if self._concurrencychecker: + if self._inline: + # offset is "as if" it were in the .d file, so we need to add on + # the size of the entry metadata. + self._concurrencychecker( + ifh, self.indexfile, offset + curr * self._io.size + ) + else: + # Entries in the .i are a consistent size. + self._concurrencychecker( + ifh, self.indexfile, curr * self._io.size + ) + self._concurrencychecker(dfh, self.datafile, offset) + p1r, p2r = self.rev(p1), self.rev(p2) # full versions are inserted when the needed deltas