diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -624,7 +624,7 @@ class localrepository(repo.repository):
         try:
             if os.path.exists(self.sjoin("journal")):
                 self.ui.status(_("rolling back interrupted transaction\n"))
-                transaction.rollback(self.sopener, self.sjoin("journal"))
+                transaction.rollback(self.sopener, self.sjoin("journal"), self.ui.warn)
                 self.invalidate()
                 return True
             else:
@@ -640,7 +640,7 @@ class localrepository(repo.repository):
             lock = self.lock()
             if os.path.exists(self.sjoin("undo")):
                 self.ui.status(_("rolling back last transaction\n"))
-                transaction.rollback(self.sopener, self.sjoin("undo"))
+                transaction.rollback(self.sopener, self.sjoin("undo"), self.ui.warn)
                 util.rename(self.join("undo.dirstate"), self.join("dirstate"))
                 try:
                     branch = self.opener("undo.branch").read()
diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -23,6 +23,23 @@ def active(func):
         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 @@ class transaction(object):
 
         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)
diff --git a/tests/test-repair-strip.out b/tests/test-repair-strip.out
--- a/tests/test-repair-strip.out
+++ b/tests/test-repair-strip.out
@@ -17,8 +17,9 @@ checking files
  b@?: rev 1 points to nonexistent changeset 2
  (expected 1)
  b@?: 736c29771fba not in manifests
+warning: orphan revlog 'data/c.i'
 2 files, 2 changesets, 3 total revisions
-1 warnings encountered!
+2 warnings encountered!
 2 integrity errors encountered!
 % journal contents
 00changelog.i
@@ -63,15 +64,15 @@ checking manifests
  manifest@?: rev 2 points to nonexistent changeset 2
  manifest@?: rev 3 points to nonexistent changeset 3
 crosschecking files in changesets and manifests
- c@?: in manifest but not in changeset
+ c@3: in manifest but not in changeset
 checking files
- b@2: 736c29771fba in manifests not found
- data/c.i@?: missing revlog!
- ?: empty or missing c
- c@3: 149da44f2a4e in manifests not found
-3 files, 2 changesets, 2 total revisions
-7 integrity errors encountered!
-(first damaged changeset appears to be 2)
+ b@?: rev 1 points to nonexistent changeset 2
+ (expected 1)
+ c@?: rev 0 points to nonexistent changeset 3
+3 files, 2 changesets, 4 total revisions
+1 warnings encountered!
+5 integrity errors encountered!
+(first damaged changeset appears to be 3)
 % journal contents
 00changelog.i
 00manifest.i