transaction: support for callbacks during abort
authorGregory Szorc <gregory.szorc@gmail.com>
Tue, 06 Jan 2015 21:56:33 -0800
changeset 23764 d486e52352e8
parent 23763 7ad155e13f0f
child 23765 537a2669a113
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.
mercurial/transaction.py
--- a/mercurial/transaction.py	Mon Dec 15 14:11:19 2014 -0800
+++ b/mercurial/transaction.py	Tue Jan 06 21:56:33 2015 -0800
@@ -136,6 +136,8 @@
         self._finalizecallback = {}
         # hold callback for post transaction close
         self._postclosecallback = {}
+        # holds callbacks to call during abort
+        self._abortcallback = {}
 
     def __del__(self):
         if self.journal:
@@ -361,6 +363,17 @@
         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:
@@ -443,6 +456,8 @@
             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"))