bundle2: also save output when error happens during part processing stable
authorPierre-Yves David <pierre-yves.david@fb.com>
Thu, 23 Apr 2015 16:36:18 +0100
branchstable
changeset 24851 df0ce98c882f
parent 24850 6b81309d15a7
child 24852 515cd710df95
bundle2: also save output when error happens during part processing Until this changeset, we were only able to save output if an error happened during the 'transaction.close()' phase. If the 'processbundle' call raised an exception, the 'bundleoperation' object was never returned, so the reply bundle was never accessible and no output could be salvaged. We introduce a quick (but not very elegant) fix to gain access to any reply created during the processing. This conclude this output related series. We should hopefully be able client-side to see the whole server output, in a proper order. The code is now complex enough that a refactoring of it would make sense on default.
mercurial/bundle2.py
mercurial/exchange.py
tests/test-bundle2-exchange.t
--- a/mercurial/bundle2.py	Thu Apr 23 14:54:45 2015 +0100
+++ b/mercurial/bundle2.py	Thu Apr 23 16:36:18 2015 +0100
@@ -285,7 +285,7 @@
     to be created"""
     raise TransactionUnavailable()
 
-def processbundle(repo, unbundler, transactiongetter=None):
+def processbundle(repo, unbundler, transactiongetter=None, op=None):
     """This function process a bundle, apply effect to/from a repo
 
     It iterates over each part then searches for and uses the proper handling
@@ -295,10 +295,16 @@
     before final usage.
 
     Unknown Mandatory part will abort the process.
+
+    It is temporarily possible to provide a prebuilt bundleoperation to the
+    function. This is used to ensure output is properly propagated in case of
+    an error during the unbundling. This output capturing part will likely be
+    reworked and this ability will probably go away in the process.
     """
-    if transactiongetter is None:
-        transactiongetter = _notransaction
-    op = bundleoperation(repo, transactiongetter)
+    if op is None:
+        if transactiongetter is None:
+            transactiongetter = _notransaction
+        op = bundleoperation(repo, transactiongetter)
     # todo:
     # - replace this is a init function soon.
     # - exception catching
--- a/mercurial/exchange.py	Thu Apr 23 14:54:45 2015 +0100
+++ b/mercurial/exchange.py	Thu Apr 23 16:36:18 2015 +0100
@@ -1297,11 +1297,15 @@
                 tr.hookargs['source'] = source
                 tr.hookargs['url'] = url
                 tr.hookargs['bundle2'] = '1'
-                r = bundle2.processbundle(repo, cg, lambda: tr).reply
-                if r is not None:
-                    repo.ui.pushbuffer(error=True, subproc=True)
-                    def recordout(output):
-                        r.newpart('output', data=output, mandatory=False)
+                op = bundle2.bundleoperation(repo, lambda: tr)
+                try:
+                    r = bundle2.processbundle(repo, cg, op=op)
+                finally:
+                    r = op.reply
+                    if r is not None:
+                        repo.ui.pushbuffer(error=True, subproc=True)
+                        def recordout(output):
+                            r.newpart('output', data=output, mandatory=False)
                 tr.close()
             except Exception, exc:
                 exc.duringunbundle2 = True
--- a/tests/test-bundle2-exchange.t	Thu Apr 23 14:54:45 2015 +0100
+++ b/tests/test-bundle2-exchange.t	Thu Apr 23 16:36:18 2015 +0100
@@ -619,3 +619,51 @@
   $ ls -1 other/.hg/store/00changelog.i*
   other/.hg/store/00changelog.i
 
+Check error from hook during the unbundling process itself
+
+  $ cat << EOF >> $HGRCPATH
+  > pretxnchangegroup = echo "Fail early!"; false
+  > EOF
+  $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
+  $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
+  $ cat other.pid >> $DAEMON_PIDS
+
+  $ hg -R main push other -r e7ec4e813ba6
+  pushing to other
+  searching for changes
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 1 changes to 1 files
+  remote: Fail early!
+  remote: transaction abort!
+  remote: Cleaning up the mess...
+  remote: rollback completed
+  abort: pretxnchangegroup hook exited with status 1
+  [255]
+  $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
+  pushing to ssh://user@dummy/other
+  searching for changes
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 1 changes to 1 files
+  remote: Fail early!
+  remote: transaction abort!
+  remote: Cleaning up the mess...
+  remote: rollback completed
+  abort: pretxnchangegroup hook exited with status 1
+  [255]
+  $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
+  pushing to http://localhost:$HGPORT2/
+  searching for changes
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 1 changes to 1 files
+  remote: Fail early!
+  remote: transaction abort!
+  remote: Cleaning up the mess...
+  remote: rollback completed
+  abort: pretxnchangegroup hook exited with status 1
+  [255]