Mercurial > public > mercurial-scm > hg-stable
changeset 50049:2f348babe30d
transaction: clarify the "quick abort" scenario
Right now, the transaction has a code-pass to do a "quick abort" that skip most?
(too much) of the logic when the right condition are detected?
We are about to improve this logic in multiple aspect. We clarify the code
first.
The conditional return in `_can_quick_abort` looks a bit weird because we are
about to make them more complex very soon.
[1] actually too much
[2] actually not often enough
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 14 Feb 2023 18:59:04 +0100 |
parents | 420fad6bdec5 |
children | 3128018e878b |
files | mercurial/transaction.py |
diffstat | 1 files changed, 48 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/transaction.py Tue Feb 07 15:27:37 2023 +0100 +++ b/mercurial/transaction.py Tue Feb 14 18:59:04 2023 +0100 @@ -668,42 +668,60 @@ self._file.close() self._backupsfile.close() + quick = self._can_quick_abort(entries) try: - if not entries and not self._backupentries: - if self._backupjournal: - self._opener.unlink(self._backupjournal) - if self._journal: - self._opener.unlink(self._journal) - return - - self._report(_(b"transaction abort!\n")) - - try: - for cat in sorted(self._abortcallback): - self._abortcallback[cat](self) - # Prevent double usage and help clear cycles. - self._abortcallback = None - _playback( - self._journal, - self._report, - self._opener, - self._vfsmap, - entries, - self._backupentries, - False, - checkambigfiles=self._checkambigfiles, - ) - self._report(_(b"rollback completed\n")) - except BaseException as exc: - self._report(_(b"rollback failed - please run hg recover\n")) - self._report( - _(b"(failure reason: %s)\n") % stringutil.forcebytestr(exc) - ) + if quick: + self._do_quick_abort(entries) + else: + self._do_full_abort(entries) finally: self._journal = None self._releasefn(self, False) # notify failure of transaction self._releasefn = None # Help prevent cycles. + def _can_quick_abort(self, entries): + """False if any semantic content have been written on disk + + True if nothing, except temporary files has been writen on disk.""" + if entries: + return False + if self._backupentries: + return False + return True + + def _do_quick_abort(self, entries): + """(Silently) do a quick cleanup (see _can_quick_abort)""" + assert self._can_quick_abort(entries) + if self._backupjournal: + self._opener.unlink(self._backupjournal) + if self._journal: + self._opener.unlink(self._journal) + + def _do_full_abort(self, entries): + """(Noisily) rollback all the change introduced by the transaction""" + self._report(_(b"transaction abort!\n")) + try: + for cat in sorted(self._abortcallback): + self._abortcallback[cat](self) + # Prevent double usage and help clear cycles. + self._abortcallback = None + _playback( + self._journal, + self._report, + self._opener, + self._vfsmap, + entries, + self._backupentries, + False, + checkambigfiles=self._checkambigfiles, + ) + self._report(_(b"rollback completed\n")) + except BaseException as exc: + self._report(_(b"rollback failed - please run hg recover\n")) + self._report( + _(b"(failure reason: %s)\n") % stringutil.forcebytestr(exc) + ) + BAD_VERSION_MSG = _( b"journal was created by a different version of Mercurial\n"