123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205(**************************************************************************)(* *)(* 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. *)(* *)(**************************************************************************)openOpamTypesopenOpamStateTypesopenOpamFilename.Opletpackagestname=OpamPackage.package_of_namest.pinnednameletpackage_optstname=trySome(packagestname)withNot_found->Noneletversionstname=(packagestname).versionletpackagesst=st.pinnedletpossible_definition_filenamesdirname=[dir/(OpamPackage.Name.to_stringname^".opam")//"opam";dir//(OpamPackage.Name.to_stringname^".opam");dir/"opam"/(OpamPackage.Name.to_stringname^".opam")//"opam";dir/"opam"//(OpamPackage.Name.to_stringname^".opam");dir/"opam"//"opam";dir//"opam"]letcheck_lockeddefault=matchOpamStateConfig.(!r.locked)with|None->default|Someext->letfl=OpamFilename.add_extensiondefaultextinifOpamFilename.existsflthen(letbase_depends=OpamFile.makedefault|>OpamFile.OPAM.read|>OpamFile.OPAM.dependsinletlock_depends=OpamFile.makefl|>OpamFile.OPAM.read|>OpamFile.OPAM.dependsinletldep_names=OpamFormula.fold_left(funacc(n,_)->OpamPackage.Name.Set.addnacc)OpamPackage.Name.Set.emptylock_dependsinletbase_formula=OpamFilter.filter_deps~build:true~post:true~test:true~doc:true~dev:truebase_dependsinletlock_formula=OpamFilter.filter_deps~build:true~post:true~test:true~doc:true~dev:truelock_dependsinletlpkg_f=lock_formula|>OpamFormula.atoms|>OpamPackage.Name.Map.of_listin(* Check consistency between them. It is based on the fact that locked file
dependencies are an and list with precise version, i.e., pkg { =v0.1}.
Construction of a two list: missing dependencies and inconsistent ones
(version mismatch) *)let(@)=List.rev_appendinletrecfoldformula=List.fold_leftcross([],[])(OpamFormula.ands_to_listformula)andcross(cont,cons)formula=matchformulawith|Atom(bn,bvf)->(letcont=ifOpamPackage.Name.Set.membnldep_namesthencontelsebn::continletcons=matchOpamPackage.Name.Map.find_optbnlpkg_fwith|Some(Some(`Eq,lv))->ifOpamFormula.check_version_formulabvflvthenconselse(bn,lv,bvf)::cons|_->consin(cont,cons))|Or(or1,or2)->letor1_cont,or1_cons=foldor1inletor2_cont,or2_cons=foldor2inletcont=ifor1_cont=[]||or2_cont=[]thencontelseor1_cont@or2_cont@continletcons=ifor1_cons=[]||or2_cons=[]thenconselseor1_cons@or2_cons@consin(cont,cons)|And(and1,and2)->letand1_cont,and1_cons=foldand1inletand2_cont,and2_cons=foldand2in((and1_cont@and2_cont@cont),(and1_cons@and2_cons@cons))|Blockf->cross(cont,cons)f|Empty->(cont,cons)inletcontains,consistent=foldbase_formulainifcontains<>[]||consistent<>[]then(OpamConsole.warning"Lock file %s is outdated, you may want to re-run opam lock:\n%s"(OpamConsole.colorise`underline(OpamFilename.Base.to_string(OpamFilename.basenamefl)))((ifcontains<>[]thenPrintf.sprintf"Dependencies present in opam file not in lock file:\n%s"(OpamStd.Format.itemizeOpamPackage.Name.to_stringcontains)else"")^(ifconsistent<>[]thenPrintf.sprintf"Dependencies in lock file not consistent wit opam file filter:\n%s"(OpamStd.Format.itemize(fun(n,lv,(bv:OpamFormula.version_formula))->Printf.sprintf"%s: %s in not contained in {%s}"(OpamPackage.Name.to_stringn)(OpamPackage.Version.to_stringlv)(OpamFormula.string_of_formula(fun(op,vc)->Printf.sprintf"%s %s"(OpamPrinter.relopop)(OpamPackage.Version.to_stringvc))bv))consistent)else"")));fl)else(OpamConsole.warning"Lock-file %s doesn't exist, using %s instead."(OpamConsole.colorise`underline(OpamFilename.to_stringfl))(OpamFilename.to_stringdefault);default)letfind_opam_file_in_sourcenamedir=letopt=OpamStd.List.find_optOpamFilename.exists(possible_definition_filenamesdirname)in(matchoptwith|Somebase->Some(check_lockedbase)|_->opt)|>OpamStd.Option.mapOpamFile.makeletname_of_opam_filenamedirfile=letopenOpamStd.Option.Opinletsuffix=".opam"inletget_names=ifFilename.check_suffixssuffixthenSomeFilename.(chop_suffix(basenames)suffix)elseNoneinletrel=OpamFilename.remove_prefixdirfileinletrel=matchOpamStateConfig.(!r.locked)with|None->rel|Somesuf->letext="."^sufinifOpamStd.String.ends_with~suffix:(suffix^ext)relthenOpamStd.String.remove_suffix~suffix:extrelelserelin(get_name(Filename.basenamerel)>>+fun()->get_name(Filename.dirnamerel))>>=funname->trySome(OpamPackage.Name.of_stringname)withFailure_->Noneletfiles_in_sourced=letbaseopam=OpamFilename.Base.of_string"opam"inletfilesd=List.filter(funf->OpamFilename.basenamef=baseopam||OpamFilename.check_suffixf".opam")(OpamFilename.filesd)@OpamStd.List.filter_map(fund->ifOpamFilename.(basename_dird=Base.of_string"opam")||OpamStd.String.ends_with~suffix:".opam"(OpamFilename.Dir.to_stringd)thenOpamFilename.opt_fileOpamFilename.Op.(d//"opam")elseNone)(OpamFilename.dirsd)infilesd@files(d/"opam")|>List.mapcheck_locked|>OpamStd.List.filter_map(funf->try(* Ignore empty files *)if(Unix.stat(OpamFilename.to_stringf)).Unix.st_size=0thenNoneelseSome(name_of_opam_filenamedf,OpamFile.makef)withUnix.Unix_error_->OpamConsole.error"Can not read %s, ignored."(OpamFilename.to_stringf);None)letorig_opam_filenameopam=letopenOpamStd.Option.OpinOpamFile.OPAM.metadata_diropam>>=fundir->OpamStd.List.find_optOpamFilename.exists[dir//(OpamPackage.Name.to_stringname^".opam");dir//"opam"]>>|OpamFile.make