transaction: allow registering a temporary transaction file
During the transaction, files may be created to store or expose data
involved in the transaction (eg: changelog index data are written in
a 'changelog.i.a' for hooks). But we do not have an official way to
record such file creation and make sure they are cleaned up. The lack
of clean-up is currently okay because there is a single file involved
and a single producer/consumer.
However, as we want to expose more data (bookmarks, phases, obsmarker)
we need something more solid. The 'backupentries' mechanism could
handle that. Temporary files can be encoded as a backup of nothing
'('', <temporarypath>)'. We "need" to attach it to the same mechanism
as we use to be able to use temporary transaction files outside of
.'store/' and 'backupentries' is expected to gain such feature.
This changeset makes it clear that we should rename 'backupentries' to
something more generic.
--- a/mercurial/transaction.py Thu Nov 13 10:22:47 2014 +0000
+++ b/mercurial/transaction.py Wed Nov 05 09:27:08 2014 +0000
@@ -44,7 +44,7 @@
backupfiles = []
for f, b in backupentries:
- if b:
+ if f and b:
filepath = opener.join(f)
backuppath = opener.join(b)
try:
@@ -54,8 +54,9 @@
report(_("failed to recover %s\n") % f)
raise
else:
+ target = f or b
try:
- opener.unlink(f)
+ opener.unlink(target)
except (IOError, OSError), inst:
if inst.errno != errno.ENOENT:
raise
@@ -65,7 +66,8 @@
if opener.exists(backuppath):
opener.unlink(backuppath)
for f in backupfiles:
- opener.unlink(f)
+ if opener.exists(f):
+ opener.unlink(f)
class transaction(object):
def __init__(self, report, opener, journal, after=None, createmode=None,
@@ -99,6 +101,7 @@
# a list of ('path', 'backuppath') entries.
# if 'backuppath' is empty, no file existed at backup time
+ # if 'path' is empty, this is a temporary transaction file
self._backupentries = []
self._backupmap = {}
self._backupjournal = "%s.backupfiles" % journal
@@ -200,6 +203,15 @@
self._backupsfile.flush()
@active
+ def registertmp(self, tmpfile):
+ """register a temporary transaction file
+
+ Such file will be delete when the transaction exit (on both failure and
+ success).
+ """
+ self._addbackupentry(('', tmpfile))
+
+ @active
def addfilegenerator(self, genid, filenames, genfunc, order=0, vfs=None):
"""add a function to generates some files at transaction commit
@@ -342,6 +354,10 @@
return
self.file.close()
self._backupsfile.close()
+ # cleanup temporary files
+ for f, b in self._backupentries:
+ if not f and b and self.opener.exists(b):
+ self.opener.unlink(b)
self.entries = []
if self.after:
self.after()
@@ -350,7 +366,7 @@
if self.opener.isfile(self._backupjournal):
self.opener.unlink(self._backupjournal)
for _f, b in self._backupentries:
- if b:
+ if b and self.opener.exists(b):
self.opener.unlink(b)
self._backupentries = []
self.journal = None