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
--- 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 ..