comparison mercurial/revlog.py @ 51505:3cf9e52f5e27 stable

inline-changelog: fix a critical bug in write_pending that delete data Since a93e52f0b6ff we no longer use inline-revlog for the changelog. The goal there was to solve the lack of testing for the two variants (inline vs split) and reduce the complexity of the interaction with "diverted-write" on the changelog level. However many existing repository still have inline-changelog and we automatically move them to normal revlog as soon as we have the chances. Unfortunately This conversion is buggy and can result in the destruction of the changelog.i if hook triggers the "write pending" mechanism. The bugs comes from the "revlog splitting" logic and the "write_pending" logic stepping over each other. Ironically the change in a93e52f0b6ff aims at no longer having this kind of problem. This changesets fix this issue and add associated tests. Fixing this reveal that the transaction hooks end up not seeing the pending transaction content, because the name is not right ("changelog.i.s.a" instead of "changelog.i.s") we fix this in the next changeset.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 12 Jun 2024 02:15:20 +0200
parents def497c75351
children 1721d983dd6d
comparison
equal deleted inserted replaced
51504:553eb132366f 51505:3cf9e52f5e27
2893 maybe_self._indexfile = old_index_file_path 2893 maybe_self._indexfile = old_index_file_path
2894 maybe_self._inner.inline = True 2894 maybe_self._inner.inline = True
2895 maybe_self._inner.index_file = old_index_file_path 2895 maybe_self._inner.index_file = old_index_file_path
2896 2896
2897 tr.registertmp(new_index_file_path) 2897 tr.registertmp(new_index_file_path)
2898 # we use 001 here to make this this happens after the finalisation of
2899 # pending changelog write (using 000). Otherwise the two finalizer
2900 # would step over each other and delete the changelog.i file.
2898 if self.target[1] is not None: 2901 if self.target[1] is not None:
2899 callback_id = b'000-revlog-split-%d-%s' % self.target 2902 callback_id = b'001-revlog-split-%d-%s' % self.target
2900 else: 2903 else:
2901 callback_id = b'000-revlog-split-%d' % self.target[0] 2904 callback_id = b'001-revlog-split-%d' % self.target[0]
2902 tr.addfinalize(callback_id, finalize_callback) 2905 tr.addfinalize(callback_id, finalize_callback)
2903 tr.addabort(callback_id, abort_callback) 2906 tr.addabort(callback_id, abort_callback)
2904 2907
2905 self._format_flags &= ~FLAG_INLINE_DATA 2908 self._format_flags &= ~FLAG_INLINE_DATA
2906 self._inner.split_inline( 2909 self._inner.split_inline(