Show More
@@ -145,7 +145,7 b' import struct' | |||||
145 | import urllib |
|
145 | import urllib | |
146 | import string |
|
146 | import string | |
147 |
|
147 | |||
148 | import changegroup |
|
148 | import changegroup, error | |
149 | from i18n import _ |
|
149 | from i18n import _ | |
150 |
|
150 | |||
151 | _pack = struct.pack |
|
151 | _pack = struct.pack | |
@@ -730,7 +730,7 b' def handlechangegroup(op, inpart):' | |||||
730 | h = inpart.read(20) |
|
730 | h = inpart.read(20) | |
731 | assert not h |
|
731 | assert not h | |
732 | if heads != op.repo.heads(): |
|
732 | if heads != op.repo.heads(): | |
733 |
raise e |
|
733 | raise error.PushRaced() | |
734 |
|
734 | |||
735 | @parthandler('b2x:output') |
|
735 | @parthandler('b2x:output') | |
736 | def handleoutput(op, inpart): |
|
736 | def handleoutput(op, inpart): |
@@ -94,3 +94,7 b' class SignalInterrupt(KeyboardInterrupt)' | |||||
94 |
|
94 | |||
95 | class SignatureError(Exception): |
|
95 | class SignatureError(Exception): | |
96 | pass |
|
96 | pass | |
|
97 | ||||
|
98 | class PushRaced(RuntimeError): | |||
|
99 | """An exception raised during unbundling that indicate a push race""" | |||
|
100 |
@@ -8,7 +8,7 b'' | |||||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | from node import hex, nullid |
|
9 | from node import hex, nullid | |
10 | import errno, urllib |
|
10 | import errno, urllib | |
11 | import util, scmutil, changegroup, base85 |
|
11 | import util, scmutil, changegroup, base85, error | |
12 | import discovery, phases, obsolete, bookmarks, bundle2 |
|
12 | import discovery, phases, obsolete, bookmarks, bundle2 | |
13 |
|
13 | |||
14 | def readbundle(ui, fh, fname, vfs=None): |
|
14 | def readbundle(ui, fh, fname, vfs=None): | |
@@ -708,9 +708,6 b' def _getbundleextrapart(bundler, repo, s' | |||||
708 | """hook function to let extensions add parts to the requested bundle""" |
|
708 | """hook function to let extensions add parts to the requested bundle""" | |
709 | pass |
|
709 | pass | |
710 |
|
710 | |||
711 | class PushRaced(RuntimeError): |
|
|||
712 | """An exception raised during unbundling that indicate a push race""" |
|
|||
713 |
|
||||
714 | def check_heads(repo, their_heads, context): |
|
711 | def check_heads(repo, their_heads, context): | |
715 | """check if the heads of a repo have been modified |
|
712 | """check if the heads of a repo have been modified | |
716 |
|
713 | |||
@@ -722,8 +719,8 b' def check_heads(repo, their_heads, conte' | |||||
722 | their_heads == ['hashed', heads_hash]): |
|
719 | their_heads == ['hashed', heads_hash]): | |
723 | # someone else committed/pushed/unbundled while we |
|
720 | # someone else committed/pushed/unbundled while we | |
724 | # were transferring data |
|
721 | # were transferring data | |
725 | raise PushRaced('repository changed while %s - ' |
|
722 | raise error.PushRaced('repository changed while %s - ' | |
726 | 'please try again' % context) |
|
723 | 'please try again' % context) | |
727 |
|
724 | |||
728 | def unbundle(repo, cg, heads, source, url): |
|
725 | def unbundle(repo, cg, heads, source, url): | |
729 | """Apply a bundle to a repo. |
|
726 | """Apply a bundle to a repo. |
@@ -133,7 +133,7 b' class localpeer(peer.peerrepository):' | |||||
133 | stream = util.chunkbuffer(ret.getchunks()) |
|
133 | stream = util.chunkbuffer(ret.getchunks()) | |
134 | ret = bundle2.unbundle20(self.ui, stream) |
|
134 | ret = bundle2.unbundle20(self.ui, stream) | |
135 | return ret |
|
135 | return ret | |
136 |
except e |
|
136 | except error.PushRaced, exc: | |
137 | raise error.ResponseError(_('push failed:'), exc.message) |
|
137 | raise error.ResponseError(_('push failed:'), exc.message) | |
138 |
|
138 | |||
139 | def lock(self): |
|
139 | def lock(self): |
@@ -826,5 +826,5 b' def unbundle(repo, proto, heads):' | |||||
826 | else: |
|
826 | else: | |
827 | sys.stderr.write("abort: %s\n" % inst) |
|
827 | sys.stderr.write("abort: %s\n" % inst) | |
828 | return pushres(0) |
|
828 | return pushres(0) | |
829 |
except e |
|
829 | except error.PushRaced, exc: | |
830 | return pusherr(str(exc)) |
|
830 | return pusherr(str(exc)) |
@@ -15,6 +15,7 b' Create an extension to test bundle2 API' | |||||
15 | > from mercurial import scmutil |
|
15 | > from mercurial import scmutil | |
16 | > from mercurial import discovery |
|
16 | > from mercurial import discovery | |
17 | > from mercurial import changegroup |
|
17 | > from mercurial import changegroup | |
|
18 | > from mercurial import error | |||
18 | > cmdtable = {} |
|
19 | > cmdtable = {} | |
19 | > command = cmdutil.command(cmdtable) |
|
20 | > command = cmdutil.command(cmdtable) | |
20 | > |
|
21 | > | |
@@ -59,6 +60,7 b' Create an extension to test bundle2 API' | |||||
59 | > ('', 'unknown', False, 'include an unknown mandatory part in the bundle'), |
|
60 | > ('', 'unknown', False, 'include an unknown mandatory part in the bundle'), | |
60 | > ('', 'parts', False, 'include some arbitrary parts to the bundle'), |
|
61 | > ('', 'parts', False, 'include some arbitrary parts to the bundle'), | |
61 | > ('', 'reply', False, 'produce a reply bundle'), |
|
62 | > ('', 'reply', False, 'produce a reply bundle'), | |
|
63 | > ('', 'pushrace', False, 'includes a check:head part with unknown nodes'), | |||
62 | > ('r', 'rev', [], 'includes those changeset in the bundle'),], |
|
64 | > ('r', 'rev', [], 'includes those changeset in the bundle'),], | |
63 | > '[OUTPUTFILE]') |
|
65 | > '[OUTPUTFILE]') | |
64 | > def cmdbundle2(ui, repo, path=None, **opts): |
|
66 | > def cmdbundle2(ui, repo, path=None, **opts): | |
@@ -75,6 +77,10 b' Create an extension to test bundle2 API' | |||||
75 | > capsstring = 'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville' |
|
77 | > capsstring = 'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville' | |
76 | > bundler.addpart(bundle2.bundlepart('b2x:replycaps', data=capsstring)) |
|
78 | > bundler.addpart(bundle2.bundlepart('b2x:replycaps', data=capsstring)) | |
77 | > |
|
79 | > | |
|
80 | > if opts['pushrace']: | |||
|
81 | > dummynode = '01234567890123456789' | |||
|
82 | > bundler.addpart(bundle2.bundlepart('b2x:check:heads', data=dummynode)) | |||
|
83 | > | |||
78 | > revs = opts['rev'] |
|
84 | > revs = opts['rev'] | |
79 | > if 'rev' in opts: |
|
85 | > if 'rev' in opts: | |
80 | > revs = scmutil.revrange(repo, opts['rev']) |
|
86 | > revs = scmutil.revrange(repo, opts['rev']) | |
@@ -132,6 +138,8 b' Create an extension to test bundle2 API' | |||||
132 | > tr.close() |
|
138 | > tr.close() | |
133 | > except KeyError, exc: |
|
139 | > except KeyError, exc: | |
134 | > raise util.Abort('missing support for %s' % exc) |
|
140 | > raise util.Abort('missing support for %s' % exc) | |
|
141 | > except error.PushRaced, exc: | |||
|
142 | > raise util.Abort('push race') | |||
135 | > finally: |
|
143 | > finally: | |
136 | > if tr is not None: |
|
144 | > if tr is not None: | |
137 | > tr.release() |
|
145 | > tr.release() | |
@@ -601,6 +609,15 b' Unbundle the reply to get the output:' | |||||
601 | remote: replying to ping request (id 6) |
|
609 | remote: replying to ping request (id 6) | |
602 | 0 unread bytes |
|
610 | 0 unread bytes | |
603 |
|
611 | |||
|
612 | Test push race detection | |||
|
613 | ||||
|
614 | $ hg bundle2 --pushrace ../part-race.hg2 | |||
|
615 | ||||
|
616 | $ hg unbundle2 < ../part-race.hg2 | |||
|
617 | 0 unread bytes | |||
|
618 | abort: push race | |||
|
619 | [255] | |||
|
620 | ||||
604 | Support for changegroup |
|
621 | Support for changegroup | |
605 | =================================== |
|
622 | =================================== | |
606 |
|
623 |
General Comments 0
You need to be logged in to leave comments.
Login now