Patchwork [3,of,5,V2] transaction: add a validation stage

login
register
mail settings
Submitter Pierre-Yves David
Date March 12, 2015, 1:33 a.m.
Message ID <b72c668ed29e918777d5.1426123997@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/8016/
State Accepted
Commit ef22cfff705254834c454b347385f1cbdae010c7
Headers show

Comments

Pierre-Yves David - March 12, 2015, 1:33 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1425966216 25200
#      Mon Mar 09 22:43:36 2015 -0700
# Node ID b72c668ed29e918777d54387f8fefb988cf2e944
# Parent  825a2a88508573b69fc5b762e3a97c4e0b1300a2
transaction: add a validation stage

The 'transaction' object can now be fed a 'validator' function. This function
will be run right before the transaction is closed to validate its content. The
target usage is hooks. The validation function is expected to raise an exception
when it wants to abort the transaction.

This only introduce the idea with a default no-op validator. Actual usage is in
the next changeset.

Patch

diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -81,11 +81,11 @@  def _playback(journal, report, opener, v
         # only pure backup file remains, it is sage to ignore any error
         pass
 
 class transaction(object):
     def __init__(self, report, opener, vfsmap, journalname, undoname=None,
-                 after=None, createmode=None):
+                 after=None, createmode=None, validator=None):
         """Begin a new transaction
 
         Begins a new transaction that allows rolling back writes in the event of
         an exception.
 
@@ -105,10 +105,16 @@  class transaction(object):
         self.entries = []
         self.map = {}
         self.journal = journalname
         self.undoname = undoname
         self._queue = []
+        # A callback to validate transaction content before closing it.
+        # should raise exception is anything is wrong.
+        # target user is repository hooks.
+        if validator is None:
+            validator = lambda tr: None
+        self.validator = validator
         # a dict of arguments to be passed to hooks
         self.hookargs = {}
         self.file = opener.open(self.journal, "w")
 
         # a list of ('location', 'path', 'backuppath', cache) entries.
@@ -376,10 +382,11 @@  class transaction(object):
 
     @active
     def close(self):
         '''commit the transaction'''
         if self.count == 1:
+            self.validator(self)  # will raise exception if needed
             self._generatefiles()
             categories = sorted(self._finalizecallback)
             for cat in categories:
                 self._finalizecallback[cat](self)