transaction: add a file generation mechanism
authorPierre-Yves David <pierre-yves.david@fb.com>
Thu, 07 Aug 2014 14:40:02 -0700
changeset 22078 feb4797c676e
parent 22077 2990ce46fc2d
child 22079 5dcc58649b1a
transaction: add a file generation mechanism A new `transaction.addfilegenerator` function is added. It allows external code to register files to be generated. See inline documentation for details. It is important to gather all file creation logic on the transaction as at some point we'll want to mimic the "pre-transaction-commit" logic that we use for revlog. I'm refering to the logic that lets hooks see the result of the transaction before it actually gets committed.
mercurial/transaction.py
--- a/mercurial/transaction.py	Thu Aug 07 10:54:17 2014 -0700
+++ b/mercurial/transaction.py	Thu Aug 07 14:40:02 2014 -0700
@@ -96,6 +96,9 @@
             opener.chmod(self.journal, createmode & 0666)
             opener.chmod(self.backupjournal, createmode & 0666)
 
+        # hold file generations to be performed on commit
+        self._filegenerators = {}
+
     def __del__(self):
         if self.journal:
             self._abort()
@@ -173,6 +176,28 @@
         self.backupsfile.flush()
 
     @active
+    def addfilegenerator(self, genid, filenames, genfunc, order=0):
+        """add a function to generates some files at transaction commit
+
+        The `genfunc` argument is a function capable of generating proper
+        content of each entry in the `filename` tuple.
+
+        At transaction close time, `genfunc` will be called with one file
+        object argument per entries in `filenames`.
+
+        The transaction itself is responsible for the backup, creation and
+        final write of such file.
+
+        The `genid` argument is used to ensure the same set of file is only
+        generated once. Call to `addfilegenerator` for a `genid` already
+        present will overwrite the old entry.
+
+        The `order` argument may be used to control the order in which multiple
+        generator will be executed.
+        """
+        self._filegenerators[genid] = (order, filenames, genfunc)
+
+    @active
     def find(self, file):
         if file in self.map:
             return self.entries[self.map[file]]
@@ -213,6 +238,18 @@
     @active
     def close(self):
         '''commit the transaction'''
+        # write files registered for generation
+        for order, filenames, genfunc in sorted(self._filegenerators.values()):
+            files = []
+            try:
+                for name in filenames:
+                    self.addbackup(name)
+                    files.append(self.opener(name, 'w', atomictemp=True))
+                genfunc(*files)
+            finally:
+                for f in files:
+                    f.close()
+
         if self.count == 1 and self.onclose is not None:
             self.onclose()