mercurial/exchange.py
changeset 20441 eca9d5375606
parent 20440 400da8bc7786
child 20462 0031ef5df586
equal deleted inserted replaced
20440:400da8bc7786 20441:eca9d5375606
   171                     # we return an integer indicating remote head count
   171                     # we return an integer indicating remote head count
   172                     # change
   172                     # change
   173                     pushop.ret = pushop.remote.addchangegroup(cg, 'push',
   173                     pushop.ret = pushop.remote.addchangegroup(cg, 'push',
   174                                                               pushop.repo.url())
   174                                                               pushop.repo.url())
   175 
   175 
   176             if pushop.ret:
   176             _pushsyncphase(pushop)
   177                 # push succeed, synchronize target of the push
       
   178                 cheads = pushop.outgoing.missingheads
       
   179             elif pushop.revs is None:
       
   180                 # All out push fails. synchronize all common
       
   181                 cheads = pushop.outgoing.commonheads
       
   182             else:
       
   183                 # I want cheads = heads(::missingheads and ::commonheads)
       
   184                 # (missingheads is revs with secret changeset filtered out)
       
   185                 #
       
   186                 # This can be expressed as:
       
   187                 #     cheads = ( (missingheads and ::commonheads)
       
   188                 #              + (commonheads and ::missingheads))"
       
   189                 #              )
       
   190                 #
       
   191                 # while trying to push we already computed the following:
       
   192                 #     common = (::commonheads)
       
   193                 #     missing = ((commonheads::missingheads) - commonheads)
       
   194                 #
       
   195                 # We can pick:
       
   196                 # * missingheads part of common (::commonheads)
       
   197                 common = set(pushop.outgoing.common)
       
   198                 nm = pushop.repo.changelog.nodemap
       
   199                 cheads = [node for node in pushop.revs if nm[node] in common]
       
   200                 # and
       
   201                 # * commonheads parents on missing
       
   202                 revset = unfi.set('%ln and parents(roots(%ln))',
       
   203                                  pushop.outgoing.commonheads,
       
   204                                  pushop.outgoing.missing)
       
   205                 cheads.extend(c.node() for c in revset)
       
   206             # even when we don't push, exchanging phase data is useful
       
   207             remotephases = pushop.remote.listkeys('phases')
       
   208             if (pushop.ui.configbool('ui', '_usedassubrepo', False)
       
   209                 and remotephases    # server supports phases
       
   210                 and pushop.ret is None # nothing was pushed
       
   211                 and remotephases.get('publishing', False)):
       
   212                 # When:
       
   213                 # - this is a subrepo push
       
   214                 # - and remote support phase
       
   215                 # - and no changeset was pushed
       
   216                 # - and remote is publishing
       
   217                 # We may be in issue 3871 case!
       
   218                 # We drop the possible phase synchronisation done by
       
   219                 # courtesy to publish changesets possibly locally draft
       
   220                 # on the remote.
       
   221                 remotephases = {'publishing': 'True'}
       
   222             if not remotephases: # old server or public only rer
       
   223                 _localphasemove(pushop, cheads)
       
   224                 # don't push any phase data as there is nothing to push
       
   225             else:
       
   226                 ana = phases.analyzeremotephases(pushop.repo, cheads,
       
   227                                                  remotephases)
       
   228                 pheads, droots = ana
       
   229                 ### Apply remote phase on local
       
   230                 if remotephases.get('publishing', False):
       
   231                     _localphasemove(pushop, cheads)
       
   232                 else: # publish = False
       
   233                     _localphasemove(pushop, pheads)
       
   234                     _localphasemove(pushop, cheads, phases.draft)
       
   235                 ### Apply local phase on remote
       
   236 
       
   237                 # Get the list of all revs draft on remote by public here.
       
   238                 # XXX Beware that revset break if droots is not strictly
       
   239                 # XXX root we may want to ensure it is but it is costly
       
   240                 outdated =  unfi.set('heads((%ln::%ln) and public())',
       
   241                                      droots, cheads)
       
   242                 for newremotehead in outdated:
       
   243                     r = pushop.remote.pushkey('phases',
       
   244                                               newremotehead.hex(),
       
   245                                               str(phases.draft),
       
   246                                               str(phases.public))
       
   247                     if not r:
       
   248                         pushop.ui.warn(_('updating %s to public failed!\n')
       
   249                                        % newremotehead)
       
   250             _pushobsolete(pushop)
   177             _pushobsolete(pushop)
   251         finally:
   178         finally:
   252             if lock is not None:
   179             if lock is not None:
   253                 lock.release()
   180                 lock.release()
   254     finally:
   181     finally:
   255         if locallock is not None:
   182         if locallock is not None:
   256             locallock.release()
   183             locallock.release()
   257 
   184 
   258     _pushbookmark(pushop)
   185     _pushbookmark(pushop)
   259     return pushop.ret
   186     return pushop.ret
       
   187 
       
   188 def _pushsyncphase(pushop):
       
   189     """synchronise phase information locally and remotly"""
       
   190     unfi = pushop.repo.unfiltered()
       
   191     if pushop.ret:
       
   192         # push succeed, synchronize target of the push
       
   193         cheads = pushop.outgoing.missingheads
       
   194     elif pushop.revs is None:
       
   195         # All out push fails. synchronize all common
       
   196         cheads = pushop.outgoing.commonheads
       
   197     else:
       
   198         # I want cheads = heads(::missingheads and ::commonheads)
       
   199         # (missingheads is revs with secret changeset filtered out)
       
   200         #
       
   201         # This can be expressed as:
       
   202         #     cheads = ( (missingheads and ::commonheads)
       
   203         #              + (commonheads and ::missingheads))"
       
   204         #              )
       
   205         #
       
   206         # while trying to push we already computed the following:
       
   207         #     common = (::commonheads)
       
   208         #     missing = ((commonheads::missingheads) - commonheads)
       
   209         #
       
   210         # We can pick:
       
   211         # * missingheads part of common (::commonheads)
       
   212         common = set(pushop.outgoing.common)
       
   213         nm = pushop.repo.changelog.nodemap
       
   214         cheads = [node for node in pushop.revs if nm[node] in common]
       
   215         # and
       
   216         # * commonheads parents on missing
       
   217         revset = unfi.set('%ln and parents(roots(%ln))',
       
   218                          pushop.outgoing.commonheads,
       
   219                          pushop.outgoing.missing)
       
   220         cheads.extend(c.node() for c in revset)
       
   221     # even when we don't push, exchanging phase data is useful
       
   222     remotephases = pushop.remote.listkeys('phases')
       
   223     if (pushop.ui.configbool('ui', '_usedassubrepo', False)
       
   224         and remotephases    # server supports phases
       
   225         and pushop.ret is None # nothing was pushed
       
   226         and remotephases.get('publishing', False)):
       
   227         # When:
       
   228         # - this is a subrepo push
       
   229         # - and remote support phase
       
   230         # - and no changeset was pushed
       
   231         # - and remote is publishing
       
   232         # We may be in issue 3871 case!
       
   233         # We drop the possible phase synchronisation done by
       
   234         # courtesy to publish changesets possibly locally draft
       
   235         # on the remote.
       
   236         remotephases = {'publishing': 'True'}
       
   237     if not remotephases: # old server or public only rer
       
   238         _localphasemove(pushop, cheads)
       
   239         # don't push any phase data as there is nothing to push
       
   240     else:
       
   241         ana = phases.analyzeremotephases(pushop.repo, cheads,
       
   242                                          remotephases)
       
   243         pheads, droots = ana
       
   244         ### Apply remote phase on local
       
   245         if remotephases.get('publishing', False):
       
   246             _localphasemove(pushop, cheads)
       
   247         else: # publish = False
       
   248             _localphasemove(pushop, pheads)
       
   249             _localphasemove(pushop, cheads, phases.draft)
       
   250         ### Apply local phase on remote
       
   251 
       
   252         # Get the list of all revs draft on remote by public here.
       
   253         # XXX Beware that revset break if droots is not strictly
       
   254         # XXX root we may want to ensure it is but it is costly
       
   255         outdated =  unfi.set('heads((%ln::%ln) and public())',
       
   256                              droots, cheads)
       
   257         for newremotehead in outdated:
       
   258             r = pushop.remote.pushkey('phases',
       
   259                                       newremotehead.hex(),
       
   260                                       str(phases.draft),
       
   261                                       str(phases.public))
       
   262             if not r:
       
   263                 pushop.ui.warn(_('updating %s to public failed!\n')
       
   264                                        % newremotehead)
   260 
   265 
   261 def _localphasemove(pushop, nodes, phase=phases.public):
   266 def _localphasemove(pushop, nodes, phase=phases.public):
   262     """move <nodes> to <phase> in the local source repo"""
   267     """move <nodes> to <phase> in the local source repo"""
   263     if pushop.locallocked:
   268     if pushop.locallocked:
   264         phases.advanceboundary(pushop.repo, phase, nodes)
   269         phases.advanceboundary(pushop.repo, phase, nodes)