comparison mercurial/revlog.py @ 50348:f952be90b051 stable 6.4.2

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.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 18 Apr 2023 01:23:27 +0200
parents 87f0155d68aa
children 978ffa09910b 814f55775b21
comparison
equal deleted inserted replaced
50347:2bb2a1ff4d8f 50348:f952be90b051
17 import collections 17 import collections
18 import contextlib 18 import contextlib
19 import io 19 import io
20 import os 20 import os
21 import struct 21 import struct
22 import weakref
22 import zlib 23 import zlib
23 24
24 # import stuff from node for others to import from revlog 25 # import stuff from node for others to import from revlog
25 from .node import ( 26 from .node import (
26 bin, 27 bin,
2055 # this code 2056 # this code
2056 if side_write: 2057 if side_write:
2057 old_index_file_path = self._indexfile 2058 old_index_file_path = self._indexfile
2058 new_index_file_path = self._indexfile + b'.s' 2059 new_index_file_path = self._indexfile + b'.s'
2059 opener = self.opener 2060 opener = self.opener
2061 weak_self = weakref.ref(self)
2060 2062
2061 fncache = getattr(opener, 'fncache', None) 2063 fncache = getattr(opener, 'fncache', None)
2062 if fncache is not None: 2064 if fncache is not None:
2063 fncache.addignore(new_index_file_path) 2065 fncache.addignore(new_index_file_path)
2064 2066
2067 opener.rename( 2069 opener.rename(
2068 new_index_file_path, 2070 new_index_file_path,
2069 old_index_file_path, 2071 old_index_file_path,
2070 checkambig=True, 2072 checkambig=True,
2071 ) 2073 )
2074 maybe_self = weak_self()
2075 if maybe_self is not None:
2076 maybe_self._indexfile = old_index_file_path
2077
2078 def abort_callback(tr):
2079 maybe_self = weak_self()
2080 if maybe_self is not None:
2081 maybe_self._indexfile = old_index_file_path
2072 2082
2073 tr.registertmp(new_index_file_path) 2083 tr.registertmp(new_index_file_path)
2074 if self.target[1] is not None: 2084 if self.target[1] is not None:
2075 finalize_id = b'000-revlog-split-%d-%s' % self.target 2085 callback_id = b'000-revlog-split-%d-%s' % self.target
2076 else: 2086 else:
2077 finalize_id = b'000-revlog-split-%d' % self.target[0] 2087 callback_id = b'000-revlog-split-%d' % self.target[0]
2078 tr.addfinalize(finalize_id, finalize_callback) 2088 tr.addfinalize(callback_id, finalize_callback)
2089 tr.addabort(callback_id, abort_callback)
2079 2090
2080 new_dfh = self._datafp(b'w+') 2091 new_dfh = self._datafp(b'w+')
2081 new_dfh.truncate(0) # drop any potentially existing data 2092 new_dfh.truncate(0) # drop any potentially existing data
2082 try: 2093 try:
2083 with self._indexfp() as read_ifh: 2094 with self._indexfp() as read_ifh: