diff -r 3e102a8dd52c -r e8c8d81eb864 mercurial/bundle2.py --- a/mercurial/bundle2.py Fri Jun 16 16:56:16 2017 -0700 +++ b/mercurial/bundle2.py Thu Jun 22 10:10:02 2017 -0700 @@ -158,6 +158,7 @@ changegroup, error, obsolete, + phases, pushkey, pycompat, tags, @@ -178,6 +179,8 @@ _fpayloadsize = '>i' _fpartparamcount = '>BB' +_fphasesentry = '>i20s' + preferedchunksize = 4096 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]') @@ -1387,6 +1390,14 @@ obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing) buildobsmarkerspart(bundler, obsmarkers) + if opts.get('phases', False): + headsbyphase = phases.subsetphaseheads(repo, outgoing.missing) + phasedata = [] + for phase in phases.allphases: + for head in headsbyphase[phase]: + phasedata.append(_pack(_fphasesentry, phase, head)) + bundler.newpart('phase-heads', data=''.join(phasedata)) + def addparttagsfnodescache(repo, bundler, outgoing): # we include the tags fnode cache for the bundle changeset # (as an optional parts) @@ -1721,6 +1732,29 @@ kwargs[key] = inpart.params[key] raise error.PushkeyFailed(partid=str(inpart.id), **kwargs) +def _readphaseheads(inpart): + headsbyphase = [[] for i in phases.allphases] + entrysize = struct.calcsize(_fphasesentry) + while True: + entry = inpart.read(entrysize) + if len(entry) < entrysize: + if entry: + raise error.Abort(_('bad phase-heads bundle part')) + break + phase, node = struct.unpack(_fphasesentry, entry) + headsbyphase[phase].append(node) + return headsbyphase + +@parthandler('phase-heads') +def handlephases(op, inpart): + """apply phases from bundle part to repo""" + headsbyphase = _readphaseheads(inpart) + addednodes = [] + for entry in op.records['changegroup']: + addednodes.extend(entry['addednodes']) + phases.updatephases(op.repo.unfiltered(), op.gettransaction(), headsbyphase, + addednodes) + @parthandler('reply:pushkey', ('return', 'in-reply-to')) def handlepushkeyreply(op, inpart): """retrieve the result of a pushkey request"""