"""Small extension altering some push behavior- Add a new wire protocol command to exchange obsolescence markers. Sending the raw file as a binary instead of using pushkey hack.- Add a "push done" notification- Push obsolescence marker before anything else (This works around the lack of global transaction)"""importerrnofromStringIOimportStringIOfrommercurial.i18nimport_frommercurialimportextensionsfrommercurialimportwireprotofrommercurialimportobsoletefrommercurialimportlocalrepodefclient_pushobsmarkers(self,obsfile):"""wireprotocol peer method"""self.requirecap('_push_experiment_pushobsmarkers_0',_('push obsolete markers faster'))ret,output=self._callpush('push_experiment_pushobsmarkers_0',obsfile)forlinoutput.splitlines(True):self.ui.status(_('remote: '),l)returnretdefsrv_pushobsmarkers(repo,proto):"""wireprotocol command"""fp=StringIO()proto.redirect()proto.getfile(fp)data=fp.getvalue()fp.close()lock=repo.lock()try:tr=repo.transaction('pushkey: obsolete markers')try:repo.obsstore.mergemarkers(tr,data)tr.close()finally:tr.release()finally:lock.release()returnwireproto.pushres(0)defsyncpush(orig,repo,remote):"""wraper for obsolete.syncpush to use the fast way if possible"""ifnot(obsolete._enabledandrepo.obsstore):returnifremote.capable('_push_experiment_pushobsmarkers_0'):return# already pushed before changesetremote.push_experiment_pushobsmarkers_0(obsfp)returnreturnorig(repo,remote)defclient_notifypushend(self):"""wire peer command to notify a push is done"""self.requirecap('_push_experiment_notifypushend_0',_('hook once push is all done'))returnself._call('push_experiment_notifypushend_0')defsrv_notifypushend(repo,proto):"""wire protocol command to notify a push is done"""proto.redirect()repo.hook('notifypushend')returnwireproto.pushres(0)defaugmented_push(orig,repo,remote,*args,**kwargs):"""push wrapped that call the wire protocol command"""ifnotremote.canpush():raiseutil.Abort(_("destination does not support push"))if(obsolete._enabledandrepo.obsstoreandremote.capable('_push_experiment_pushobsmarkers_0')):# push marker early to limit damage of pushing too early.try:obsfp=repo.sopener('obsstore')exceptIOErrorase:ife.errno!=errno.ENOENT:raiseelse:remote.push_experiment_pushobsmarkers_0(obsfp)ret=orig(repo,remote,*args,**kwargs)ifremote.capable('_push_experiment_notifypushend_0'):remote.push_experiment_notifypushend_0()returnretdefcapabilities(orig,repo,proto):"""wrapper to advertise new capability"""caps=orig(repo,proto)ifobsolete._enabled:caps+=' _push_experiment_pushobsmarkers_0'caps+=' _push_experiment_notifypushend_0'returncapsdefextsetup(ui):wireproto.wirepeer.push_experiment_pushobsmarkers_0=client_pushobsmarkerswireproto.wirepeer.push_experiment_notifypushend_0=client_notifypushendwireproto.commands['push_experiment_pushobsmarkers_0']=(srv_pushobsmarkers,'')wireproto.commands['push_experiment_notifypushend_0']=(srv_notifypushend,'')extensions.wrapfunction(wireproto,'capabilities',capabilities)extensions.wrapfunction(obsolete,'syncpush',syncpush)extensions.wrapfunction(localrepo.localrepository,'push',augmented_push)