123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195(**************************************************************************)(* *)(* Copyright 2012-2019 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. *)(* *)(**************************************************************************)openOpamTypesopenOpamProcess.Job.Opletlogfmt=OpamConsole.log"CURL"fmtexceptionDownload_failofstringoption*stringletfail(s,l)=raise(Download_fail(s,l))letuser_agent=CString(Printf.sprintf"opam/%s"(OpamVersion.(to_stringcurrent)))letcurl_args=[CString"--write-out",None;CString"%%{http_code}\\n",None;CString"--retry",None;CIdent"retry",None;CString"--retry-delay",None;CString"2",None;CString"--compressed",Some(FIdent(OpamFilter.ident_of_string"compress"));CString"--user-agent",None;user_agent,None;CString"-L",None;CString"-o",None;CIdent"out",None;CString"--",None;(* End list of options *)CIdent"url",None;]letwget_args=[CString"--content-disposition",None;CString"-t",None;CIdent"retry",None;CString"-O",None;CIdent"out",None;CString"-U",None;user_agent,None;CString"--",None;(* End list of options *)CIdent"url",None;]letfetch_args=[CString"-o",None;CIdent"out",None;CString"--user-agent",None;user_agent,None;CString"--",None;(* End list of options *)CIdent"url",None;]letftp_args=[CString"-o",None;CIdent"out",None;CString"-U",None;user_agent,None;CString"--",None;(* End list of options *)CIdent"url",None;]letdownload_args~url~out~retry?checksum~compress()=letcmd,_=Lazy.forceOpamRepositoryConfig.(!r.download_tool)inletcmd=matchcmdwith|[(CIdent"wget"),_]->cmd@wget_args|[(CIdent"fetch"),_]->cmd@fetch_args|[(CIdent"ftp"),_]->cmd@ftp_args|[_]->cmd@curl_args(* Assume curl if the command is a single arg *)|_->cmdinOpamFilter.single_command(funv->ifnot(OpamVariable.Full.is_globalv)thenNoneelsematchOpamVariable.to_string(OpamVariable.Full.variablev)with|("curl"|"wget"|"fetch"|"ftp")asdl_tool->Some(Sdl_tool)|"url"->Some(S(OpamUrl.to_stringurl))|"out"->Some(Sout)|"retry"->Some(S(string_of_intretry))|"compress"->Some(Bcompress)|"opam-version"->Some(SOpamVersion.(to_stringcurrent))|"checksum"->OpamStd.Option.map(func->SOpamHash.(to_stringc))checksum|"hashalgo"->OpamStd.Option.map(func->SOpamHash.(string_of_kind(kindc)))checksum|"hashpath"->OpamStd.Option.map(func->S(String.concatFilename.dir_sepOpamHash.(to_pathc)))checksum|"hashvalue"->OpamStd.Option.map(func->SOpamHash.(contentsc))checksum|_->None)cmdlettool_returnurlret=matchLazy.forceOpamRepositoryConfig.(!r.download_tool)with|_,`Default->ifOpamProcess.is_failureretthenfail(Some"Download command failed",Printf.sprintf"Download command failed: %s"(OpamProcess.result_summaryret))elseDone()|_,`Curl->ifOpamProcess.is_failureretthenfail(Some"Curl failed",Printf.sprintf"Curl failed: %s"(OpamProcess.result_summaryret));matchret.OpamProcess.r_stdoutwith|[]->fail(Some"curl empty response",Printf.sprintf"curl: empty response while downloading %s"(OpamUrl.to_stringurl))|l->letcode=List.hd(List.revl)inletnum=tryint_of_stringcodewithFailure_->999inifnum>=400thenfail(Some("curl error code "^code),Printf.sprintf"curl: code %s while downloading %s"code(OpamUrl.to_stringurl))elseDone()letdownload_command~compress?checksum~url~dst()=letcmd,args=matchdownload_args~url~out:dst~retry:OpamRepositoryConfig.(!r.retries)?checksum~compress()with|cmd::args->cmd,args|[]->OpamConsole.error_and_exit`Configuration_error"Empty custom download command"inOpamSystem.make_commandcmdargs@@>tool_returnurlletreally_download?(quiet=false)~overwrite?(compress=false)?checksum?(validate=true)~url~dst()=assert(url.OpamUrl.backend=`http);lettmp_dst=dst^".part"inifSys.file_existstmp_dstthenOpamSystem.removetmp_dst;OpamProcess.Job.catch(function|Failuresase->OpamSystem.removetmp_dst;ifnotquietthenOpamConsole.error"%s"s;raisee|e->OpamSystem.removetmp_dst;OpamStd.Exn.fatale;log"Could not download file at %s."(OpamUrl.to_stringurl);raisee)@@fun()->download_command~compress?checksum~url~dst:tmp_dst()@@+fun()->ifnot(Sys.file_existstmp_dst)thenfail(Some"Downloaded file not found","Download command succeeded, but resulting file not found")elseifSys.file_existsdst&¬overwritethenOpamSystem.internal_error"The downloaded file will overwrite %s."dst;ifvalidate&&OpamRepositoryConfig.(!r.force_checksums<>Somefalse)thenOpamStd.Option.iter(funcksum->ifnot(OpamHash.check_filetmp_dstcksum)thenfail(Some"Bad checksum",Printf.sprintf"Bad checksum, expected %s"(OpamHash.to_stringcksum)))checksum;OpamSystem.mvtmp_dstdst;Done()letdownload_as?quiet?validate~overwrite?compress?checksumurldst=matchOpamUrl.local_fileurlwith|Somesrc->ifsrc=dstthenDone()else(ifOpamFilename.existsdstthenifoverwritethenOpamFilename.removedstelseOpamSystem.internal_error"The downloaded file will overwrite %s."(OpamFilename.to_stringdst);OpamFilename.copy~src~dst;Done())|None->OpamFilename.(mkdir(dirnamedst));really_download?quiet~overwrite?compress?checksum?validate~url~dst:(OpamFilename.to_stringdst)()letdownload?quiet?validate~overwrite?compress?checksumurldstdir=letdst=OpamFilename.(createdstdir(Base.of_string(OpamUrl.basenameurl)))indownload_as?quiet?validate~overwrite?compress?checksumurldst@@|fun()->dst