Mercurial > hg
changeset 48571:ccd9cb73125c stable
revlog: fix a bug where transaction can be aborted partially
Fix a repo corruption bug caused by a partial transaction rollback.
Differential Revision: https://phab.mercurial-scm.org/D12009
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Thu, 20 Jan 2022 14:06:36 +0000 |
parents | f38ae2d7390e |
children | f1898680d713 |
files | mercurial/revlog.py tests/test-transaction-rollback-on-revlog-split.t |
diffstat | 2 files changed, 20 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revlog.py Thu Jan 20 14:02:58 2022 +0000 +++ b/mercurial/revlog.py Thu Jan 20 14:06:36 2022 +0000 @@ -2006,7 +2006,7 @@ raise error.RevlogError( _(b"%s not found in the transaction") % self._indexfile ) - trindex = 0 + trindex = None tr.add(self._datafile, 0) existing_handles = False @@ -2029,10 +2029,17 @@ with self._indexfp() as read_ifh: for r in self: new_dfh.write(self._getsegmentforrevs(r, r, df=read_ifh)[1]) - if troffset <= self.start(r) + r * self.index.entry_size: + if ( + trindex is None + and troffset + <= self.start(r) + r * self.index.entry_size + ): trindex = r new_dfh.flush() + if trindex is None: + trindex = 0 + with self.__index_new_fp() as fp: self._format_flags &= ~FLAG_INLINE_DATA self._inline = False
--- a/tests/test-transaction-rollback-on-revlog-split.t Thu Jan 20 14:02:58 2022 +0000 +++ b/tests/test-transaction-rollback-on-revlog-split.t Thu Jan 20 14:06:36 2022 +0000 @@ -63,7 +63,7 @@ [80] #endif $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file | tail -1 - data/file.i 192 + data/file.i 128 The first file.i entry should match the "Reference size" above. The first file.d entry is the temporary record during the split, @@ -73,14 +73,14 @@ $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file data/file.i 1174 data/file.d 0 - data/file.d 1067 - data/file.i 192 + data/file.d 1046 + data/file.i 128 $ hg recover rolling back interrupted transaction (verify step skipped, run `hg verify` to check your repository content) $ f -s .hg/store/data/file* - .hg/store/data/file.d: size=1067 - .hg/store/data/file.i: size=192 + .hg/store/data/file.d: size=1046 + .hg/store/data/file.i: size=128 $ hg tip changeset: 1:cfa8d6e60429 tag: tip @@ -90,23 +90,12 @@ $ hg verify -q warning: revlog 'data/file.d' not in fncache! - file@?: rev 2 points to nonexistent changeset 2 - (expected ) - file@?: fa1120531cc1 not in manifests - 2 warnings encountered! + 1 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache - 2 integrity errors encountered! - [1] $ hg debugrebuildfncache --only-data adding data/file.d 1 items added, 0 removed from fncache $ hg verify -q - file@?: rev 2 points to nonexistent changeset 2 - (expected ) - file@?: fa1120531cc1 not in manifests - 1 warnings encountered! - 2 integrity errors encountered! - [1] $ cd .. @@ -134,13 +123,13 @@ $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file data/file.i 1174 data/file.d 0 - data/file.d 1067 + data/file.d 1046 $ hg recover rolling back interrupted transaction (verify step skipped, run `hg verify` to check your repository content) $ f -s .hg/store/data/file* - .hg/store/data/file.d: size=1067 + .hg/store/data/file.d: size=1046 .hg/store/data/file.i: size=1174 $ hg tip changeset: 1:cfa8d6e60429 @@ -172,8 +161,8 @@ abort: pretxnchangegroup hook exited with status 1 [40] $ f -s .hg/store/data/file* - .hg/store/data/file.d: size=1067 - .hg/store/data/file.i: size=192 + .hg/store/data/file.d: size=1046 + .hg/store/data/file.i: size=128 $ hg tip changeset: 1:cfa8d6e60429 tag: tip @@ -183,12 +172,7 @@ $ hg verify -q warning: revlog 'data/file.d' not in fncache! - file@?: rev 2 points to nonexistent changeset 2 - (expected ) - file@?: fa1120531cc1 not in manifests - 2 warnings encountered! + 1 warnings encountered! hint: run "hg debugrebuildfncache" to recover from corrupt fncache - 2 integrity errors encountered! - [1] $ cd ..