Comments
Patch
@@ -42,32 +42,34 @@ def _playback(journal, report, opener, e
if inst.errno != errno.ENOENT:
raise
backupfiles = []
for f, b in backupentries:
- if b:
+ if f and b:
filepath = opener.join(f)
backuppath = opener.join(b)
try:
util.copyfile(backuppath, filepath)
backupfiles.append(b)
except IOError:
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
opener.unlink(journal)
backuppath = "%s.backupfiles" % journal
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,
onclose=None, onabort=None):
"""Begin a new transaction
@@ -97,10 +99,11 @@ class transaction(object):
self.hookargs = {}
self.file = opener.open(self.journal, "w")
# 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
self._backupsfile = opener.open(self._backupjournal, 'w')
self._backupsfile.write('%d\n' % version)
@@ -198,10 +201,19 @@ class transaction(object):
self._backupmap[file] = len(self._backupentries) - 1
self._backupsfile.write("%s\0%s\n" % entry)
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
The `genfunc` argument is a function capable of generating proper
content of each entry in the `filename` tuple.
@@ -340,19 +352,23 @@ class transaction(object):
self.count -= 1
if self.count != 0:
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()
if self.opener.isfile(self.journal):
self.opener.unlink(self.journal)
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
# run post close action
categories = sorted(self._postclosecallback)