Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file model.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281moduleMake(Context:S.CONTEXT)=struct(* Note: [OpamFormula.neg] doesn't work in the [Empty] case, so we just
record whether to negate the result here. *)typerestriction={kind:[`Ensure|`Prevent];expr:OpamFormula.version_formula;}typereal_role={context:Context.t;name:OpamPackage.Name.t;}typerole=|Realofreal_role(* A role is usually an opam package name *)|Virtualof<>*impllist(* (object just for sorting) *)andreal_impl={context:Context.t;pkg:OpamPackage.t;opam:OpamFile.OPAM.t;requires:dependencylist;}anddependency={drole:role;importance:[`Essential|`Recommended|`Restricts];restrictions:restrictionlist;}andimpl=|RealImplofreal_impl(* An implementation is usually an opam package *)|VirtualImplofint*dependencylist(* (int just for sorting) *)|RejectofOpamPackage.t|Dummy(* Used for diagnostics *)letrecpp_versionf=function|RealImplimpl->Fmt.stringf@@OpamPackage.Version.to_string(OpamPackage.versionimpl.pkg)|Rejectpkg->Fmt.stringf@@OpamPackage.version_to_stringpkg|VirtualImpl(_i,deps)->Fmt.(list~sep:(any"&")pp_role)f(List.map(fund->d.drole)deps)|Dummy->Fmt.stringf"(no version)"andpp_implf=function|RealImplimpl->Fmt.stringf(OpamPackage.to_stringimpl.pkg)|Rejectpkg->Fmt.stringf@@OpamPackage.to_stringpkg|VirtualImpl_asx->pp_versionfx|Dummy->Fmt.stringf"(no solution found)"andpp_rolef=function|Realt->Fmt.stringf(OpamPackage.Name.to_stringt.name)|Virtual(_,impls)->Fmt.pff"%a"Fmt.(list~sep:(any"|")pp_impl)implsletpp_impl_long=pp_implmoduleRole=structtypet=roleletpp=pp_roleletcompareab=matcha,bwith|Reala,Realb->OpamPackage.Name.comparea.nameb.name|Virtual(a,_),Virtual(b,_)->compareab|Real_,Virtual_->-1|Virtual_,Real_->1endletrolecontextname=Real{context;name}letvirtual_impl~context~depends()=letdepends=depends|>List.map(funname->letdrole=rolecontextnameinletimportance=`Essentialin{drole;importance;restrictions=[]})inVirtualImpl(-1,depends)letvirtual_roleimpls=letimpls=impls|>List.mapi(funi->function|VirtualImpl(_,x)->VirtualImpl(i,x)|x->x)inVirtual(objectend,impls)typecommand=|(* We don't use 0install commands anywhere *)typecommand_name=privatestringletpp_command_=function(_:command)->.letcommand_requires_role=function(_:command)->.letget_command_impl_command_name=Nonetypedep_info={dep_role:Role.t;dep_importance:[`Essential|`Recommended|`Restricts];dep_required_commands:command_namelist;}typerequirements={role:Role.t;command:command_nameoption;}letdummy_impl=Dummy(* Turn an opam dependency formula into a 0install list of dependencies. *)letlist_deps~context~importance~rankdeps=letopenOpamTypesinletrecaux=function|Empty->[]|Atom(name,restrictions)->letdrole=rolecontextnamein[{drole;restrictions;importance}]|Blockx->auxx|And(x,y)->auxx@auxy|Or_aso->letimpls=group_orsoinletdrole=virtual_roleimplsin(* Essential because we must apply a restriction, even if its
components are only restrictions. *)[{drole;restrictions=[];importance=`Essential}]andgroup_ors=function|Or(x,y)->group_orsx@group_orsy|expr->leti=!rankinrank:=i+1;[VirtualImpl(i,auxexpr)]inauxdepsletrequires_=function|Dummy|Reject_->[],[]|VirtualImpl(_,deps)->deps,[]|RealImplimpl->impl.requires,[]letdep_info{drole;importance;restrictions=_}={dep_role=drole;dep_importance=importance;dep_required_commands=[]}typerole_information={replacement:Role.toption;impls:impllist;}typemachine_group=privatestring(* We don't use machine groups because opam is source-only. *)letmachine_group_impl=Nonetypeconflict_class=stringletconflict_class=function|RealImplimpl->OpamFile.OPAM.conflict_classimpl.opam|>List.mapOpamPackage.Name.to_string|VirtualImpl_->[]|Dummy|Reject_->[](* Opam uses conflicts, e.g.
conflicts if X {> 1} OR Y {< 1 OR > 2}
whereas 0install uses restricts, e.g.
restrict to X {<= 1} AND Y {>= 1 AND <= 2}
Warning: [OpamFormula.neg _ Empty = Empty], so does NOT reverse the result in this case.
For empty conflicts this is fine (don't conflict with anything, just like an empty depends
list). But for the version expressions inside, it's wrong: a conflict with no expression
conflicts with all versions and should restrict the choice to nothing, not to everything.
So, we just tag the formula as [`Prevent] instead of negating it. *)letpreventf=OpamFormula.negFun.idf|>OpamFormula.map(fun(a,expr)->OpamFormula.Atom(a,[{kind=`Prevent;expr}]))letensure=OpamFormula.map(fun(name,vexpr)->letrlist=matchvexprwith|OpamFormula.Empty->[]|r->[{kind=`Ensure;expr=r}]inOpamFormula.Atom(name,rlist))(* Get all the candidates for a role. *)letimplementations=function|Virtual(_,impls)->{impls;replacement=None}|Realrole->letcontext=role.contextinletimpls=Context.candidatescontextrole.name|>List.filter_map(function|_,Error_rejection->None|version,Okopam->letpkg=OpamPackage.createrole.nameversionin(* Note: we ignore depopts here: see opam/doc/design/depopts-and-features *)letrequires=letrank=ref0inletmake_depsimportancexformget=getopam|>Context.filter_depscontextpkg|>xform|>list_deps~context~importance~rankinmake_deps`EssentialensureOpamFile.OPAM.depends@make_deps`RestrictspreventOpamFile.OPAM.conflictsinSome(RealImpl{context;pkg;opam;requires}))in{impls;replacement=None}letrestrictionsdependency=dependency.restrictionsletmeets_restrictionimpl{kind;expr}=matchimplwith|Dummy->true|VirtualImpl_->assertfalse(* Can't constrain version of a virtual impl! *)|Reject_->false|RealImplimpl->letresult=OpamFormula.check_version_formulaexpr(OpamPackage.versionimpl.pkg)inmatchkindwith|`Ensure->result|`Prevent->notresulttyperejection=Context.rejectionletrejectsrole=matchrolewith|Virtual_->[],[]|Realrole->letcontext=role.contextinletrejects=Context.candidatescontextrole.name|>List.filter_map(function|_,Ok_->None|version,Errorreason->letpkg=OpamPackage.createrole.nameversioninSome(Rejectpkg,reason))inletnotes=[]inrejects,notesletcompare_versionab=matcha,bwith|RealImpla,RealImplb->OpamPackage.comparea.pkgb.pkg|VirtualImpl(ia,_),VirtualImpl(ib,_)->compare(ia:int)ib|Rejecta,Rejectb->OpamPackage.compareab|(RealImpl_|Reject_|VirtualImpl_|Dummy),(RealImpl_|Reject_|VirtualImpl_|Dummy)->comparebaletuser_restrictions=function|Virtual_->None|Realrole->matchContext.user_restrictionsrole.contextrole.namewith|None->None|Somef->Some{kind=`Ensure;expr=OpamFormula.Atomf}letformat_machine_impl="(src)"letstring_of_op=function|`Eq->"="|`Geq->">="|`Gt->">"|`Leq->"<="|`Lt->"<"|`Neq->"<>"letstring_of_version_formula=OpamFormula.string_of_formula(fun(rel,v)->Printf.sprintf"%s %s"(string_of_oprel)(OpamPackage.Version.to_stringv))letstring_of_restriction=function|{kind=`Prevent;expr=OpamFormula.Empty}->"conflict with all versions"|{kind=`Prevent;expr}->Fmt.str"not(%s)"(string_of_version_formulaexpr)|{kind=`Ensure;expr}->string_of_version_formulaexprletdescribe_problem_impl=Fmt.to_to_stringContext.pp_rejectionletversion=function|RealImplimpl->Someimpl.pkg|Rejectpkg->Somepkg|VirtualImpl_->None|Dummy->Noneletpackage_name=function|Real{name;_}->Somename|Virtual_->Noneletformula{kind;expr}=(kind,expr)end