123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167(** default[1] negotiator implementation
[1] "default" as defined in the canonical git implementation in C,
see https://github.com/git/git/tree/master/negotiator *)openSigstype('k,'p,'t)psq=(modulePsq.Swithtypek='kandtypep='pandtypet='t)type('uid,'g,'s)parents='uid->('uid,'uid*intref*int64,'g)store->(('uid*intref*int64)list,'s)iotype'uidt=|State:{mutablerev_list:'psq;psq:('uid,'uid*intref*int64,'psq)psq;mutablenon_common_revs:int;}->'uidtlet_common=1lsl2let_common_ref=1lsl3let_seen=1lsl4let_popped=1lsl5letmake:typeuid.compare:(uid->uid->int)->uidt=fun~compare->letmoduleK=structtypet=uidletcompare=compareendinletmoduleP=structtypet=uid*intref*int64letcompare(_,_,a)(_,_,b)=Int64.comparebaendinletmodulePsq=Psq.Make(K)(P)inletrev_list=Psq.emptyinletnon_common_revs=0inState{rev_list;psq=(modulePsq);non_common_revs}letrev_list_push:typeuid.uidt->uid*intref*int64->int->unit=fun(State({rev_list;psq=(modulePsq);non_common_revs}asstate))(uid,p,ts)mark->if!plandmark=0thenp:=!plormark;state.rev_list<-Psq.adduid(uid,p,ts)rev_list;if!pland_common=0thenstate.non_common_revs<-non_common_revs+1letrecmark_common:typegsuid.sscheduler->parents:(uid,g,s)parents->(uid,uid*intref*int64,g)store->uidt->uid*intref*int64->bool->(unit,s)io=fun({bind;return}asscheduler)~parentsstore(State({non_common_revs;_}asstate)ast)(uid,p,ts)only_ancestors->let(>>=)=bindinifonly_ancestorsthenp:=!plor_common;if!pland_seen=0then(rev_list_pusht(uid,p,ts)_seen;return())else(if(notonly_ancestors)&&!pland_popped=0thenstate.non_common_revs<-non_common_revs-1;parentsuidstore>>=letrecgo=function|[]->return()|(uid,p,ts)::rest->mark_commonscheduler~parentsstoret(uid,p,ts)false>>=fun()->gorestingo)letknown_common:typegsuid.sscheduler->parents:(uid,g,s)parents->(uid,uid*intref*int64,g)store->uidt->uid*intref*int64->(unit,s)io=fun({return;_}asscheduler)~parentsstoret(uid,p,ts)->if!pland_seen=0then(rev_list_pusht(uid,p,ts)(_common_reflor_seen);mark_commonscheduler~parentsstoret(uid,p,ts)true)elsereturn()lettiptobj=rev_list_pushtobj_seenletack:typegsuid.sscheduler->parents:(uid,g,s)parents->(uid,uid*intref*int64,g)store->uidt->uid*intref*int64->(bool,s)io=fun({bind;return}asscheduler)~parentsstoret(uid,p,ts)->let(>>=)=bindinletres=not(!pland_common=0)inmark_commonscheduler~parentsstoret(uid,p,ts)false>>=fun()->returnresletget_rev:typegsuid.sscheduler->parents:(uid,g,s)parents->(uid,uid*intref*int64,g)store->uidt->(uidoption,s)io=fun({bind;return}asscheduler)~parentsstore(State({psq=(modulePsq);_}asstate)ast)->let(>>=)=bindinletrecgo()=ifstate.non_common_revs=0||Psq.is_emptystate.rev_listthenreturnNoneelsematchPsq.popstate.rev_listwith|None->returnNone|Some((uid,(_,p,_)),rev_list)->state.rev_list<-rev_list;parentsuidstore>>=funps->p:=!plor_popped;if!pland_common=0thenstate.non_common_revs<-state.non_common_revs-1;letmark=ref0inletres=ref(Someuid)inif!pland_common<>0then(mark:=_commonlor_seen;res:=None)elseif!pland_common_ref<>0thenmark:=_commonlor_seenelsemark:=_seen;letrecloop=function|[]->(match!reswithNone->go()|Some_asv->returnv)|(uid,p,ts)::rest->if!pland_seen=0thenrev_list_pusht(uid,p,ts)!mark;if!markland_common<>0thenmark_commonscheduler~parentsstoret(uid,p,ts)true>>=fun()->looprestelselooprestinlooppsingo()letnext:typegsuid.sscheduler->parents:(uid,g,s)parents->(uid,uid*intref*int64,g)store->uidt->(uidoption,s)io=funscheduler~parentsstoret->get_revscheduler~parentsstoret