[PATCH] transaction: support for callbacks during abort

Gregory Szorc gregory.szorc at gmail.com
Wed Jan 7 06:00:18 UTC 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1420610193 28800
#      Tue Jan 06 21:56:33 2015 -0800
# Node ID 5affbb31eea2a1034bc73ee20182880adcc9af36
# Parent  b9d06fa10ef29c012d48bd4f3c93fd7bf1347d40
transaction: support for callbacks during abort

Previous transaction work added callbacks to be called during regular
transaction commit/close. As part of refactoring Mozilla's pushlog
extension (an extension that opens a SQLite database and tries to tie
its transaction semantics to Mercurial's transaction), I discovered that
the new transaction APIs were insufficient to avoid monkeypatching
transaction instance internals. Adding a callback that is called during
transaction abort removes the necessity for monkeypatching and completes
the API.

diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -135,8 +135,10 @@ class transaction(object):
         # holds callback to call when writing the transaction
         self._finalizecallback = {}
         # hold callback for post transaction close
         self._postclosecallback = {}
+        # holds callbacks to call during abort
+        self._abortcallback = {}
 
     def __del__(self):
         if self.journal:
             self._abort()
@@ -360,8 +362,19 @@ class transaction(object):
         """
         self._postclosecallback[category] = callback
 
     @active
+    def addabort(self, category, callback):
+        """add a callback to be called when the transaction is aborted.
+
+        The transaction will be given as the first argument to the callback.
+
+        Category is a unique identifier to allow overwriting an old callback
+        with a newer callback.
+        """
+        self._abortcallback[category] = callback
+
+    @active
     def close(self):
         '''commit the transaction'''
         if self.count == 1:
             self._generatefiles()
@@ -442,8 +455,10 @@ class transaction(object):
 
             self.report(_("transaction abort!\n"))
 
             try:
+                for cat in sorted(self._abortcallback):
+                    self._abortcallback[cat](self)
                 _playback(self.journal, self.report, self.opener, self._vfsmap,
                           self.entries, self._backupentries, False)
                 self.report(_("rollback completed\n"))
             except Exception:


More information about the Mercurial-devel mailing list