diff mercurial/transaction.py @ 8294:48a382c23226

transaction: refactor transaction.abort and rollback to use the same code This adds a change to the way that abort is processed, as it will not continue truncating files beyond the first failure, otherwise the respective functionality is maintained, i.e. abort will not unlink files, but rollback will. Co-contributor: Sune Foldager <cryo@cyanite.org>
author Henrik Stuart <hg@hstuart.dk>
date Mon, 04 May 2009 15:31:57 +0200
parents 560af1bbfd6e
children c8e81f557da7
line wrap: on
line diff
--- a/mercurial/transaction.py	Mon May 04 13:47:12 2009 +0200
+++ b/mercurial/transaction.py	Mon May 04 15:31:57 2009 +0200
@@ -23,6 +23,23 @@
         return func(self, *args, **kwds)
     return _active
 
+def _playback(journal, report, opener, entries, unlink=True):
+    for f, o, ignore in entries:
+        if o or not unlink:
+            try:
+                opener(f, 'a').truncate(o)
+            except:
+                report(_("failed to truncate %s\n") % f)
+                raise
+        else:
+            try:
+                fn = opener(f).name
+                os.unlink(fn)
+            except OSError, inst:
+                if inst.errno != errno.ENOENT:
+                    raise
+    os.unlink(journal)
+
 class transaction(object):
     def __init__(self, report, opener, journal, after=None, createmode=None):
         self.journal = None
@@ -101,40 +118,21 @@
 
         self.report(_("transaction abort!\n"))
 
-        failed = False
-        for f, o, ignore in self.entries:
+        try:
             try:
-                self.opener(f, "a").truncate(o)
+                _playback(self.journal, self.report, self.opener, self.entries, False)
+                self.report(_("rollback completed\n"))
             except:
-                failed = True
-                self.report(_("failed to truncate %s\n") % f)
-
-        self.entries = []
-
-        if not failed:
-            os.unlink(self.journal)
-            self.report(_("rollback completed\n"))
-        else:
-            self.report(_("rollback failed - please run hg recover\n"))
-
-        self.journal = None
+                self.report(_("rollback failed - please run hg recover\n"))
+        finally:
+            self.journal = None
 
 
-def rollback(opener, file):
-    files = {}
+def rollback(opener, file, report):
+    entries = []
+
     for l in open(file).readlines():
         f, o = l.split('\0')
-        files[f] = int(o)
-    for f in files:
-        o = files[f]
-        if o:
-            opener(f, "a").truncate(int(o))
-        else:
-            try:
-                fn = opener(f).name
-                os.unlink(fn)
-            except OSError, inst:
-                if inst.errno != errno.ENOENT:
-                    raise
-    os.unlink(file)
+        entries.append((f, int(o), None))
 
+    _playback(file, report, opener, entries)