revlog-split: make sure the self._indexfile attribut is reset (
issue6811)
Before this change, after a transaction committing a file split, a revlog
object would have its `self._indexfile` attribute desynchronised from the
actual file storing the data. If that same object is reused (as we do for the
manifest during clone bundles), this lead to the data being writting in the
wrong location and the repository to go corrupt.
We not properly reset the attribut when applicable and everything is back in
working order.
--- a/mercurial/revlog.py Tue Apr 18 00:07:52 2023 +0200
+++ b/mercurial/revlog.py Tue Apr 18 01:23:27 2023 +0200
@@ -19,6 +19,7 @@
import io
import os
import struct
+import weakref
import zlib
# import stuff from node for others to import from revlog
@@ -2057,6 +2058,7 @@
old_index_file_path = self._indexfile
new_index_file_path = self._indexfile + b'.s'
opener = self.opener
+ weak_self = weakref.ref(self)
fncache = getattr(opener, 'fncache', None)
if fncache is not None:
@@ -2069,13 +2071,22 @@
old_index_file_path,
checkambig=True,
)
+ maybe_self = weak_self()
+ if maybe_self is not None:
+ maybe_self._indexfile = old_index_file_path
+
+ def abort_callback(tr):
+ maybe_self = weak_self()
+ if maybe_self is not None:
+ maybe_self._indexfile = old_index_file_path
tr.registertmp(new_index_file_path)
if self.target[1] is not None:
- finalize_id = b'000-revlog-split-%d-%s' % self.target
+ callback_id = b'000-revlog-split-%d-%s' % self.target
else:
- finalize_id = b'000-revlog-split-%d' % self.target[0]
- tr.addfinalize(finalize_id, finalize_callback)
+ callback_id = b'000-revlog-split-%d' % self.target[0]
+ tr.addfinalize(callback_id, finalize_callback)
+ tr.addabort(callback_id, abort_callback)
new_dfh = self._datafp(b'w+')
new_dfh.truncate(0) # drop any potentially existing data
--- a/tests/test-clonebundles.t Tue Apr 18 00:07:52 2023 +0200
+++ b/tests/test-clonebundles.t Tue Apr 18 01:23:27 2023 +0200
@@ -733,9 +733,7 @@
$ cd revlog-split-in-the-bundle
$ f --size .hg/store/00manifest.*
.hg/store/00manifest.d: size=499037
- .hg/store/00manifest.i: size=192 (missing-correct-output !)
- .hg/store/00manifest.i: size=128 (known-bad-output !)
- .hg/store/00manifest.i.s: size=64 (known-bad-output !)
+ .hg/store/00manifest.i: size=192
$ f --size .hg/store/data/_a.*
.hg/store/data/_a.d: size=588917
.hg/store/data/_a.i: size=192
@@ -743,15 +741,11 @@
manifest should work
$ hg files -r tip | wc -l
- \s*10001 (re) (missing-correct-output !)
- abort: 00manifest@4941afd6b8e298d932227572c5c303cbc14301bd: no node (known-bad-output !)
- 0 (known-bad-output !)
+ \s*10001 (re)
file content should work
$ hg cat -r tip A | wc -l
- \s*100001 (re) (missing-correct-output !)
- abort: 00manifest@4941afd6b8e298d932227572c5c303cbc14301bd: no node (known-bad-output !)
- 0 (known-bad-output !)
+ \s*100001 (re)