Mercurial > hg-stable
changeset 20967:984850270acb
unbundle: extract checkheads in its own function
We are going to refactor the unbundle function to have it working on
a local repository too. Having this function extracted will ease the process.
In the case of non-matching heads, the function now directly raises an
exception. The top level of the function is catching it.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Fri, 04 Apr 2014 17:15:25 -0700 |
parents | 63659b809021 |
children | 33d5fdd9bd99 |
files | mercurial/exchange.py mercurial/wireproto.py |
diffstat | 2 files changed, 46 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/exchange.py Mon Apr 07 18:10:50 2014 -0700 +++ b/mercurial/exchange.py Fri Apr 04 17:15:25 2014 -0700 @@ -611,3 +611,20 @@ temp.write(c) temp.seek(0) return bundle2.unbundle20(repo.ui, temp) + +class PushRaced(RuntimeError): + """An exception raised during unbunding that indicate a push race""" + +def check_heads(repo, their_heads, context): + """check if the heads of a repo have been modified + + Used by peer for unbundling. + """ + heads = repo.heads() + heads_hash = util.sha1(''.join(sorted(heads))).digest() + if not (their_heads == ['force'] or their_heads == heads or + their_heads == ['hashed', heads_hash]): + # someone else committed/pushed/unbundled while we + # were transferring data + raise PushRaced('repository changed while %s - ' + 'please try again' % context)
--- a/mercurial/wireproto.py Mon Apr 07 18:10:50 2014 -0700 +++ b/mercurial/wireproto.py Fri Apr 04 17:15:25 2014 -0700 @@ -9,7 +9,7 @@ from i18n import _ from node import bin, hex import changegroup as changegroupmod -import peer, error, encoding, util, store +import peer, error, encoding, util, store, exchange class abstractserverproto(object): @@ -754,46 +754,36 @@ def unbundle(repo, proto, heads): their_heads = decodelist(heads) - def check_heads(): - heads = repo.heads() - heads_hash = util.sha1(''.join(sorted(heads))).digest() - return (their_heads == ['force'] or their_heads == heads or - their_heads == ['hashed', heads_hash]) + try: + proto.redirect() - proto.redirect() + exchange.check_heads(repo, their_heads, 'preparing changes') - # fail early if possible - if not check_heads(): - return pusherr('repository changed while preparing changes - ' - 'please try again') - - # write bundle data to temporary file because it can be big - fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-') - fp = os.fdopen(fd, 'wb+') - r = 0 - try: - proto.getfile(fp) - lock = repo.lock() + # write bundle data to temporary file because it can be big + fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-') + fp = os.fdopen(fd, 'wb+') + r = 0 try: - if not check_heads(): - # someone else committed/pushed/unbundled while we - # were transferring data - return pusherr('repository changed while uploading changes - ' - 'please try again') - - # push can proceed - fp.seek(0) - gen = changegroupmod.readbundle(fp, None) - + proto.getfile(fp) + lock = repo.lock() try: - r = changegroupmod.addchangegroup(repo, gen, 'serve', - proto._client()) - except util.Abort, inst: - sys.stderr.write("abort: %s\n" % inst) + exchange.check_heads(repo, their_heads, 'uploading changes') + + # push can proceed + fp.seek(0) + gen = changegroupmod.readbundle(fp, None) + + try: + r = changegroupmod.addchangegroup(repo, gen, 'serve', + proto._client()) + except util.Abort, inst: + sys.stderr.write("abort: %s\n" % inst) + finally: + lock.release() + return pushres(r) + finally: - lock.release() - return pushres(r) - - finally: - fp.close() - os.unlink(tempname) + fp.close() + os.unlink(tempname) + except exchange.PushRaced, exc: + return pusherr(str(exc))