D392: util: add base class for transactional context managers
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Tue Aug 15 01:59:16 EDT 2017
martinvonz updated this revision to Diff 914.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D392?vs=890&id=914
REVISION DETAIL
https://phab.mercurial-scm.org/D392
AFFECTED FILES
mercurial/dirstateguard.py
mercurial/exchange.py
mercurial/transaction.py
mercurial/util.py
CHANGE DETAILS
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -15,6 +15,7 @@
from __future__ import absolute_import
+import abc
import bz2
import calendar
import codecs
@@ -592,6 +593,31 @@
for k, v in src:
self[k] = v
+class transactional(object):
+ """Base class for making a transactional type into a context manager."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def close(self):
+ """Successfully closes the transaction."""
+
+ @abc.abstractmethod
+ def release(self):
+ """Marks the end of the transaction.
+
+ If the transaction has not been closed, it will be aborted.
+ """
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ try:
+ if exc_type is None:
+ self.close()
+ finally:
+ self.release()
+
@contextlib.contextmanager
def acceptintervention(tr=None):
"""A context manager that closes the transaction on InterventionRequired
diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -101,7 +101,7 @@
# only pure backup file remains, it is sage to ignore any error
pass
-class transaction(object):
+class transaction(util.transactional):
def __init__(self, report, opener, vfsmap, journalname, undoname=None,
after=None, createmode=None, validator=None, releasefn=None,
checkambigfiles=None):
@@ -376,16 +376,6 @@
if self.count > 0 and self.usages == 0:
self._abort()
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- try:
- if exc_type is None:
- self.close()
- finally:
- self.release()
-
def running(self):
return self.count > 0
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1168,7 +1168,7 @@
# deprecated; talk to trmanager directly
return self.trmanager.transaction()
-class transactionmanager(object):
+class transactionmanager(util.transactional):
"""An object to manage the life cycle of a transaction
It creates the transaction on demand and calls the appropriate hooks when
diff --git a/mercurial/dirstateguard.py b/mercurial/dirstateguard.py
--- a/mercurial/dirstateguard.py
+++ b/mercurial/dirstateguard.py
@@ -11,9 +11,10 @@
from . import (
error,
+ util,
)
-class dirstateguard(object):
+class dirstateguard(util.transactional):
'''Restore dirstate at unexpected failure.
At the construction, this class does:
@@ -43,16 +44,6 @@
# ``release(tr, ....)``.
self._abort()
- def __enter__(self):
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- try:
- if exc_type is None:
- self.close()
- finally:
- self.release()
-
def close(self):
if not self._active: # already inactivated
msg = (_("can't close already inactivated backup: %s")
To: martinvonz, #hg-reviewers, indygreg
Cc: indygreg, mercurial-devel
More information about the Mercurial-devel
mailing list