mercurial/transaction.py
changeset 8294 48a382c23226
parent 8290 560af1bbfd6e
child 8363 c8e81f557da7
--- 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)