strip: use the 'finally: tr.release' pattern during stripping stable
authorPierre-Yves David <pierre-yves.david@fb.com>
Sat, 08 Aug 2015 14:50:03 -0700
branchstable
changeset 26012 d815a5997576
parent 26000 9ac4e81b9659
child 26014 a5f62af29517
child 26025 ba8089433090
child 26045 1b3524cedf7b
strip: use the 'finally: tr.release' pattern during stripping The previous code, was calling 'abort' in all exception cases. This was wrong when an exception was raised by post-close callback on the transaction. Calling 'abort' on an already closed transaction resulted in a error, shadowing the original error. We now use the same pattern as everywhere else. 'tr.release()' will abort the transaction if we escape the scope without closing it. We add a test to make sure we do not regress.
mercurial/repair.py
tests/test-strip.t
--- a/mercurial/repair.py	Thu Aug 06 21:00:16 2015 -0400
+++ b/mercurial/repair.py	Sat Aug 08 14:50:03 2015 -0700
@@ -173,9 +173,8 @@
                 if troffset == 0:
                     repo.store.markremoved(file)
             tr.close()
-        except: # re-raises
-            tr.abort()
-            raise
+        finally:
+            tr.release()
 
         if saveheads or savebases:
             ui.note(_("adding branch\n"))
--- a/tests/test-strip.t	Thu Aug 06 21:00:16 2015 -0400
+++ b/tests/test-strip.t	Sat Aug 08 14:50:03 2015 -0700
@@ -826,3 +826,26 @@
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     mergeCD
   
+
+Error during post-close callback of the strip transaction
+(They should be gracefully handled and reported)
+
+  $ cat > ../crashstrip.py << EOF
+  > from mercurial import error
+  > def reposetup(ui, repo):
+  >     class crashstriprepo(repo.__class__):
+  >         def transaction(self, desc, *args, **kwargs):
+  >             tr = super(crashstriprepo, self).transaction(self, desc, *args, **kwargs)
+  >             if desc == 'strip':
+  >                 def crash(tra): raise error.Abort('boom')
+  >                 tr.addpostclose('crash', crash)
+  >             return tr
+  >     repo.__class__ = crashstriprepo
+  > EOF
+  $ hg strip tip --config extensions.crash=$TESTTMP/crashstrip.py
+  saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg (glob)
+  strip failed, full bundle stored in '$TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg'
+  abort: boom
+  [255]
+
+