123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openPpopenCErrorsmoduletypeKind=sigtype'atvalmaster:'atendmoduletypeS=sigmoduleBranch:sigtypetvalmake:string->tvalequal:t->t->boolvalcompare:t->t->intvalto_string:t->stringvalmaster:tendtypeidtype'akind_gentypekind=Branch.tkind_gentypebranch_info={kind:kind;root:id;pos:id;}type('diff,'info,'property_data)tvalempty:id->('diff,'info,'property_data)tvalcurrent_branch:('e,'i,'c)t->Branch.tvalbranches:('e,'i,'c)t->Branch.tlistvalget_branch:('e,'i,'c)t->Branch.t->branch_infovalreset_branch:('e,'i,'c)t->Branch.t->id->('e,'i,'c)tvalbranch:('e,'i,'c)t->?root:id->?pos:id->Branch.t->kind->('e,'i,'c)tvaldelete_branch:('e,'i,'c)t->Branch.t->('e,'i,'c)tvalmerge:('diff,'i,'c)t->id->ours:'diff->theirs:'diff->?into:Branch.t->Branch.t->('diff,'i,'c)tvalcommit:('diff,'i,'c)t->id->'diff->('diff,'i,'c)tvalrewrite_merge:('diff,'i,'c)t->id->ours:'diff->theirs:'diff->at:id->Branch.t->('diff,'i,'c)tvalcheckout:('e,'i,'c)t->Branch.t->('e,'i,'c)tvalset_info:('e,'info,'c)t->id->'info->('e,'info,'c)tvalget_info:('e,'info,'c)t->id->'infooption(* Read only dag *)moduleDag:Dag.Swithtypenode=idvaldag:('diff,'info,'cdata)t->('diff,'info,'cdata)Dag.tvalcreate_property:('e,'i,'c)t->idlist->'c->('e,'i,'c)tvalproperty_of:('e,'i,'c)t->id->'cDag.Property.tlistvaldelete_property:('e,'i,'c)t->'cDag.Property.t->('e,'i,'c)t(* Removes all unreachable nodes and returns them *)valgc:('e,'info,'c)t->('e,'info,'c)t*Dag.NodeSet.tvalreachable:('e,'info,'c)t->id->Dag.NodeSet.tendmoduleMake(OT:Map.OrderedType)(K:Kind)=structmoduleDag=Dag.Make(OT)typeid=OT.tmoduleBranch=structtypet=stringletmake=letbid=ref0infuns->incrbid;string_of_int!bid^"_"^sletequal=CString.equalletcompare=CString.compareletto_strings=sletmaster="master"endtype'akind_gen='aK.ttypekind=Branch.tkind_genmoduleBranchMap=Map.Make(Branch)typebranch_info={kind:kind;root:id;pos:id;}type('edge,'info,'property_data)t={cur_branch:Branch.t;heads:branch_infoBranchMap.t;dag:('edge,'info,'property_data)Dag.t;}letemptyroot={cur_branch=Branch.master;heads=BranchMap.singletonBranch.master{root=root;pos=root;kind=K.master};dag=Dag.empty;}letadd_nodevcsidedges=assert(not(CList.is_emptyedges));{vcswithdag=List.fold_left(fung(t,tgt)->Dag.add_edgegidttgt)vcs.dagedges}letget_branchvcshead=tryBranchMap.findheadvcs.headswithNot_found->anomaly(str"head "++strhead++str" not found.")letreset_branchvcsheadid=letmapnameh=ifBranch.equalnameheadthen{hwithpos=id}elsehin{vcswithheads=BranchMap.mapimapvcs.heads;}letcurrent_branchvcs=vcs.cur_branchletbranchvcs?(root=(get_branchvcsvcs.cur_branch).pos)?(pos=root)namekind={vcswithheads=BranchMap.addname{kind;root;pos}vcs.heads;cur_branch=name}letdelete_branchvcsname=ifBranch.equalBranch.masternamethenvcselseletfiltern_=not(Branch.equalnname)in{vcswithheads=BranchMap.filterfiltervcs.heads}letmergevcsid~ours:tr1~theirs:tr2?(into=vcs.cur_branch)name=assert(not(Branch.equalnameinto));letbr_id=(get_branchvcsname).posinletcur_id=(get_branchvcsinto).posinletvcs=add_nodevcsid[tr1,cur_id;tr2,br_id]inletvcs=reset_branchvcsintoidinvcsletdel_edgeidvcstgt={vcswithdag=Dag.del_edgevcs.dagidtgt}letrewrite_mergevcsid~ours:tr1~theirs:tr2~at:cur_idname=letbr_id=(get_branchvcsname).posinletold_edges=List.mapfst(Dag.from_nodevcs.dagid)inletvcs=List.fold_left(del_edgeid)vcsold_edgesinletvcs=add_nodevcsid[tr1,cur_id;tr2,br_id]invcsletcommitvcsidtr=letvcs=add_nodevcsid[tr,(get_branchvcsvcs.cur_branch).pos]inletvcs=reset_branchvcsvcs.cur_branchidinvcsletcheckoutvcsname={vcswithcur_branch=name}letset_infovcsidinfo={vcswithdag=Dag.set_infovcs.dagidinfo}letget_infovcsid=Dag.get_infovcs.dagidletcreate_propertyvcsli={vcswithdag=Dag.create_propertyvcs.dagli}letproperty_ofvcsi=Dag.property_ofvcs.dagiletdelete_propertyvcsc={vcswithdag=Dag.del_propertyvcs.dagc}letbranchesvcs=BranchMap.fold(funx_accu->x::accu)vcs.heads[]letdagvcs=vcs.dagletrecclosuresdn=letl=tryDag.from_nodednwithNot_found->[]inList.fold_left(funs(n',_)->ifDag.NodeSet.memn'sthenselseclosuresdn')(Dag.NodeSet.addns)lletreachablevcsi=closureDag.NodeSet.emptyvcs.dagiletgcvcs=letalive=BranchMap.fold(funb{pos}s->closuresvcs.dagpos)vcs.headsDag.NodeSet.emptyinletdead=Dag.NodeSet.diff(Dag.all_nodesvcs.dag)alivein{vcswithdag=Dag.del_nodesvcs.dagdead},deadend