bundle2: make it possible have a global transaction for the unbundling
We use the `gettransaction` method approach already used for pull. We
need this because we do not know beforehand if the bundle needs a
transaction to be created. And (1) we do not want to create a
transaction for nothing. (2) Some bundle2 bundles may be read-only and
do not require any lock or transaction to be held.
--- a/mercurial/bundle2.py Fri Apr 04 17:47:19 2014 -0500
+++ b/mercurial/bundle2.py Wed Apr 02 23:56:49 2014 -0700
@@ -238,12 +238,23 @@
* a way to construct a bundle response when applicable.
"""
- def __init__(self, repo):
+ def __init__(self, repo, transactiongetter):
self.repo = repo
self.ui = repo.ui
self.records = unbundlerecords()
+ self.gettransaction = transactiongetter
-def processbundle(repo, unbundler):
+class TransactionUnavailable(RuntimeError):
+ pass
+
+def _notransaction():
+ """default method to get a transaction while processing a bundle
+
+ Raise an exception to highlight the fact that no transaction was expected
+ to be created"""
+ raise TransactionUnavailable()
+
+def processbundle(repo, unbundler, transactiongetter=_notransaction):
"""This function process a bundle, apply effect to/from a repo
It iterates over each part then searches for and uses the proper handling
@@ -254,7 +265,7 @@
Unknown Mandatory part will abort the process.
"""
- op = bundleoperation(repo)
+ op = bundleoperation(repo, transactiongetter)
# todo:
# - replace this is a init function soon.
# - exception catching
@@ -532,6 +543,12 @@
This is a very early implementation that will massive rework before being
inflicted to any end-user.
"""
+ # Make sure we trigger a transaction creation
+ #
+ # The addchangegroup function will get a transaction object by itself, but
+ # we need to make sure we trigger the creation of a transaction object used
+ # for the whole processing scope.
+ op.gettransaction()
data = StringIO.StringIO(part.data)
data.seek(0)
cg = changegroup.readbundle(data, 'bundle2part')
--- a/tests/test-bundle2.t Fri Apr 04 17:47:19 2014 -0500
+++ b/tests/test-bundle2.t Wed Apr 02 23:56:49 2014 -0700
@@ -96,13 +96,18 @@
> def cmdunbundle2(ui, repo):
> """process a bundle2 stream from stdin on the current repo"""
> try:
+ > tr = None
> lock = repo.lock()
+ > tr = repo.transaction('processbundle')
> try:
> unbundler = bundle2.unbundle20(ui, sys.stdin)
- > op = bundle2.processbundle(repo, unbundler)
+ > op = bundle2.processbundle(repo, unbundler, lambda: tr)
+ > tr.close()
> except KeyError, exc:
> raise util.Abort('missing support for %s' % exc)
> finally:
+ > if tr is not None:
+ > tr.release()
> lock.release()
> remains = sys.stdin.read()
> ui.write('%i unread bytes\n' % len(remains))