123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)openOpamTypesopenOpamTypesBaseletlogfmt=OpamConsole.log"opam-file"fmtopenOpamFile.OPAM(** manipulation utilities *)letnames_of_formulaflagf=OpamPackageVar.filter_depends_formula~build:true~post:true~dev:true~test:flag~doc:flag~default:false~env:OpamStd.Option.nonef|>OpamFormula.atoms|>List.mapfst|>OpamPackage.Name.Set.of_listletall_commandst=t.build@t.install@t.remove@t.run_test@t.deprecated_build_docletall_urlst=leturlf_urlsuf=OpamFile.URL.urluf::OpamFile.URL.mirrorsufin(matcht.urlwithSomeuf->urlf_urlsuf|None->[])@(matcht.dev_repowithSomeu->[u]|None->[])@List.fold_left(funacc(_,uf)->urlf_urlsuf@acc)[]t.extra_sourcesletfilters_of_formulaf=OpamFormula.fold_left(funacc(_,f)->OpamFormula.fold_left(funacc->function|Constraint(_,f)->f::acc|Filterf->f::acc)accf)[]f(* Doesn't include filters in commands *)letall_filters?(exclude_post=false)t=OpamStd.List.filter_mapsndt.patches@OpamStd.List.filter_mapsndt.messages@(ifexclude_postthen[]elseOpamStd.List.filter_mapsndt.post_messages)@List.mapsndt.depexts@OpamStd.List.filter_mapsndt.libraries@OpamStd.List.filter_mapsndt.syntax@[t.available]@filters_of_formula(OpamFormula.ands(t.depends::t.depopts::t.conflicts::List.map(fun(_,f,_)->f)t.features))letmap_all_filtersft=letmapsndx=List.map(fun(x,ft)->x,fft)xinletmapsndoptx=List.map(function|(x,Someft)->x,Some(fft)|nf->nf)xinletmap_commands=List.map(fun(args,filter)->List.map(function|s,Someft->s,Some(fft)|nf->nf)args,OpamStd.Option.mapffilter)inletmap_filtered_formula=OpamFormula.map(fun(name,fc)->letfc=OpamFormula.map(function|Filterflt->Atom(Filter(fflt))|Constraint(relop,flt)->Atom(Constraint(relop,(fflt))))fcinAtom(name,fc))inletmap_features=List.map(fun(var,fformula,doc)->var,map_filtered_formulafformula,doc)int|>with_patches(mapsndoptt.patches)|>with_messages(mapsndoptt.messages)|>with_post_messages(mapsndoptt.post_messages)|>with_depexts(mapsndt.depexts)|>with_libraries(mapsndoptt.libraries)|>with_syntax(mapsndoptt.syntax)|>with_available(ft.available)|>with_depends(map_filtered_formulat.depends)|>with_depopts(map_filtered_formulat.depopts)|>with_conflicts(map_filtered_formulat.conflicts)|>with_features(map_featurest.features)|>with_build(map_commandst.build)|>with_run_test(map_commandst.run_test)|>with_install(map_commandst.install)|>with_remove(map_commandst.remove)|>with_deprecated_build_test(map_commandst.deprecated_build_test)|>with_deprecated_build_doc(map_commandst.deprecated_build_doc)letall_variables?exclude_postt=OpamFilter.commands_variables(all_commandst)@List.fold_left(funaccf->OpamFilter.variablesf@acc)[](all_filters?exclude_postt)letmap_all_variablesft=letmap_fld(x,flt)=x,OpamFilter.map_variablesffltinletmap_optfld=function|x,Someflt->x,Some(OpamFilter.map_variablesfflt)|_,Noneasoptfld->optfldinletmap_commands=letmap_args=List.map(fun(s,filter)->(matchswith|CStrings->CString(OpamFilter.map_variables_in_stringfs)|CIdentid->letid=tryfilter_ident_of_stringid|>OpamFilter.map_variables_in_fidentf|>string_of_filter_identwithFailure_->idinCIdentid),OpamStd.Option.Op.(filter>>|OpamFilter.map_variablesf))inList.map(fun(args,filter)->map_argsargs,OpamStd.Option.Op.(filter>>|OpamFilter.map_variablesf))inletmap_filtered_formula=OpamFormula.map(fun(name,fc)->letfc=OpamFormula.map(function|Filterflt->Atom(Filter(OpamFilter.map_variablesfflt))|Constraint(relop,flt)->Atom(Constraint(relop,(OpamFilter.map_variablesfflt))))fcinAtom(name,fc))inletmap_features=List.map(fun(var,fformula,doc)->var,map_filtered_formulafformula,doc)int|>with_patches(List.mapmap_optfldt.patches)|>with_messages(List.mapmap_optfldt.messages)|>with_post_messages(List.mapmap_optfldt.post_messages)|>with_depexts(List.mapmap_fldt.depexts)|>with_libraries(List.mapmap_optfldt.libraries)|>with_syntax(List.mapmap_optfldt.syntax)|>with_build(map_commandst.build)|>with_run_test(map_commandst.run_test)|>with_install(map_commandst.install)|>with_remove(map_commandst.remove)|>with_depends(map_filtered_formulat.depends)|>with_depopts(map_filtered_formulat.depopts)|>with_conflicts(map_filtered_formulat.conflicts)|>with_available(OpamFilter.map_variablesft.available)|>with_features(map_featurest.features)|>with_deprecated_build_test(map_commandst.deprecated_build_test)|>with_deprecated_build_doc(map_commandst.deprecated_build_doc)letall_expanded_stringst=List.mapfstt.messages@List.mapfstt.post_messages@List.fold_left(funacc(args,_)->List.fold_left(funacc->functionCStrings,_->s::acc|_->acc)accargs)[](all_commandst)@List.fold_left(OpamFilter.fold_down_left(funacc->functionFStrings->s::acc|_->acc))[](all_filterst)letall_dependst=OpamPackage.Name.Set.union(names_of_formulatruet.depends)(names_of_formulatruet.depopts)(* Templating & linting *)lettemplatenv=letmaintainer=letfrom_git=trymatchOpamSystem.read_command_output["git";"config";"--get";"user.name"],OpamSystem.read_command_output["git";"config";"--get";"user.email"]with|[name],[email]->Some[Printf.sprintf"%s <%s>"nameemail]|_->raiseNot_foundwithe->OpamStd.Exn.fatale;Noneinmatchfrom_gitwith|Someu->u|None->letemail=trySome(Sys.getenv"EMAIL")withNot_found->NoneintryletopenUnixinletpw=getpwuid(getuid())inletemail=matchemailwith|Somee->e|None->pw.pw_name^"@"^gethostname()inmatchOpamStd.String.splitpw.pw_gecos','with|name::_->[Printf.sprintf"%s <%s>"nameemail]|_->[email]withNot_found->matchemailwith|Somee->[e]|None->[]increatenv|>with_name_optNone|>with_maintainermaintainer|>with_build[[CString"./configure",None;CString"--prefix=%{prefix}%",None],None;[CIdent"make",None],None]|>with_install[[CIdent"make",None;CString"install",None],None]|>with_depends(Atom(OpamPackage.Name.of_string"specify-dependencies-here",(Atom(Constraint(`Geq,FString"optional-version")))))|>with_authormaintainer|>with_homepage[""]|>with_license[""]|>with_dev_repo(OpamUrl.of_string"git+https://")|>with_bug_reports[""]|>with_synopsis""letlint?check_extra_filest=letformat_errors=List.map(fun(field,(pos,msg))->3,`Error,Printf.sprintf"File format error in '%s'%s: %s"field(matchposwith|Some(_,li,col)whenli>=0&&col>=0->Printf.sprintf" at line %d, column %d"licol|_->"")msg)(OpamFile.OPAM.format_errorst)inletcondnumlevelmsg?detailcd=ifcdthenletmsg=matchdetailwith|Somed->Printf.sprintf"%s: \"%s\""msg(String.concat"\", \""d)|None->msginSome(num,level,msg)elseNoneinletall_commands=all_commandstinletall_expanded_strings=all_expanded_stringstinletall_depends=all_dependstinletwarnings=[cond20`Warning"Field 'opam-version' refers to the patch version of opam, it \
should be of the form MAJOR.MINOR"~detail:[OpamVersion.to_stringt.opam_version](OpamVersion.nopatcht.opam_version<>t.opam_version);cond21`Error"Field 'opam-version' doesn't match the current version, \
validation may not be accurate"~detail:[OpamVersion.to_stringt.opam_version](OpamVersion.comparet.opam_versionOpamVersion.current_nopatch<>0);(*
cond (t.name = None)
"Missing field 'name' or directory in the form 'name.version'";
cond (t.version = None)
"Missing field 'version' or directory in the form 'name.version'";
*)(letempty_fields=OpamStd.List.filter_map(functionn,[""]->Somen|_->None)["maintainer",t.maintainer;"homepage",t.homepage;"author",t.author;"license",t.license;"doc",t.doc;"tags",t.tags;"bug_reports",t.bug_reports]incond22`Error"Some fields are present but empty; remove or fill them"~detail:empty_fields(empty_fields<>[]));cond23`Error"Missing field 'maintainer'"(t.maintainer=[]);cond24`Error"Field 'maintainer' has the old default value"(List.mem"contact@ocamlpro.com"t.maintainer&¬(List.mem"org:ocamlpro"t.tags));cond25`Warning"Missing field 'authors'"(t.author=[]);cond26`Warning"No field 'install', but a field 'remove': install instructions \
probably part of 'build'. Use the 'install' field or a .install \
file"(t.install=[]&&t.build<>[]&&t.remove<>[]);(*
cond 27 `Warning
"No field 'remove' while a field 'install' is present, uncomplete \
uninstallation suspected"
(t.install <> [] && t.remove = []);
*)(letunk_flags=OpamStd.List.filter_map(function|Pkgflag_Unknowns->Somes|_->None)t.flagsincond28`Error"Unknown package flags found"~detail:unk_flags(unk_flags<>[]));(letfiltered_vars=OpamFilter.variables_of_filtered_formulat.depends@OpamFilter.variables_of_filtered_formulat.depopts|>List.filter(funv->not(OpamVariable.Full.is_globalv))|>List.mapOpamVariable.Full.to_stringincond29`Error"Package dependencies mention package variables"~detail:filtered_vars(filtered_vars<>[]));(*
cond 30 `Error
"Field 'depopts' is not a pure disjunction"
(List.exists (function
| OpamFormula.Atom _ -> false
| _ -> true)
(OpamFormula.ors_to_list t.depopts));
*)(letdup_depends=OpamPackage.Name.Set.inter(names_of_formulafalset.depends)(names_of_formulatruet.depopts)incond31`Error"Fields 'depends' and 'depopts' refer to the same package names"~detail:OpamPackage.Name.(List.mapto_string(Set.elementsdup_depends))(not(OpamPackage.Name.Set.is_emptydup_depends)));cond32`Error"Field 'ocaml-version:' and variable 'ocaml-version' are deprecated, use \
a dependency towards the 'ocaml' package instead for availability, and \
the 'ocaml:version' package variable for scripts"(t.ocaml_version<>None||List.mem(OpamVariable.Full.of_string"ocaml-version")(all_variablest));cond33`Error"Field 'os' is deprecated, use 'available' and the 'os' variable \
instead"(t.os<>Empty);(letpkg_vars=List.filter(funv->not(OpamVariable.Full.is_globalv))(OpamFilter.variablest.available)incond34`Error"Field 'available:' contains references to package-local variables. \
It should only be determined from global configuration variables"~detail:(List.mapOpamVariable.Full.to_stringpkg_vars)(pkg_vars<>[]));cond35`Warning"Missing field 'homepage'"(t.homepage=[]);(* cond (t.doc = []) *)(* "Missing field 'doc'"; *)cond36`Warning"Missing field 'bug-reports'"(t.bug_reports=[]);cond37`Warning"Missing field 'dev-repo'"(t.dev_repo=None&&t.url<>None);(*
cond 38 `Warning
"Package declares 'depexts', but has no 'post-messages' to help \
the user out when they are missing"
(t.depexts <> None && t.post_messages = []);
*)cond39`Error"Command 'make' called directly, use the built-in variable \
instead"(List.exists(function|(CString"make",_)::_,_->true|_->false)all_commands);(*
cond 40 `Warning
"Field 'features' is still experimental and not yet to be used on \
the official repo"
(t.features <> []);
(let alpha_flags =
OpamStd.List.filter_map (function
| Pkgflag_LightUninstall | Pkgflag_Unknown _ -> None
| f ->
if List.exists (fun tag -> flag_of_tag tag = Some f) t.tags
then None
else Some (string_of_pkg_flag f))
t.flags
in
cond 40 `Warning
"Package uses flags that aren't recognised by earlier versions in \
OPAM 1.2 branch. At the moment, you should use a tag \"flags:foo\" \
instead for compatibility"
~detail:alpha_flags
(alpha_flags <> []));
*)(letundep_pkgs=List.fold_left(funaccv->matchOpamVariable.Full.packagevwith|Somenwhent.OpamFile.OPAM.name<>Somen&¬(OpamPackage.Name.Set.memnall_depends)&&OpamVariable.(Full.variablev<>of_string"installed")->OpamPackage.Name.Set.addnacc|_->acc)OpamPackage.Name.Set.empty(all_variables~exclude_post:truet)incond41`Warning"Some packages are mentioned in package scripts or features, but \
there is no dependency or depopt toward them"~detail:OpamPackage.Name.(List.mapto_string(Set.elementsundep_pkgs))(not(OpamPackage.Name.Set.is_emptyundep_pkgs)));cond42`Error"The 'dev-repo:' field doesn't use version control. You should use \
URLs of the form \"git://\", \"git+https://\", \"hg+https://\"..."(matcht.dev_repowith|None->false|Some{OpamUrl.backend=#OpamUrl.version_control;_}->false|Some_->true);cond43`Error"Conjunction used in 'conflicts:' field. Only '|' is allowed"(OpamVersion.comparet.opam_version(OpamVersion.of_string"1.3")>=0&&letrecors_only_constraint=function|Atom_|Empty->true|Or(a,b)->ors_only_constrainta&&ors_only_constraintb|And(a,Atom(Filter_))|And(Atom(Filter_),a)|Blocka->ors_only_constrainta|And_->falseinletreccheck=function|Atom(_,c)->ors_only_constraintc|Empty->true|Or(a,b)->checka&&checkb|Blocka->checka|And_->falseinnot(checkt.conflicts));cond44`Warning"The 'plugin' package flag is set but the package name doesn't \
begin with 'opam-'"(OpamVersion.comparet.opam_version(OpamVersion.of_string"1.3")>=0&&List.memPkgflag_Plugint.flags&&matcht.OpamFile.OPAM.namewith|None->false|Somename->not(OpamStd.String.starts_with~prefix:"opam-"(OpamPackage.Name.to_stringname)));(letunclosed=List.fold_left(funaccs->List.rev_append(OpamFilter.unclosed_expansionss)acc)[]all_expanded_stringsincond45`Error"Unclosed variable interpolations in strings"~detail:(List.mapsndunclosed)(unclosed<>[]));cond46`Error"Package is flagged \"conf\" but has source, install or remove \
instructions"(has_flagPkgflag_Conft&&(t.install<>[]||t.remove<>[]||t.url<>None||t.extra_sources<>[]));cond47`Warning"Synopsis should start with a capital and not end with a dot"(letvalid_re=Re.(compile(seq[bos;diffany(alt[blank;lower]);repany;diffany(alt[blank;char'.']);eos]))inmatcht.descrwithNone->false|Somed->not(Re.execpvalid_re(OpamFile.Descr.synopsisd)));cond48`Warning"The fields 'build-test:' and 'build-doc:' are deprecated, and should be \
replaced by uses of the 'with-test' and 'with-doc' filter variables in \
the 'build:' and 'install:' fields, and by the newer 'run-test:' \
field"(t.deprecated_build_test<>[]||t.deprecated_build_doc<>[]);(letsuspicious_urls=List.filter(funu->OpamUrl.parse~handle_suffix:true(OpamUrl.to_stringu)<>u)(all_urlst)incond49`Warning"The following URLs don't use version control but look like version \
control URLs"~detail:(List.mapOpamUrl.to_stringsuspicious_urls)(suspicious_urls<>[]));cond50`Warning"The 'post' flag doesn't make sense with build or optional \
dependencies"(List.mem(OpamVariable.Full.of_string"post")(List.flatten(List.mapOpamFilter.variables(filters_of_formulat.depopts)))||OpamFormula.fold_left(funacc(_,f)->acc||letvars=OpamFormula.fold_left(funvarsf->matchfwith|Constraint_->vars|Filterfi->OpamFilter.variablesfi@vars)[]finList.mem(OpamVariable.Full.of_string"build")vars&&List.mem(OpamVariable.Full.of_string"post")vars)falset.depends);cond51`Error"The behaviour for negated dependency flags 'build' or 'post' is \
unspecified"(OpamFormula.fold_left(funacc(_,f)->acc||OpamFormula.fold_left(funaccf->acc||matchfwith|Filterfi->OpamFilter.fold_down_left(funaccfi->acc||matchfiwith|FNot(FIdent([],var,None))->(matchOpamVariable.to_stringvarwith|"build"|"post"->true|_->false)|_->false)false(OpamFilter.distribute_negationsfi)|_->false)falsef)false(OpamFormula.ands[t.depends;t.depopts]));cond52`Error"Package is needlessly flagged \"light-uninstall\", since it has no \
remove instructions"(has_flagPkgflag_Conft&&t.remove=[]);(letmismatching_extra_files=matcht.extra_files,check_extra_fileswith|None,_|_,None->[]|Somefs,Some[]->List.mapfstfs|Someefiles,Someffiles->OpamStd.List.filter_map(fun(n,_)->ifList.mem_assocnffilesthenNoneelseSomen)efiles@OpamStd.List.filter_map(fun(n,check_f)->tryifcheck_f(List.assocnefiles)thenNoneelseSomenwithNot_found->Somen)ffilesincond53`Error"Mismatching 'extra-files:' field"~detail:(List.mapOpamFilename.Base.to_stringmismatching_extra_files)(mismatching_extra_files<>[]));(letspaced_depexts=List.concat(List.map(fun(dl,_)->List.filter(fund->String.containsd' '||String.lengthd=0)dl)t.depexts)incond54`Warning"External dependencies should not contain spaces nor empty string"~detail:spaced_depexts(spaced_depexts<>[]));(letbad_os_arch_values=List.fold_left(OpamFilter.fold_down_left(funacc->function|FOp(FIdent([],vname,None),_,FStringvalue)|FOp(FStringvalue,_,FIdent([],vname,None))->(matchOpamVariable.to_stringvnamewith|"os"->letnorm=OpamSysPoll.normalise_osvalueinifvalue<>normthen(value,norm)::accelseacc|"arch"->letnorm=OpamSysPoll.normalise_archvalueinifvalue<>normthen(value,norm)::accelseacc|_->acc)|_->acc))[](all_filterst)incond55`Error"Non-normalised OS or arch string being tested"~detail:(List.map(fun(used,norm)->Printf.sprintf"%s (use %s instead)"usednorm)bad_os_arch_values)(bad_os_arch_values<>[]));]informat_errors@OpamStd.List.filter_map(funx->x)warningsletextra_files_defaultfilename=letdir=OpamFilename.Op.(OpamFilename.dirname(OpamFile.filenamefilename)/"files")inList.map(funf->OpamFilename.Base.of_string(OpamFilename.remove_prefixdirf),OpamHash.check_file(OpamFilename.to_stringf))(OpamFilename.rec_filesdir)letlint_gen?check_extra_filesreaderfilename=letwarnings,t=letwarn_of_bad_format(pos,msg)=2,`Error,Printf.sprintf"File format error%s: %s"(matchposwith|Some(_,li,col)whenli>=0&&col>=0->Printf.sprintf" at line %d, column %d"licol|_->"")msgintryletf=readerfilenameinlet_,t=OpamPp.parse~pos:(pos_file(OpamFile.filenamefilename))(OpamFormat.I.map_fileOpamFile.OPAM.pp_raw_fields)finlett,warnings=matchOpamPackage.of_filename(OpamFile.filenamefilename)with|None->t,[]|Somenv->letfname=nv.OpamPackage.nameinletfversion=nv.OpamPackage.versioninlett,name_warn=matcht.OpamFile.OPAM.namewith|Sometname->iftname=fnamethent,[]elset,[4,`Warning,Printf.sprintf"Field 'name: %S' while the directory name or pinning \
implied %S"(OpamPackage.Name.to_stringtname)(OpamPackage.Name.to_stringfname)]|None->OpamFile.OPAM.with_namefnamet,[]inlett,version_warn=matcht.OpamFile.OPAM.versionwith|Sometversion->iftversion=fversionthent,[]elset,[4,`Warning,Printf.sprintf"Field 'version: %S' while the directory name or pinning \
implied %S"(OpamPackage.Version.to_stringtversion)(OpamPackage.Version.to_stringfversion)]|None->OpamFile.OPAM.with_versionfversiont,[]int,name_warn@version_warninwarnings,Some(OpamFile.OPAM.with_metadata_dir(Some(OpamFilename.dirname(OpamFile.filenamefilename)))t)with|OpamSystem.File_not_found_->OpamConsole.error"%s not found"(OpamFile.to_stringfilename);[0,`Error,"File does not exist"],None|OpamLexer.Error_|Parsing.Parse_error->[1,`Error,"File does not parse"],None|OpamPp.Bad_formatbf->[warn_of_bad_formatbf],None|OpamPp.Bad_format_listbfl->List.mapwarn_of_bad_formatbfl,Noneinletcheck_extra_files=matchcheck_extra_fileswith|None->extra_files_defaultfilename|Somef->finwarnings@(matchtwithSomet->lint~check_extra_filest|None->[]),tletlint_file?check_extra_filesfilename=letreaderfilename=tryletic=OpamFilename.open_in(OpamFile.filenamefilename)intryletf=OpamFile.Syntax.of_channelfilenameicinclose_inic;fwithe->close_inic;raiseewithOpamSystem.File_not_found_->OpamConsole.error_and_exit`Bad_arguments"File %s not found"(OpamFile.to_stringfilename)inlint_gen?check_extra_filesreaderfilenameletlint_channel?check_extra_filesfilenameic=letreaderfilename=OpamFile.Syntax.of_channelfilenameicinlint_gen?check_extra_filesreaderfilenameletlint_string?check_extra_filesfilenamestring=letreaderfilename=OpamFile.Syntax.of_stringfilenamestringinlint_gen?check_extra_filesreaderfilenameletwarns_to_stringws=OpamStd.List.concat_map"\n"(fun(n,w,s)->letws=matchwwith|`Warning->OpamConsole.colorise`yellow"warning"|`Error->OpamConsole.colorise`red"error"inOpamStd.Format.reformat~indent:14(Printf.sprintf" %16s %2d: %s"wsns))ws(* Package definition loading *)openOpamFilename.OpopenOpamStd.Option.Oplettry_readrdf=tryrdf,Nonewith|(OpamSystem.Internal_error_|Not_found)asexc->ifOpamFormatConfig.(!r.strict)thenOpamConsole.error_and_exit`File_error"Could not read file %s: %s.\nAborting (strict mode)."(OpamFile.to_stringf)(Printexc.to_stringexc);None,letf=OpamFile.filenamefinSome(OpamFilename.(Base.to_string(basenamef)),(Some(pos_filef),Printexc.to_stringexc))|OpamPp.Bad_formatbfasexc->ifOpamFormatConfig.(!r.strict)thenOpamConsole.error_and_exit`File_error"Errors while parsing %s: %s.\nAborting (strict mode)."(OpamFile.to_stringf)(Printexc.to_stringexc);None,letf=OpamFile.filenamefinSome(OpamFilename.(Base.to_string(basenamef)),bf)letadd_aux_files?dir~files_subdir_hashesopam=letdir=matchdirwith|None->OpamFile.OPAM.metadata_diropam|some->someinmatchdirwith|None->opam|Somedir->let(url_file:OpamFile.URL.tOpamFile.t)=OpamFile.make(dir//"url")inlet(descr_file:OpamFile.Descr.tOpamFile.t)=OpamFile.make(dir//"descr")inletfiles_dir=OpamFilename.Op.(dir/"files")inletopam=matchOpamFile.OPAM.urlopam,try_readOpamFile.URL.read_opturl_filewith|None,(Someurl,None)->OpamFile.OPAM.with_urlurlopam|Someopam_url,(Someurl,errs)->ifurl=opam_url&&errs=Nonethenlog"Duplicate definition of url in '%s' and opam file"(OpamFile.to_stringurl_file)elseOpamConsole.warning"File '%s' ignored (conflicting url already specified in the \
'opam' file)"(OpamFile.to_stringurl_file);opam|_,(_,Someerr)->OpamFile.OPAM.with_format_errors(err::opam.format_errors)opam|_,(None,None)->opaminletopam=matchOpamFile.OPAM.descropam,try_readOpamFile.Descr.read_optdescr_filewith|None,(Somedescr,None)->OpamFile.OPAM.with_descrdescropam|Some_,(Some_,_)->log"Duplicate descr in '%s' and opam file"(OpamFile.to_stringdescr_file);opam|_,(_,Someerr)->OpamFile.OPAM.with_format_errors(err::opam.format_errors)opam|_,(None,None)->opaminletopam=ifnotfiles_subdir_hashesthenopamelseletextra_files=OpamFilename.opt_dirfiles_dir>>|fundir->List.map(funf->OpamFilename.Base.of_string(OpamFilename.remove_prefixdirf),OpamHash.compute(OpamFilename.to_stringf))(OpamFilename.rec_filesdir)inmatchOpamFile.OPAM.extra_filesopam,extra_fileswith|None,None->opam|None,Someef->OpamFile.OPAM.with_extra_filesefopam|Someef,None->log"Missing expected extra files %s at %s/files"(OpamStd.List.concat_map", "(fun(f,_)->OpamFilename.Base.to_stringf)ef)(OpamFilename.Dir.to_stringdir);opam|Someoef,Someef->ifoef<>efthenlog"Mismatching extra-files at %s"(OpamFilename.Dir.to_stringdir);opaminopamletread_opamdir=let(opam_file:OpamFile.OPAM.tOpamFile.t)=OpamFile.make(dir//"opam")inmatchtry_readOpamFile.OPAM.read_optopam_filewith|Someopam,None->Some(add_aux_files~dir~files_subdir_hashes:trueopam)|_,Someerr->OpamConsole.warning"Could not read file %s. skipping:\n%s"(OpamFile.to_stringopam_file)(OpamPp.string_of_bad_format(OpamPp.Bad_format(snderr)));None|None,None->None