123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335(**************************************************************************)(* *)(* Copyright 2012-2015 OCamlPro *)(* Copyright 2012 INRIA *)(* *)(* All rights reserved. This file is distributed under the terms of the *)(* GNU Lesser General Public License version 2.1, with the special *)(* exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)openOpamStd.OpopenOpamTypesopenOpamStateTypes(* Lists of defined variables, for documentation *)letglobal_variable_names=["opam-version","The currently running opam version";"switch","The identifier of the current switch";"jobs","The number of parallel jobs set up in opam \
configuration";"root","The current opam root directory";"make","The 'make' command to use";]letpackage_variable_names=["name","Name of the package";"version","Version of the package";"depends","Resolved direct dependencies of the package";"installed","Whether the package is installed";"enable","Takes the value \"enable\" or \"disable\" depending on whether \
the package is installed";"pinned","Whether the package is pinned";"bin","Binary directory for this package";"sbin","System binary directory for this package";"lib","Library directory for this package";"man","Man directory for this package";"doc","Doc directory for this package";"share","Share directory for this package";"etc","Etc directory for this package";"build","Directory where the package was built";"hash","Hash of the package archive";"dev","True if this is a development package";"build-id","A hash identifying the precise package version with all its \
dependencies";]letpredefined_depends_variables=List.mapOpamVariable.Full.of_string["build";"post";"with-test";"with-doc";"dev";]letresolve_globalgtfull_var=letmoduleV=OpamVariableinifV.Full.(scopefull_var<>Global)thenNoneelseletvar=V.Full.variablefull_varinmatchV.Full.read_from_envfull_varwith|Some_asc->c|None->matchOpamVariable.Map.find_optvargt.global_variableswith|Some(lazy(Some_assome),_)->some|_->matchV.to_stringvarwith|"opam-version"->Some(V.stringOpamVersion.(to_stringcurrent))|"jobs"->Some(V.int(OpamStateConfig.(Lazy.force!r.jobs)))|"root"->Some(V.string(OpamFilename.Dir.to_stringgt.root))|"make"->Some(V.stringOpamStateConfig.(Lazy.force!r.makecmd))|_->None(** Resolve switch-global variables only, as allowed by the 'available:'
field *)letresolve_switch_raw?packagegtswitchswitch_configfull_var=letmoduleV=OpamVariableinletvar=V.Full.variablefull_varinletallowed_package_variables=matchV.Full.scopefull_var,packagewith|_,None->None|V.Full.Packagen,Somenvwhenn<>nv.name->None|_,Somenv->matchV.to_stringvarwith|"name"->Some(S(OpamPackage.Name.to_stringnv.name))|"version"->Some(S(OpamPackage.Version.to_stringnv.version))|_->Noneinifallowed_package_variables<>Nonethenallowed_package_variableselseifV.Full.scopefull_var<>V.Full.GlobalthenNoneelsematchV.Full.read_from_envfull_varwith|Some_asc->c|None->tryletstdpath=OpamTypesBase.std_path_of_string(V.to_stringvar)inletdir=OpamPath.Switch.get_stdpathgt.rootswitchswitch_configstdpathinSome(V.string(OpamFilename.Dir.to_stringdir))withFailure_->matchOpamFile.Switch_config.variableswitch_configvarwith|Some_asc->c|None->matchresolve_globalgtfull_varwith|Some_asc->c|None->matchV.to_stringvarwith|"switch"->Some(V.string(OpamSwitch.to_stringswitch))|_->Noneletresolve_switch?packagestfull_var=resolve_switch_raw?packagest.switch_globalst.switchst.switch_configfull_varopenOpamVariableletis_dev_packagestopam=matchOpamFile.OPAM.urlopamwith|None->false|Someurlf->matchOpamFile.URL.(urlurlf,checksumurlf)with|{OpamUrl.backend=`http;_},_whennot(OpamPackage.Set.mem(OpamFile.OPAM.packageopam)st.pinned)->false|_,_::_->false|_,[]->trueletfilter_depends_formula?(build=true)?(post=false)?(test=OpamStateConfig.(!r.build_test))?(doc=OpamStateConfig.(!r.build_doc))?(dev=false)?default~envff=ff|>OpamFilter.partial_filter_formula(funv->ifList.memvpredefined_depends_variablesthenNoneelseenvv)|>OpamFilter.filter_deps~build~post~test~doc~dev?defaultletall_depends?build?post?test?doc?dev?(filter_default=false)?(depopts=true)stopam=letdev=matchdevwithNone->is_dev_packagestopam|Somed->dinletdeps=OpamFormula.ands(OpamFile.OPAM.dependsopam::ifdepoptsthen[OpamFile.OPAM.depoptsopam]else[])infilter_depends_formula?build?post?test?doc~dev~default:filter_default~env:(resolve_switch~package:(OpamFile.OPAM.packageopam)st)depsletall_installed_depsstopam=letdeps=OpamFormula.atoms(all_depends~post:falsestopam)inOpamStd.List.filter_map(fun(n,cstr)->tryletnv=OpamPackage.Set.find(funnv->nv.name=n)st.installedinletversion=nv.versioninmatchcstrwith|None->Somenv|Some(op,v)whenOpamFormula.eval_relopopversionv->Somenv|Some_->NonewithNot_found->None)depsletbuild_idstopam=letkind=`SHA256inletrecauxhash_mapnvopam=tryhash_map,OpamPackage.Map.findnvhash_mapwithNot_found->matchOpamFile.OPAM.urlopamwith|SomeurlfwhenOpamFile.URL.checksumurlf=[]->(* no fixed source: build-id undefined *)raiseExit|_->lethash_map,deps_hashes=List.fold_left(fun(hash_map,hashes)nv->lethash_map,hash=auxhash_mapnv(OpamPackage.Map.findnvst.opams)inhash_map,hash::hashes)(hash_map,[])(List.sort(funab->-OpamPackage.compareab)(all_installed_depsstopam))inletopam_hash=OpamHash.compute_from_string~kind(OpamFile.OPAM.write_to_string(OpamFile.OPAM.effective_partopam))inlethash=OpamHash.compute_from_string~kind(OpamStd.List.concat_map" "OpamHash.contents(opam_hash::deps_hashes))inOpamPackage.Map.addnvhashhash_map,hashintrylet_hash_map,hash=auxOpamPackage.Map.empty(OpamFile.OPAM.packageopam)opaminSome(OpamHash.contentshash)withExit->None(* filter handling *)letresolvest?opam:opam_arg?(local=OpamVariable.Map.empty)v=letdirnamedir=string(OpamFilename.Dir.to_stringdir)inletpkgname=OpamStd.Option.mapOpamFile.OPAM.nameopam_arginletread_package_varv=letgetname=tryletcfg=OpamPackage.Map.find(OpamPackage.package_of_namest.installedname)st.conf_filesinOpamFile.Dot_config.variablecfg(OpamVariable.Full.variablev)withNot_found->NoneinmatchOpamVariable.Full.scopevwith|OpamVariable.Full.Global->None|OpamVariable.Full.Packagen->getn|OpamVariable.Full.Self->OpamStd.Option.Op.(pkgname>>=get)inletget_local_varv=matchOpamVariable.Full.packagevwith|Some_->None|None->letvar=OpamVariable.Full.variablevintrymatchOpamVariable.Map.findvarlocalwith|None->raiseExit(* Variable explicitly undefined *)|some->somewithNot_found->Noneinletget_package_varv=ifOpamVariable.Full.is_globalvthenNoneelseletvar_str=OpamVariable.to_string(OpamVariable.Full.variablev)inletname=matchOpamVariable.Full.scopevwith|OpamVariable.Full.Global->assertfalse|OpamVariable.Full.Packagen->n|OpamVariable.Full.Self->matchpkgnamewithSomen->n|None->raiseExitinletopam=(* ensure opam, if not None, corresponds to name *)matchopam_argwith|SomeowhenOpamFile.OPAM.nameo=name->opam_arg|_->tryletnv=OpamPackage.package_of_namest.installednameinSome(OpamPackage.Map.findnvst.opams)withNot_found->Noneinletget_nvopam=OpamPackage.createname(OpamFile.OPAM.versionopam)inletroot=st.switch_global.rootinmatchvar_str,opamwith|"installed",Some_->Some(bool(OpamPackage.has_namest.installedname))|"installed",None->Some(boolfalse)|"pinned",_->Some(bool(OpamPackage.has_namest.pinnedname))|"name",_->ifOpamPackage.has_namest.packagesnamethenSome(string(OpamPackage.Name.to_stringname))elseNone|_,None->None|"bin",_->Some(dirname(OpamPath.Switch.binrootst.switchst.switch_config))|"sbin",_->Some(dirname(OpamPath.Switch.sbinrootst.switchst.switch_config))|"lib",_->Some(dirname(OpamPath.Switch.librootst.switchst.switch_configname))|"man",_->Some(dirname(OpamPath.Switch.man_dirrootst.switchst.switch_config))|"doc",_->Some(dirname(OpamPath.Switch.docrootst.switchst.switch_configname))|"share",_->Some(dirname(OpamPath.Switch.sharerootst.switchst.switch_configname))|"etc",_->Some(dirname(OpamPath.Switch.etcrootst.switchst.switch_configname))|"build",Someopam->Some(dirname(OpamPath.Switch.buildrootst.switch(get_nvopam)))|"version",Someopam->Some(string(OpamPackage.Version.to_string(OpamFile.OPAM.versionopam)))|"depends",Someopam->letinstalled_deps=all_installed_depsstopaminletstr_deps=OpamStd.List.concat_map" "OpamPackage.to_stringinstalled_depsinSome(stringstr_deps)|"hash",Someopam->(tryletnv=get_nvopaminletf=OpamPath.archiverootnvinifOpamFilename.existsfthenSome(string(OpamHash.to_string(OpamHash.compute~kind:`MD5(OpamFilename.to_stringf))))elseSome(string"")withNot_found->Some(string""))|"dev",Someopam->Some(bool(is_dev_packagestopam))|"build-id",Someopam->OpamStd.Option.mapstring(build_idstopam)|_,_->Noneinletmake_package_localv=(* [var] within the opam file of [pkg] is tried as [pkg:var] *)matchOpamVariable.Full.is_globalv,pkgnamewith|true,Somename->OpamVariable.Full.createname(OpamVariable.Full.variablev)|_->vinletskip_=Noneinletv'=make_package_localvinletcontents=tryList.fold_left(functionNone->(fun(f,v)->fv)|r->(fun_->r))None[get_local_var,v;Full.read_from_env,v;(ifv'<>vthenFull.read_from_envelseskip),v';read_package_var,v;resolve_switchst,v;(ifv'<>vthenread_package_varelseskip),v';get_package_var,v';]withExit->Noneincontents