Mercurial > public > mercurial-scm > hg
comparison mercurial/exchange.py @ 21061:62d35f251c60
bundle2: allow using bundle2 for push
We now support bundle2 for local push. The unbundle function has to detect
which version of the bundle to use since the return type is different.
Note that push error handling is currently nonexistent. This is one of the
reasons why bundle2 is still disabled by default.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Thu, 10 Apr 2014 10:53:43 -0700 |
parents | 6c383c871fdb |
children | e7c0a65a5c9c |
comparison
equal
deleted
inserted
replaced
21060:0bea9db7543b | 21061:62d35f251c60 |
---|---|
104 _pushdiscovery(pushop) | 104 _pushdiscovery(pushop) |
105 if _pushcheckoutgoing(pushop): | 105 if _pushcheckoutgoing(pushop): |
106 pushop.repo.prepushoutgoinghooks(pushop.repo, | 106 pushop.repo.prepushoutgoinghooks(pushop.repo, |
107 pushop.remote, | 107 pushop.remote, |
108 pushop.outgoing) | 108 pushop.outgoing) |
109 _pushchangeset(pushop) | 109 if pushop.remote.capable('bundle2'): |
110 _pushbundle2(pushop) | |
111 else: | |
110 _pushcomputecommonheads(pushop) | 112 _pushcomputecommonheads(pushop) |
111 _pushsyncphase(pushop) | 113 _pushsyncphase(pushop) |
112 _pushobsolete(pushop) | 114 _pushobsolete(pushop) |
113 finally: | 115 finally: |
114 if lock is not None: | 116 if lock is not None: |
169 pushop.remoteheads, | 171 pushop.remoteheads, |
170 pushop.newbranch, | 172 pushop.newbranch, |
171 bool(pushop.incoming), | 173 bool(pushop.incoming), |
172 newbm) | 174 newbm) |
173 return True | 175 return True |
176 | |
177 def _pushbundle2(pushop): | |
178 """push data to the remote using bundle2 | |
179 | |
180 The only currently supported type of data is changegroup but this will | |
181 evolve in the future.""" | |
182 # Send known head to the server for race detection. | |
183 bundler = bundle2.bundle20(pushop.ui) | |
184 if not pushop.force: | |
185 part = bundle2.bundlepart('CHECK:HEADS', data=iter(pushop.remoteheads)) | |
186 bundler.addpart(part) | |
187 # add the changegroup bundle | |
188 cg = changegroup.getlocalbundle(pushop.repo, 'push', pushop.outgoing) | |
189 def cgchunks(cg=cg): | |
190 yield 'HG10UN' | |
191 for c in cg.getchunks(): | |
192 yield c | |
193 cgpart = bundle2.bundlepart('CHANGEGROUP', data=cgchunks()) | |
194 bundler.addpart(cgpart) | |
195 stream = util.chunkbuffer(bundler.getchunks()) | |
196 sent = bundle2.unbundle20(pushop.repo.ui, stream) | |
197 reply = pushop.remote.unbundle(sent, ['force'], 'push') | |
198 try: | |
199 op = bundle2.processbundle(pushop.repo, reply) | |
200 except KeyError, exc: | |
201 raise util.Abort('missing support for %s' % exc) | |
202 cgreplies = op.records.getreplies(cgpart.id) | |
203 assert len(cgreplies['changegroup']) == 1 | |
204 pushop.ret = cgreplies['changegroup'][0]['return'] | |
174 | 205 |
175 def _pushchangeset(pushop): | 206 def _pushchangeset(pushop): |
176 """Make the actual push of changeset bundle to remote repo""" | 207 """Make the actual push of changeset bundle to remote repo""" |
177 outgoing = pushop.outgoing | 208 outgoing = pushop.outgoing |
178 unbundle = pushop.remote.capable('unbundle') | 209 unbundle = pushop.remote.capable('unbundle') |
635 mechanism to check that no push race occurred between the creation of the | 666 mechanism to check that no push race occurred between the creation of the |
636 bundle and its application. | 667 bundle and its application. |
637 | 668 |
638 If the push was raced as PushRaced exception is raised.""" | 669 If the push was raced as PushRaced exception is raised.""" |
639 r = 0 | 670 r = 0 |
671 # need a transaction when processing a bundle2 stream | |
672 tr = None | |
640 lock = repo.lock() | 673 lock = repo.lock() |
641 try: | 674 try: |
642 check_heads(repo, heads, 'uploading changes') | 675 check_heads(repo, heads, 'uploading changes') |
643 # push can proceed | 676 # push can proceed |
644 r = changegroup.addchangegroup(repo, cg, source, url) | 677 if util.safehasattr(cg, 'params'): |
678 tr = repo.transaction('unbundle') | |
679 ret = bundle2.processbundle(repo, cg, lambda: tr) | |
680 tr.close() | |
681 stream = util.chunkbuffer(ret.reply.getchunks()) | |
682 r = bundle2.unbundle20(repo.ui, stream) | |
683 else: | |
684 r = changegroup.addchangegroup(repo, cg, source, url) | |
645 finally: | 685 finally: |
686 if tr is not None: | |
687 tr.release() | |
646 lock.release() | 688 lock.release() |
647 return r | 689 return r |