123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162(* FIXME: implement prefix subdirs to avoid too many objects in one
dir, like aa/aa545 *)openCoreopenRresulttypeid=stringletok_exn=function|Okx->x|Error(`Msgmsg)->failwithmsgletfilter_errorsxs=List.filter_mapxs~f:(function|Ok_->None|Errore->Somee)let(/)=Filename.concattypet=stringletcache_dirbase=base/"cache"letbuild_dirbase=base/"build"lettmp_dirbase=base/"tmp"letstderr_dirbase=base/"stderr"letstdout_dirbase=base/"stdout"letsingularity_image_dirbase=base/"singularity_image"letget_objfdbid=Filename.concat(fdb)idletcache=get_objcache_dirletbuild=get_objbuild_dirlettmp=get_objtmp_dirletstdout=get_objstdout_dirletstderr=get_objstderr_dirletcreate_dbpath=Unix.mkdir_p(tmp_dirpath);Unix.mkdir_p(build_dirpath);Unix.mkdir_p(cache_dirpath);Unix.mkdir_p(stderr_dirpath);Unix.mkdir_p(stdout_dirpath);Unix.mkdir_p(singularity_image_dirpath);Ok()letdir_is_emptypath=Sys.readdirpath=[||]letno_such_path_errorpath=R.error_msgf"Path %s doesn't exist, is not readable or writable"path(* [check_path sort p] checks that [p] exists and is of the right
sort *)letcheck_pathsortp=ifSys.file_existsp=`Yesthenmatchsortwith|`Dir->ifSys.is_directoryp=`YesthenOk()elseR.error_msgf"Path %s should be a directory"p|`File->ifSys.is_filep=`YesthenOk()elseR.error_msgf"Path %s should be a file"pelseno_such_path_errorpletdirs_of_db_existpath=letdir_paths=[path;cache_dirpath;build_dirpath;tmp_dirpath;stderr_dirpath;stdout_dirpath;singularity_image_dirpath;]inletchecks=List.mapdir_paths~f:(check_path`Dir)inmatchfilter_errorscheckswith|[]->Ok()|h::t->R.reword_error_msg(fun_->`Msg(sprintf"Malformed database at %s"path))(Error(List.foldt~init:h~f:(fun(`Msgaccu)(`Msgmsg)->`Msg(accu^"\n"^msg))))letdb_is_well_formedpath=dirs_of_db_existpathletpath_has_valid_dbpath=R.reword_error_msg(fun_->R.msg"Failed to obtain a valid bistro database")(matchSys.file_existspathwith|`Yes->ifdir_is_emptypaththencreate_dbpathelsedb_is_well_formedpath|`No->create_dbpath|`Unknown->no_such_path_errorpath)letinitpath=letpath=ifFilename.is_relativepaththenFilename.concat(Sys.getcwd())pathelsepathinpath_has_valid_dbpath>>|fun()->pathletinit_exnpath=ok_exn(initpath)letfold_cachedb~init~f=Array.fold(Sys.readdir(cache_dirdb))~init~fletrecpath:t->Bistro_internals.Workflow.path->string=fundbp->matchpwith|FS_pathx->x|Cache_idid->cachedbid|Cd(dir,sel)->Filename.concat(pathdbdir)(Path.to_stringsel)letrecworkflow_pathdb(Bistro_internals.Workflow.Anyw)=letopenBistro_internals.Workflowinmatchwwith|Input{path;_}->Some(FS_path(Misc.absolutizepath))|Select{dir;sel;_}->workflow_pathdb(Anydir)|>Option.map~f:(fund->Cd(d,sel))|Shell{id;_}->Some(Cache_idid)|Plugin{id;task=Path_plugin_;_}->Some(Cache_idid)|Plugin{id;task=Value_plugin_;_}->Some(Cache_idid)|_->Noneletis_in_cachedbu=workflow_pathdbu|>Option.value_map~default:false~f:(funu->Sys.file_exists(pathdbu)=`Yes)letcontainer_image_identifierimg=letfaccountnametag=sprintf"%s_%s%s_%s.sif"accountname(Option.value_maptag~default:""~f:((^)"_"))(Bistro_internals.Workflow.digestimg)inmatch(img:Bistro_internals.Command.container_image)with|Docker_imagei->fi.accounti.namei.tag|Singularity_imagei->fi.accounti.namei.tagletsingularity_imagedbimg=Filename.concat(singularity_image_dirdb)(container_image_identifierimg)