# HG changeset patch # User Pierre-Yves David # Date 2023-04-17 23:23:27 # Node ID f952be90b0514a576dcc8bbe758ce3847faba9bb # Parent 2bb2a1ff4d8f8f98c392f6e7c965d82875ce80f4 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. diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -19,6 +19,7 @@ import contextlib import io import os import struct +import weakref import zlib # import stuff from node for others to import from revlog @@ -2057,6 +2058,7 @@ class revlog: 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 @@ class revlog: 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 diff --git a/tests/test-clonebundles.t b/tests/test-clonebundles.t --- a/tests/test-clonebundles.t +++ b/tests/test-clonebundles.t @@ -733,9 +733,7 @@ check the results $ 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 @@ check the results 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)