Mercurial > hg
comparison mercurial/bundle2.py @ 24686:e0e28e910fa3
bundle2: rename format, parts and config to final names
It is finally time to freeze the bundle2 format! To do so we:
- rename HG2Y to HG20,
- drop "b2x:" prefix from all part names,
- rename capability to "bundle2-exp" to "bundle2"
- rename the hook flag from 'bundle2-exp' to 'bundle2'
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Thu, 09 Apr 2015 16:25:48 -0400 |
parents | 5cac3accdaa1 |
children | c00e4338fa4b |
comparison
equal
deleted
inserted
replaced
24685:b3d78d82d84c | 24686:e0e28e910fa3 |
---|---|
356 handler(op, part) | 356 handler(op, part) |
357 finally: | 357 finally: |
358 if output is not None: | 358 if output is not None: |
359 output = op.ui.popbuffer() | 359 output = op.ui.popbuffer() |
360 if output: | 360 if output: |
361 outpart = op.reply.newpart('b2x:output', data=output, | 361 outpart = op.reply.newpart('output', data=output, |
362 mandatory=False) | 362 mandatory=False) |
363 outpart.addparam('in-reply-to', str(part.id), mandatory=False) | 363 outpart.addparam('in-reply-to', str(part.id), mandatory=False) |
364 finally: | 364 finally: |
365 # consume the part content to not corrupt the stream. | 365 # consume the part content to not corrupt the stream. |
366 part.seek(0, 2) | 366 part.seek(0, 2) |
406 | 406 |
407 Use the `addparam` method to add stream level parameter. and `newpart` to | 407 Use the `addparam` method to add stream level parameter. and `newpart` to |
408 populate it. Then call `getchunks` to retrieve all the binary chunks of | 408 populate it. Then call `getchunks` to retrieve all the binary chunks of |
409 data that compose the bundle2 container.""" | 409 data that compose the bundle2 container.""" |
410 | 410 |
411 _magicstring = 'HG2Y' | 411 _magicstring = 'HG20' |
412 | 412 |
413 def __init__(self, ui, capabilities=()): | 413 def __init__(self, ui, capabilities=()): |
414 self.ui = ui | 414 self.ui = ui |
415 self._params = [] | 415 self._params = [] |
416 self._parts = [] | 416 self._parts = [] |
614 return None | 614 return None |
615 | 615 |
616 def compressed(self): | 616 def compressed(self): |
617 return False | 617 return False |
618 | 618 |
619 formatmap = {'2Y': unbundle20} | 619 formatmap = {'20': unbundle20} |
620 | 620 |
621 class bundlepart(object): | 621 class bundlepart(object): |
622 """A bundle2 part contains application level payload | 622 """A bundle2 part contains application level payload |
623 | 623 |
624 The part `type` is used to route the part to the application level | 624 The part `type` is used to route the part to the application level |
732 yield chunk | 732 yield chunk |
733 except Exception, exc: | 733 except Exception, exc: |
734 # backup exception data for later | 734 # backup exception data for later |
735 exc_info = sys.exc_info() | 735 exc_info = sys.exc_info() |
736 msg = 'unexpected error: %s' % exc | 736 msg = 'unexpected error: %s' % exc |
737 interpart = bundlepart('b2x:error:abort', [('message', msg)], | 737 interpart = bundlepart('error:abort', [('message', msg)], |
738 mandatory=False) | 738 mandatory=False) |
739 interpart.id = 0 | 739 interpart.id = 0 |
740 yield _pack(_fpayloadsize, -1) | 740 yield _pack(_fpayloadsize, -1) |
741 for chunk in interpart.getchunks(): | 741 for chunk in interpart.getchunks(): |
742 yield chunk | 742 yield chunk |
980 adjust = self.read(internaloffset) | 980 adjust = self.read(internaloffset) |
981 if len(adjust) != internaloffset: | 981 if len(adjust) != internaloffset: |
982 raise util.Abort(_('Seek failed\n')) | 982 raise util.Abort(_('Seek failed\n')) |
983 self._pos = newpos | 983 self._pos = newpos |
984 | 984 |
985 capabilities = {'HG2Y': (), | 985 capabilities = {'HG20': (), |
986 'b2x:listkeys': (), | 986 'listkeys': (), |
987 'b2x:pushkey': (), | 987 'pushkey': (), |
988 'digests': tuple(sorted(util.DIGESTS.keys())), | 988 'digests': tuple(sorted(util.DIGESTS.keys())), |
989 'b2x:remote-changegroup': ('http', 'https'), | 989 'remote-changegroup': ('http', 'https'), |
990 } | 990 } |
991 | 991 |
992 def getrepocaps(repo, allowpushback=False): | 992 def getrepocaps(repo, allowpushback=False): |
993 """return the bundle2 capabilities for a given repo | 993 """return the bundle2 capabilities for a given repo |
994 | 994 |
995 Exists to allow extensions (like evolution) to mutate the capabilities. | 995 Exists to allow extensions (like evolution) to mutate the capabilities. |
996 """ | 996 """ |
997 caps = capabilities.copy() | 997 caps = capabilities.copy() |
998 caps['b2x:changegroup'] = tuple(sorted(changegroup.packermap.keys())) | 998 caps['changegroup'] = tuple(sorted(changegroup.packermap.keys())) |
999 if obsolete.isenabled(repo, obsolete.exchangeopt): | 999 if obsolete.isenabled(repo, obsolete.exchangeopt): |
1000 supportedformat = tuple('V%i' % v for v in obsolete.formats) | 1000 supportedformat = tuple('V%i' % v for v in obsolete.formats) |
1001 caps['b2x:obsmarkers'] = supportedformat | 1001 caps['obsmarkers'] = supportedformat |
1002 if allowpushback: | 1002 if allowpushback: |
1003 caps['b2x:pushback'] = () | 1003 caps['pushback'] = () |
1004 return caps | 1004 return caps |
1005 | 1005 |
1006 def bundle2caps(remote): | 1006 def bundle2caps(remote): |
1007 """return the bundle capabilities of a peer as dict""" | 1007 """return the bundle capabilities of a peer as dict""" |
1008 raw = remote.capable('bundle2-exp') | 1008 raw = remote.capable('bundle2') |
1009 if not raw and raw != '': | 1009 if not raw and raw != '': |
1010 return {} | 1010 return {} |
1011 capsblob = urllib.unquote(remote.capable('bundle2-exp')) | 1011 capsblob = urllib.unquote(remote.capable('bundle2')) |
1012 return decodecaps(capsblob) | 1012 return decodecaps(capsblob) |
1013 | 1013 |
1014 def obsmarkersversion(caps): | 1014 def obsmarkersversion(caps): |
1015 """extract the list of supported obsmarkers versions from a bundle2caps dict | 1015 """extract the list of supported obsmarkers versions from a bundle2caps dict |
1016 """ | 1016 """ |
1017 obscaps = caps.get('b2x:obsmarkers', ()) | 1017 obscaps = caps.get('obsmarkers', ()) |
1018 return [int(c[1:]) for c in obscaps if c.startswith('V')] | 1018 return [int(c[1:]) for c in obscaps if c.startswith('V')] |
1019 | 1019 |
1020 @parthandler('b2x:changegroup', ('version',)) | 1020 @parthandler('changegroup', ('version',)) |
1021 def handlechangegroup(op, inpart): | 1021 def handlechangegroup(op, inpart): |
1022 """apply a changegroup part on the repo | 1022 """apply a changegroup part on the repo |
1023 | 1023 |
1024 This is a very early implementation that will massive rework before being | 1024 This is a very early implementation that will massive rework before being |
1025 inflicted to any end-user. | 1025 inflicted to any end-user. |
1039 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') | 1039 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') |
1040 op.records.add('changegroup', {'return': ret}) | 1040 op.records.add('changegroup', {'return': ret}) |
1041 if op.reply is not None: | 1041 if op.reply is not None: |
1042 # This is definitely not the final form of this | 1042 # This is definitely not the final form of this |
1043 # return. But one need to start somewhere. | 1043 # return. But one need to start somewhere. |
1044 part = op.reply.newpart('b2x:reply:changegroup', mandatory=False) | 1044 part = op.reply.newpart('reply:changegroup', mandatory=False) |
1045 part.addparam('in-reply-to', str(inpart.id), mandatory=False) | 1045 part.addparam('in-reply-to', str(inpart.id), mandatory=False) |
1046 part.addparam('return', '%i' % ret, mandatory=False) | 1046 part.addparam('return', '%i' % ret, mandatory=False) |
1047 assert not inpart.read() | 1047 assert not inpart.read() |
1048 | 1048 |
1049 _remotechangegroupparams = tuple(['url', 'size', 'digests'] + | 1049 _remotechangegroupparams = tuple(['url', 'size', 'digests'] + |
1050 ['digest:%s' % k for k in util.DIGESTS.keys()]) | 1050 ['digest:%s' % k for k in util.DIGESTS.keys()]) |
1051 @parthandler('b2x:remote-changegroup', _remotechangegroupparams) | 1051 @parthandler('remote-changegroup', _remotechangegroupparams) |
1052 def handleremotechangegroup(op, inpart): | 1052 def handleremotechangegroup(op, inpart): |
1053 """apply a bundle10 on the repo, given an url and validation information | 1053 """apply a bundle10 on the repo, given an url and validation information |
1054 | 1054 |
1055 All the information about the remote bundle to import are given as | 1055 All the information about the remote bundle to import are given as |
1056 parameters. The parameters include: | 1056 parameters. The parameters include: |
1068 try: | 1068 try: |
1069 raw_url = inpart.params['url'] | 1069 raw_url = inpart.params['url'] |
1070 except KeyError: | 1070 except KeyError: |
1071 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url') | 1071 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url') |
1072 parsed_url = util.url(raw_url) | 1072 parsed_url = util.url(raw_url) |
1073 if parsed_url.scheme not in capabilities['b2x:remote-changegroup']: | 1073 if parsed_url.scheme not in capabilities['remote-changegroup']: |
1074 raise util.Abort(_('remote-changegroup does not support %s urls') % | 1074 raise util.Abort(_('remote-changegroup does not support %s urls') % |
1075 parsed_url.scheme) | 1075 parsed_url.scheme) |
1076 | 1076 |
1077 try: | 1077 try: |
1078 size = int(inpart.params['size']) | 1078 size = int(inpart.params['size']) |
1108 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') | 1108 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2') |
1109 op.records.add('changegroup', {'return': ret}) | 1109 op.records.add('changegroup', {'return': ret}) |
1110 if op.reply is not None: | 1110 if op.reply is not None: |
1111 # This is definitely not the final form of this | 1111 # This is definitely not the final form of this |
1112 # return. But one need to start somewhere. | 1112 # return. But one need to start somewhere. |
1113 part = op.reply.newpart('b2x:reply:changegroup') | 1113 part = op.reply.newpart('reply:changegroup') |
1114 part.addparam('in-reply-to', str(inpart.id), mandatory=False) | 1114 part.addparam('in-reply-to', str(inpart.id), mandatory=False) |
1115 part.addparam('return', '%i' % ret, mandatory=False) | 1115 part.addparam('return', '%i' % ret, mandatory=False) |
1116 try: | 1116 try: |
1117 real_part.validate() | 1117 real_part.validate() |
1118 except util.Abort, e: | 1118 except util.Abort, e: |
1119 raise util.Abort(_('bundle at %s is corrupted:\n%s') % | 1119 raise util.Abort(_('bundle at %s is corrupted:\n%s') % |
1120 (util.hidepassword(raw_url), str(e))) | 1120 (util.hidepassword(raw_url), str(e))) |
1121 assert not inpart.read() | 1121 assert not inpart.read() |
1122 | 1122 |
1123 @parthandler('b2x:reply:changegroup', ('return', 'in-reply-to')) | 1123 @parthandler('reply:changegroup', ('return', 'in-reply-to')) |
1124 def handlereplychangegroup(op, inpart): | 1124 def handlereplychangegroup(op, inpart): |
1125 ret = int(inpart.params['return']) | 1125 ret = int(inpart.params['return']) |
1126 replyto = int(inpart.params['in-reply-to']) | 1126 replyto = int(inpart.params['in-reply-to']) |
1127 op.records.add('changegroup', {'return': ret}, replyto) | 1127 op.records.add('changegroup', {'return': ret}, replyto) |
1128 | 1128 |
1129 @parthandler('b2x:check:heads') | 1129 @parthandler('check:heads') |
1130 def handlecheckheads(op, inpart): | 1130 def handlecheckheads(op, inpart): |
1131 """check that head of the repo did not change | 1131 """check that head of the repo did not change |
1132 | 1132 |
1133 This is used to detect a push race when using unbundle. | 1133 This is used to detect a push race when using unbundle. |
1134 This replaces the "heads" argument of unbundle.""" | 1134 This replaces the "heads" argument of unbundle.""" |
1140 assert not h | 1140 assert not h |
1141 if heads != op.repo.heads(): | 1141 if heads != op.repo.heads(): |
1142 raise error.PushRaced('repository changed while pushing - ' | 1142 raise error.PushRaced('repository changed while pushing - ' |
1143 'please try again') | 1143 'please try again') |
1144 | 1144 |
1145 @parthandler('b2x:output') | 1145 @parthandler('output') |
1146 def handleoutput(op, inpart): | 1146 def handleoutput(op, inpart): |
1147 """forward output captured on the server to the client""" | 1147 """forward output captured on the server to the client""" |
1148 for line in inpart.read().splitlines(): | 1148 for line in inpart.read().splitlines(): |
1149 op.ui.write(('remote: %s\n' % line)) | 1149 op.ui.write(('remote: %s\n' % line)) |
1150 | 1150 |
1151 @parthandler('b2x:replycaps') | 1151 @parthandler('replycaps') |
1152 def handlereplycaps(op, inpart): | 1152 def handlereplycaps(op, inpart): |
1153 """Notify that a reply bundle should be created | 1153 """Notify that a reply bundle should be created |
1154 | 1154 |
1155 The payload contains the capabilities information for the reply""" | 1155 The payload contains the capabilities information for the reply""" |
1156 caps = decodecaps(inpart.read()) | 1156 caps = decodecaps(inpart.read()) |
1157 if op.reply is None: | 1157 if op.reply is None: |
1158 op.reply = bundle20(op.ui, caps) | 1158 op.reply = bundle20(op.ui, caps) |
1159 | 1159 |
1160 @parthandler('b2x:error:abort', ('message', 'hint')) | 1160 @parthandler('error:abort', ('message', 'hint')) |
1161 def handlereplycaps(op, inpart): | 1161 def handlereplycaps(op, inpart): |
1162 """Used to transmit abort error over the wire""" | 1162 """Used to transmit abort error over the wire""" |
1163 raise util.Abort(inpart.params['message'], hint=inpart.params.get('hint')) | 1163 raise util.Abort(inpart.params['message'], hint=inpart.params.get('hint')) |
1164 | 1164 |
1165 @parthandler('b2x:error:unsupportedcontent', ('parttype', 'params')) | 1165 @parthandler('error:unsupportedcontent', ('parttype', 'params')) |
1166 def handlereplycaps(op, inpart): | 1166 def handlereplycaps(op, inpart): |
1167 """Used to transmit unknown content error over the wire""" | 1167 """Used to transmit unknown content error over the wire""" |
1168 kwargs = {} | 1168 kwargs = {} |
1169 parttype = inpart.params.get('parttype') | 1169 parttype = inpart.params.get('parttype') |
1170 if parttype is not None: | 1170 if parttype is not None: |
1173 if params is not None: | 1173 if params is not None: |
1174 kwargs['params'] = params.split('\0') | 1174 kwargs['params'] = params.split('\0') |
1175 | 1175 |
1176 raise error.UnsupportedPartError(**kwargs) | 1176 raise error.UnsupportedPartError(**kwargs) |
1177 | 1177 |
1178 @parthandler('b2x:error:pushraced', ('message',)) | 1178 @parthandler('error:pushraced', ('message',)) |
1179 def handlereplycaps(op, inpart): | 1179 def handlereplycaps(op, inpart): |
1180 """Used to transmit push race error over the wire""" | 1180 """Used to transmit push race error over the wire""" |
1181 raise error.ResponseError(_('push failed:'), inpart.params['message']) | 1181 raise error.ResponseError(_('push failed:'), inpart.params['message']) |
1182 | 1182 |
1183 @parthandler('b2x:listkeys', ('namespace',)) | 1183 @parthandler('listkeys', ('namespace',)) |
1184 def handlelistkeys(op, inpart): | 1184 def handlelistkeys(op, inpart): |
1185 """retrieve pushkey namespace content stored in a bundle2""" | 1185 """retrieve pushkey namespace content stored in a bundle2""" |
1186 namespace = inpart.params['namespace'] | 1186 namespace = inpart.params['namespace'] |
1187 r = pushkey.decodekeys(inpart.read()) | 1187 r = pushkey.decodekeys(inpart.read()) |
1188 op.records.add('listkeys', (namespace, r)) | 1188 op.records.add('listkeys', (namespace, r)) |
1189 | 1189 |
1190 @parthandler('b2x:pushkey', ('namespace', 'key', 'old', 'new')) | 1190 @parthandler('pushkey', ('namespace', 'key', 'old', 'new')) |
1191 def handlepushkey(op, inpart): | 1191 def handlepushkey(op, inpart): |
1192 """process a pushkey request""" | 1192 """process a pushkey request""" |
1193 dec = pushkey.decode | 1193 dec = pushkey.decode |
1194 namespace = dec(inpart.params['namespace']) | 1194 namespace = dec(inpart.params['namespace']) |
1195 key = dec(inpart.params['key']) | 1195 key = dec(inpart.params['key']) |
1200 'key': key, | 1200 'key': key, |
1201 'old': old, | 1201 'old': old, |
1202 'new': new} | 1202 'new': new} |
1203 op.records.add('pushkey', record) | 1203 op.records.add('pushkey', record) |
1204 if op.reply is not None: | 1204 if op.reply is not None: |
1205 rpart = op.reply.newpart('b2x:reply:pushkey') | 1205 rpart = op.reply.newpart('reply:pushkey') |
1206 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) | 1206 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) |
1207 rpart.addparam('return', '%i' % ret, mandatory=False) | 1207 rpart.addparam('return', '%i' % ret, mandatory=False) |
1208 | 1208 |
1209 @parthandler('b2x:reply:pushkey', ('return', 'in-reply-to')) | 1209 @parthandler('reply:pushkey', ('return', 'in-reply-to')) |
1210 def handlepushkeyreply(op, inpart): | 1210 def handlepushkeyreply(op, inpart): |
1211 """retrieve the result of a pushkey request""" | 1211 """retrieve the result of a pushkey request""" |
1212 ret = int(inpart.params['return']) | 1212 ret = int(inpart.params['return']) |
1213 partid = int(inpart.params['in-reply-to']) | 1213 partid = int(inpart.params['in-reply-to']) |
1214 op.records.add('pushkey', {'return': ret}, partid) | 1214 op.records.add('pushkey', {'return': ret}, partid) |
1215 | 1215 |
1216 @parthandler('b2x:obsmarkers') | 1216 @parthandler('obsmarkers') |
1217 def handleobsmarker(op, inpart): | 1217 def handleobsmarker(op, inpart): |
1218 """add a stream of obsmarkers to the repo""" | 1218 """add a stream of obsmarkers to the repo""" |
1219 tr = op.gettransaction() | 1219 tr = op.gettransaction() |
1220 new = op.repo.obsstore.mergemarkers(tr, inpart.read()) | 1220 new = op.repo.obsstore.mergemarkers(tr, inpart.read()) |
1221 if new: | 1221 if new: |
1222 op.repo.ui.status(_('%i new obsolescence markers\n') % new) | 1222 op.repo.ui.status(_('%i new obsolescence markers\n') % new) |
1223 op.records.add('obsmarkers', {'new': new}) | 1223 op.records.add('obsmarkers', {'new': new}) |
1224 if op.reply is not None: | 1224 if op.reply is not None: |
1225 rpart = op.reply.newpart('b2x:reply:obsmarkers') | 1225 rpart = op.reply.newpart('reply:obsmarkers') |
1226 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) | 1226 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) |
1227 rpart.addparam('new', '%i' % new, mandatory=False) | 1227 rpart.addparam('new', '%i' % new, mandatory=False) |
1228 | 1228 |
1229 | 1229 |
1230 @parthandler('b2x:reply:obsmarkers', ('new', 'in-reply-to')) | 1230 @parthandler('reply:obsmarkers', ('new', 'in-reply-to')) |
1231 def handlepushkeyreply(op, inpart): | 1231 def handlepushkeyreply(op, inpart): |
1232 """retrieve the result of a pushkey request""" | 1232 """retrieve the result of a pushkey request""" |
1233 ret = int(inpart.params['new']) | 1233 ret = int(inpart.params['new']) |
1234 partid = int(inpart.params['in-reply-to']) | 1234 partid = int(inpart.params['in-reply-to']) |
1235 op.records.add('obsmarkers', {'new': ret}, partid) | 1235 op.records.add('obsmarkers', {'new': ret}, partid) |