1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354moduleSys=Stdlib.SysmoduleFpath=structletis_roott=Filename.dirnamet=tletrecmkdir_p?(perms=0o777)t_s=ifis_roott_sthen()elsetryUnix.mkdirt_spermswith|Unix.Unix_error(EEXIST,_,_)->()|Unix.Unix_error(ENOENT,_,_)ase->letparent=Filename.dirnamet_sinifis_rootparentthenraiseeelse(mkdir_pparent~perms;Unix.mkdirt_sperms)endletbasename_opt~is_root~basenamet=ifis_roottthenNoneelseSome(basenamet)letis_dir_sep=ifSys.win32||Sys.cygwinthenfunc->c='/'||c='\\'||c=':'elsefunc->c='/'letexplode_path=letrecstartaccpathi=ifi<0thenaccelseifis_dir_sep(String.unsafe_getpathi)thenstartaccpath(i-1)elsecomponentaccpathi(i-1)andcomponentaccpathend_i=ifi<0thenString.takepath(end_+1)::accelseifis_dir_sep(String.unsafe_getpathi)thenstart(String.subpath~pos:(i+1)~len:(end_-i)::acc)path(i-1)elsecomponentaccpathend_(i-1)infunpath->ifpath=Filename.current_dir_namethen[path]elsematchstart[]path(String.lengthpath-1)with|"."::xs->xs|xs->xsmoduleExternal:sigincludePath_intf.Svalrelative:t->string->tvalmkdir_p:?perms:int->t->unitvalinitial_cwd:tvalcwd:unit->tvalas_local:t->stringend=structmoduleT=Interned.No_interning(structletinitial_size=512letresize_policy=Interned.Greedyletorder=Interned.Naturalend)()moduleTable=Hashtbl.Make(T)typet=T.tletto_string=T.to_stringletmake=T.makeletequal=T.equallethash=T.hashletcompare=T.compareletas_stringx~f=to_stringx|>f|>makeletextend_basenamet~suffix=as_stringt~f:(funt->t^suffix)letof_stringt=ifFilename.is_relativetthenCode_error.raise"Path.External.of_string: relative path given"[("t",Stringt)];maketletparse_string_exn~loct=ifFilename.is_relativetthenUser_error.raise~loc[Pp.textf"path %s is not absolute"t];maketletto_dynt=Dyn.String(to_stringt)(* let rec cd_dot_dot t = match Unix.readlink t with | exception _ ->
Filename.dirname t | t -> cd_dot_dot t
let relative initial_t path = let rec loop t components = match components
with | [] | ["." | ".."] -> die "invalid filename concatenation: %s / %s"
initial_t path | [fn] -> Filename.concat t fn | "." :: rest -> loop t rest
| ".." :: rest -> loop (cd_dot_dot t) rest | comp :: rest -> loop
(Filename.concat t comp) rest in loop initial_t (explode_path path) *)letrelativexy=matchywith|"."->x|_->make(Filename.concat(to_stringx)y)letbasenamet=Filename.basename(to_stringt)letroot=of_string"/"letis_root=equalrootletbasename_opt=basename_opt~is_root~basenameletparentt=ifis_roottthenNoneelseSome(as_stringt~f:Filename.dirname)letparent_exnt=matchparenttwith|None->Code_error.raise"Path.External.parent_exn called on a root path"[]|Somep->pletmkdir_p?permsp=Fpath.mkdir_p?perms(to_stringp)letextensiont=Filename.extension(to_stringt)letsplit_extensiont=lets,ext=Filename.split_extension(to_stringt)in(makes,ext)letset_extensiont~ext=letbase,_=split_extensiontinto_stringbase^ext|>makeletcwd()=make(Sys.getcwd())letinitial_cwd=cwd()letas_localt=lets=to_stringtin"."^sinclude(Comparator.Operators(structtypenonrect=tletcompare=compareend):Comparator.OPSwithtypet:=t)letto_string_maybe_quotedt=String.maybe_quoted(to_stringt)letis_descendantb~of_:a=ifis_rootathentrueelseString.is_prefix~prefix:(to_stringa^"/")(to_stringb)moduleSet=structincludeT.Setletof_listing~dir~filenames=of_list_mapfilenames~f:(funf->relativedirf)endmoduleMap=T.MapendmoduleUnspecified=Path_intf.UnspecifiedmoduleLocal_gen:sigincludePath_intf.Local_genmodulePrefix:sigtype'wlocal='wttype'wtvalmake:'wlocal->'wtvaldrop:'wt->'wlocal->'wlocaloption(* for all local path p, drop (invalid p = None) *)valinvalid:'wtendwithtype'wlocal:='wtend=struct(* either "." for root, or a '/' separated list of components other that ".",
".." and not containing '/'. *)moduleT=Interned.No_interning(structletinitial_size=512letresize_policy=Interned.Greedyletorder=Interned.Naturalend)()moduleTable=Hashtbl.Make(T)type_t=T.tletto_string=T.to_stringletmake=T.makelethash=T.hashletcompare=T.compareletroot=make"."letis_roott=Ordering.is_eq(comparetroot)letto_list=letreclooptaccij=ifi=0thenString.taketj::accelsematcht.[i-1]with|'/'->loopt(String.subt~pos:i~len:(j-i)::acc)(i-1)(i-1)|_->looptacc(i-1)jinfunt->ifis_roottthen[]elselett=to_stringtinletlen=String.lengthtinloopt[]lenlenletparentt=ifis_roottthenNoneelselett=to_stringtinmatchString.rindex_fromt(String.lengtht-1)'/'with|None->Someroot|Somei->Some(make(String.taketi))letbasenamet=ifis_roottthenCode_error.raise"Path.Local.basename called on the root"[]elselett=to_stringtinletlen=String.lengthtinmatchString.rindex_fromt(len-1)'/'with|None->t|Somei->String.subt~pos:(i+1)~len:(len-i-1)letto_dynt=Dyn.String(to_stringt)moduleL=structletrelative_resulttcomponents=letreclooptcomponents=matchcomponentswith|[]->Result.Okt|"."::rest->looptrest|".."::rest->(ifis_roottthenResult.Error()elsematchparenttwith|None->Error()|Someparent->loopparentrest)|fn::rest->ifis_roottthenloop(makefn)restelseloop(make(to_stringt^"/"^fn))restinlooptcomponentsletrelative?error_loctcomponents=matchrelative_resulttcomponentswith|Result.Okt->t|Error()->User_error.raise?loc:error_loc[Pp.textf"path outside the workspace: %s from %s"(String.concat~sep:"/"components)(to_stringt)]endletrelative?error_loctpath=ifnot(Filename.is_relativepath)thenCode_error.raise"Local.relative: received absolute path"[("t",to_dynt);("path",Stringpath)];matchL.relative_resultt(explode_pathpath)with|Result.Okt->t|Error()->User_error.raise?loc:error_loc[Pp.textf"path outside the workspace: %s from %s"path(to_stringt)]letis_canonicalized=letrecbefore_slashsi=ifi<0thenfalseelsematchs.[i]with|'/'->false|'.'->before_dot_slashs(i-1)|_->in_components(i-1)andbefore_dot_slashsi=ifi<0thenfalseelsematchs.[i]with|'/'->false|'.'->before_dot_dot_slashs(i-1)|_->in_components(i-1)andbefore_dot_dot_slashsi=ifi<0thenfalseelsematchs.[i]with|'/'->false|_->in_components(i-1)andin_componentsi=ifi<0thentrueelsematchs.[i]with|'/'->before_slashs(i-1)|_->in_components(i-1)infuns->letlen=String.lengthsinlen=0||before_slashs(len-1)letparse_string_exn~locs=matchswith|""|"."->root|_whenis_canonicalizeds->makes|_->relativeroots~error_loc:locletof_strings=parse_string_exn~loc:Loc0.nonesletappendab=match(is_roota,is_rootb)with|true,_->b|_,true->a|_,_->make(to_stringa^"/"^to_stringb)letdescendantt~of_=ifis_rootof_thenSometelseift=of_thenSomerootelselett=to_stringtinletof_=to_stringof_inletof_len=String.lengthof_inlett_len=String.lengthtinift_len>of_len&&t.[of_len]='/'&&String.is_prefixt~prefix:of_thenSome(make(String.dropt(of_len+1)))elseNoneletis_descendantt~of_=is_rootof_||t=of_||lett=to_stringtinletof_=to_stringof_inletof_len=String.lengthof_inlett_len=String.lengthtint_len>of_len&&t.[of_len]='/'&&String.is_prefixt~prefix:of_letreacht~from=letreclooptfrom=match(t,from)with|a::t,b::fromwhena=b->looptfrom|_->(matchList.fold_leftfrom~init:t~f:(funacc_->".."::acc)with|[]->"."|l->String.concatl~sep:"/")inloop(to_listt)(to_listfrom)letextend_basenamet~suffix=make(to_stringt^suffix)letextensiont=Filename.extension(to_stringt)letsplit_extensiont=lets,ext=Filename.split_extension(to_stringt)in(makes,ext)letset_extensiont~ext=letbase,_=split_extensiontinto_stringbase^ext|>makemodulePrefix=structletmake_path=maketype_t={len:int;path:string;path_slash:string}letmakep=ifis_rootpthenCode_error.raise"Path.Local.Prefix.make"[("path",to_dynp)];letp=to_stringpin{len=String.lengthp;path=p;path_slash=p^"/"}letdroptp=letp=to_stringpinletlen=String.lengthpiniflen=t.len&&p=t.paththenSomerootelseString.drop_prefixp~prefix:t.path_slash|>Option.map~f:make_pathletinvalid={len=-1;path="/";path_slash="/"}endletsplit_first_componentt=ifis_roottthenNoneelselett=to_stringtinmatchString.lsplit2t~on:'/'with|None->Some(t,root)|Some(before,after)->Some(before,after|>of_string)letexplodep=ifis_rootpthen[]elseString.split(to_stringp)~on:'/'letto_string_maybe_quotedt=String.maybe_quoted(to_stringt)letparent_exnt=matchparenttwith|None->Code_error.raise"Path.Local.parent:exn t is root"[("t",to_dynt)]|Someparent->parentmoduleFix_root(Root:sigtypewend)=structtype_w=Root.wmoduleSet=structincludeT.Setletof_listing~dir~filenames=of_list_mapfilenames~f:(funf->relativedirf)endmoduleMap=T.MapmoduleTable=TableendendmoduleLocal:sigtypew=Unspecified.wtypet=wLocal_gen.tincludePath_intf.Swithtypet:=tvalroot:tvalis_root:t->boolvalrelative:?error_loc:Loc0.t->t->string->tvalappend:t->t->tvaldescendant:t->of_:t->toptionvalis_descendant:t->of_:t->boolvalreach:t->from:t->stringmoduleL:sigvalrelative:?error_loc:Loc0.t->t->stringlist->tendvalsplit_first_component:t->(string*t)optionvalexplode:t->stringlistvalof_local:t->tmodulePrefix:sigtypelocal=ttypetvalmake:local->tvaldrop:t->local->localoption(* for all local path p, drop (invalid p = None) *)valinvalid:tendwithtypelocal:=tend=structtypew=Unspecified.winclude(Local_gen:moduletypeofLocal_genwithtype'at:='aLocal_gen.twithmodulePrefix:=Local_gen.Prefix)typenonrect=wLocal_gen.tmodulePrefix=structopenLocal_geninclude(Prefix:moduletypeofPrefixwithtype'at:='aPrefix.t)typet=wPrefix.tendinclude(Comparator.Operators(structtypenonrect=tletcompare=Local_gen.compareend):Comparator.OPSwithtypet:=t)letof_localt=tincludeFix_root(structtypenonrecw=wend)letbasename_opt=basename_opt~is_root~basenameendmoduleRelative_to_source_root=structletmkdir_p?permss=Fpath.mkdir_p?perms(Local.to_strings)endmoduleSource0=Localletabs_root,set_root=letroot_dir=refNoneinletset_rootnew_root=match!root_dirwith|None->root_dir:=Somenew_root|Someroot_dir->Code_error.raise"set_root: cannot set root_dir more than once"[("root_dir",External.to_dynroot_dir);("new_root_dir",External.to_dynnew_root)]inletabs_root=lazy(match!root_dirwith|None->Code_error.raise"root_dir: cannot use root dir before it's set"[]|Someroot_dir->root_dir)in(abs_root,set_root)moduleKind=structtypet=|ExternalofExternal.t|In_source_dirofLocal.tletto_absolute_filenamet=matchtwith|Externals->External.to_strings|In_source_dirl->External.to_string(External.relative(Lazy.forceabs_root)(Local.to_stringl))letto_string=function|In_source_dirt->Local.to_stringt|Externalt->External.to_stringtletto_dynt=Dyn.String(to_stringt)letof_strings=ifFilename.is_relativesthenIn_source_dir(Local.of_strings)elseExternal(External.of_strings)letmkdir_p?perms=function|In_source_dirt->Relative_to_source_root.mkdir_p?permst|Externalt->External.mkdir_p?permstletappend_localxy=matchxwith|In_source_dirx->In_source_dir(Local.appendxy)|Externalx->External(External.relativex(Local.to_stringy))endletchmod_generic~mode?(op=`Set)path=letmode=matchopwith|`Set->mode|`Add|`Remove->letstat=Unix.statpathinifop=`Addthenstat.st_permlormodeelsestat.st_permlandlnotmodeinUnix.chmodpathmodemoduleBuild=structincludeLocalletappend_source=appendletappend_local=appendletlocalt=tletextract_build_contextt=split_first_componenttletextract_first_component=extract_build_contextletextract_build_context_dirt=Option.map(split_first_componentt)~f:(fun(before,after)->(Local.of_stringbefore,after))letsplit_sandbox_roott_original=matchsplit_first_componentt_originalwith|Some(".sandbox",t)->(matchsplit_first_componenttwith|Some(sandbox_name,t)->(Some(of_string(".sandbox"^"/"^sandbox_name)),t)|None->(None,t_original))|Some_|None->(None,t_original)letextract_build_context_dir_maybe_sandboxedt=letsandbox_root,t=split_sandbox_roottinOption.map(extract_build_context_dirt)~f:(fun(ctx_dir,src_dir)->letctx_dir=matchsandbox_rootwith|None->ctx_dir|Someroot->appendrootctx_dirin(ctx_dir,src_dir))letextract_build_context_dir_exnt=matchextract_build_context_dirtwith|Somet->t|None->Code_error.raise"Path.Build.extract_build_context_dir_exn"[("t",to_dynt)]letextract_build_context_exnt=matchextract_build_contexttwith|Somet->t|None->Code_error.raise"Path.Build.extract_build_context_exn"[("t",to_dynt)]letdrop_build_contextt=Option.map(extract_build_contextt)~f:sndletdrop_build_context_exnt=matchdrop_build_contexttwith|Somed->d|None->Code_error.raise"Path.Build.drop_build_context_exn"[("t",to_dynt)]letbuild_dir=Fdecl.createKind.to_dynletbuild_dir_prefix=Fdecl.createDyn.Encoder.opaqueletset_build_dir(new_build_dir:Kind.t)=letnew_build_dir_prefix=(matchnew_build_dirwith|External_->()|In_source_dirp->ifLocal.is_rootp||Local.parent_exnp<>Local.rootthenUser_error.raise[Pp.textf"Invalid build directory: %s"(Local.to_stringp|>String.maybe_quoted);Pp.text"The build directory must be an absolute path or a \
sub-directory of the root of the workspace."]);matchnew_build_dirwith|In_source_dirp->Local.Prefix.makep|External_->Local.Prefix.invalidinFdecl.setbuild_dirnew_build_dir;Fdecl.setbuild_dir_prefixnew_build_dir_prefixletto_stringp=matchFdecl.getbuild_dirwith|In_source_dirb->Local.to_string(Local.appendbp)|Externalb->ifLocal.is_rootpthenExternal.to_stringbelseFilename.concat(External.to_stringb)(Local.to_stringp)letof_localt=tletchmod~mode?(op=`Set)path=chmod_generic~mode~op(to_stringpath)moduleKind=KindendmoduleT:sigtypet=|ExternalofExternal.t|In_source_treeofLocal.t|In_build_dirofLocal.tvalto_dyn:t->Dyn.tvalcompare:t->t->Ordering.tvalequal:t->t->boolvalhash:t->intvalin_build_dir:Local.t->tvalin_source_tree:Local.t->tvalexternal_:External.t->tend=structtypet=|ExternalofExternal.t|In_source_treeofLocal.t|In_build_dirofLocal.tletcomparexy=match(x,y)with|Externalx,Externaly->External.comparexy|External_,_->Lt|_,External_->Gt|In_source_treex,In_source_treey->Local.comparexy|In_source_tree_,_->Lt|_,In_source_tree_->Gt|In_build_dirx,In_build_diry->Local.comparexyletequal(x:t)(y:t)=x=ylethash=Hashtbl.hashletin_build_dirs=In_build_dirsletin_source_trees=In_source_treesletexternal_e=Externaleletto_dynt=letopenDyninmatchtwith|In_build_dirs->Variant("In_build_dir",[Local.to_dyns])|In_source_trees->Variant("In_source_tree",[Local.to_dyns])|Externals->Variant("External",[External.to_dyns])endincludeTlethash(t:t)=Hashtbl.hashtletbuild_dir=in_build_dirLocal.rootletis_root=function|In_source_trees->Local.is_roots|In_build_dir_|External_->falsemoduleMap=Map.Make(T)letkind=function|In_build_dirp->Kind.append_local(Fdecl.getBuild.build_dir)p|In_source_trees->Kind.In_source_dirs|Externals->Kind.Externalsletis_managed=function|In_build_dir_|In_source_tree_->true|External_->falseletto_stringt=matchtwith|In_source_treep->Local.to_stringp|Externalp->External.to_stringp|In_build_dirp->Build.to_stringpletto_string_maybe_quotedt=String.maybe_quoted(to_stringt)letroot=in_source_treeLocal.rootletmake_local_pathp=matchLocal.Prefix.drop(Fdecl.getBuild.build_dir_prefix)pwith|None->in_source_treep|Somep->in_build_dirpletof_local=make_local_pathletrelative?error_loctfn=matchfnwith|""|"."->t|_whennot(Filename.is_relativefn)->external_(External.of_stringfn)|_->(matchtwith|In_source_treep->make_local_path(Local.relativepfn?error_loc)|In_build_dirp->in_build_dir(Local.relativepfn?error_loc)|Externals->external_(External.relativesfn))letparse_string_exn~locs=matchswith|""|"."->in_source_treeLocal.root|s->ifFilename.is_relativesthenmake_local_path(Local.parse_string_exn~locs)elseexternal_(External.parse_string_exn~locs)letof_strings=parse_string_exn~loc:Loc0.nonesletto_dyn=letopenDyn.Encoderinfunction|In_build_dirs->constr"In_build_dir"[Local.to_dyns]|In_source_trees->constr"In_source_tree"[Local.to_dyns]|Externals->constr"External"[External.to_dyns]letof_filename_relative_to_initial_cwdfn=external_(ifFilename.is_relativefnthenExternal.relativeExternal.initial_cwdfnelseExternal.of_stringfn)letto_absolute_filenamet=Kind.to_absolute_filename(kindt)letexternal_of_localx~root=External.to_string(External.relativeroot(Local.to_stringx))letexternal_of_in_source_treex=external_of_localx~root:(Lazy.forceabs_root)letreacht~from=match(t,from)with|Externalt,_->External.to_stringt|In_source_treet,In_source_treefrom|In_build_dirt,In_build_dirfrom->Local.reacht~from|In_source_treet,In_build_dirfrom->(matchFdecl.getBuild.build_dirwith|In_source_dirb->Local.reacht~from:(Local.appendbfrom)|External_->external_of_in_source_treet)|In_build_dirt,In_source_treefrom->(matchFdecl.getBuild.build_dirwith|In_source_dirb->Local.reach(Local.appendbt)~from|Externalb->external_of_localt~root:b)|In_source_treet,External_->external_of_in_source_treet|In_build_dirt,External_->(matchFdecl.getBuild.build_dirwith|In_source_dirb->external_of_in_source_tree(Local.appendbt)|Externalb->external_of_localt~root:b)letreach_for_running?(from=root)t=letfn=reacht~frominmatchFilename.analyze_program_namefnwith|In_path->"./"^fn|_->fnletdescendantt~of_=match(t,of_)with|In_source_treet,In_source_treeof_|In_build_dirt,In_build_dirof_->Option.map~f:in_source_tree(Local.descendantt~of_)|_->Noneletis_descendantt~of_=match(t,of_)with|In_source_treet,In_source_treeof_|In_build_dirt,In_build_dirof_->Local.is_descendantt~of_|_->falseletappend_localab=matchawith|In_source_treea->in_source_tree(Local.appendab)|In_build_dira->in_build_dir(Local.appendab)|Externala->external_(External.relativea(Local.to_stringb))letappend_local=append_localletappend_source=append_localletbasenamet=matchkindtwith|In_source_dirt->Local.basenamet|Externalt->External.basenametletbasename_opt=basename_opt~is_root~basenameletparent=function|Externals->Option.map(External.parents)~f:external_|In_source_treel->Local.parentl|>Option.map~f:in_source_tree|In_build_dirl->Local.parentl|>Option.map~f:in_build_dirletparent_exnt=matchparenttwith|Somep->p|None->Code_error.raise"Path.parent:exn t is root"[("t",to_dynt)]letis_strict_descendant_of_build_dir=function|In_build_dirp->not(Local.is_rootp)|In_source_tree_|External_->falseletis_in_build_dir=function|In_build_dir_->true|In_source_tree_|External_->falseletis_in_source_tree=function|In_source_tree_->true|In_build_dir_|External_->falseletas_in_source_tree=function|In_source_trees->Somes|In_build_dir_|External_->Noneletas_in_source_tree_exnt=matchas_in_source_treetwith|Somet->t|None->Code_error.raise"[as_in_source_tree_exn] called on something not in source tree"[("t",to_dynt)]letas_in_build_dir=function|In_build_dirb->Someb|In_source_tree_|External_->Noneletas_in_build_dir_exnt=matchtwith|External_|In_source_tree_->Code_error.raise"[as_in_build_dir_exn] called on something not in build dir"[("t",to_dynt)]|In_build_dirp->pletextract_build_context=function|In_source_tree_|External_->None|In_build_dirpwhenLocal.is_rootp->None|In_build_dirt->Build.extract_build_contexttletextract_build_dir_first_component=extract_build_contextletextract_build_context_exnt=matchextract_build_contexttwith|Somet->t|None->Code_error.raise"Path.extract_build_context_exn"[("t",to_dynt)]letextract_build_context_dir=function|In_source_tree_|External_->None|In_build_dirt->Option.map(Build.extract_build_context_dirt)~f:(fun(base,rest)->(in_build_dirbase,rest))letextract_build_context_dir_maybe_sandboxed=function|In_source_tree_|External_->None|In_build_dirt->Option.map(Build.extract_build_context_dir_maybe_sandboxedt)~f:(fun(base,rest)->(in_build_dirbase,rest))letdrop_optional_sandbox_root=function|(In_source_tree_|External_)asx->x|In_build_dirt->(matchBuild.split_sandbox_roottwith|_sandbox_root,t->(In_build_dirt:t))letextract_build_context_dir_exnt=matchextract_build_context_dirtwith|Somet->t|None->Code_error.raise"Path.extract_build_context_dir_exn"[("t",to_dynt)]letdrop_build_contextt=Option.map(extract_build_contextt)~f:sndletdrop_build_context_exnt=matchextract_build_contexttwith|None->Code_error.raise"Path.drop_build_context_exn"[("t",to_dynt)]|Some(_,t)->tletdrop_optional_build_contextt=matchextract_build_contexttwith|None->t|Some(_,t)->in_source_treetletdrop_optional_build_context_maybe_sandboxedt=matchextract_build_context_dir_maybe_sandboxedtwith|None->t|Some(_,t)->in_source_treetletdrop_optional_build_context_src_exnt=matchtwith|External_->Code_error.raise"drop_optional_build_context_src_exn called on an external path"[]|In_build_dir_->(matchextract_build_contexttwith|Some(_,s)->s|None->Code_error.raise"drop_optional_build_context_src_exn called on a build directory itself"[])|In_source_treep->pletsplit_first_componentt=matchkindtwith|In_source_dirt->Option.map(Local.split_first_componentt)~f:(fun(before,after)->(before,after|>in_source_tree))|_->Noneletexplodet=matchkindtwith|In_source_dirpwhenLocal.is_rootp->Some[]|In_source_dirs->Some(String.split(Local.to_strings)~on:'/')|External_->Noneletexplode_exnt=matchexplodetwith|Somes->s|None->Code_error.raise"Path.explode_exn"[("path",to_dynt)]letexistst=trySys.file_exists(to_stringt)withSys_error_->falseletreaddir_unsorted=letrecloopdhacc=matchUnix.readdirdhwith|"."|".."->loopdhacc|s->loopdh(s::acc)|exceptionEnd_of_file->accinfunt->tryletdh=Unix.opendir(to_stringt)inExn.protect~f:(fun()->matchloopdh[]with|exceptionUnix.Unix_error(e,_,_)->Errore|s->Result.Oks)~finally:(fun()->Unix.closedirdh)withUnix.Unix_error(e,_,_)->Erroreletis_directoryt=trySys.is_directory(to_stringt)withSys_error_->falseletis_directory_with_errort=matchSys.is_directory(to_stringt)with|exceptionSys_errore->Errore|bool->Okboolletis_filet=not(is_directoryt)letrmdirt=Unix.rmdir(to_stringt)letwin32_unlinkfn=tryUnix.unlinkfnwithUnix.Unix_error(Unix.EACCES,_,_)ase->(try(* Try removing the read-only attribute *)Unix.chmodfn0o666;Unix.unlinkfnwith_->raisee)letunlink_operation=ifSys.win32thenwin32_unlinkelseUnix.unlinkletunlinkt=unlink_operation(to_stringt)letlinkxy=Unix.link(to_stringx)(to_stringy)letunlink_no_errt=tryunlinktwith_->()letbuild_dir_exists()=is_directorybuild_dirletensure_build_dir_exists()=letperms=0o777inmatchkindbuild_dirwith|In_source_dirp->Relative_to_source_root.mkdir_pp~perms|Externalp->(letp=External.to_stringpintryUnix.mkdirppermswith|Unix.Unix_error(EEXIST,_,_)->()|Unix.Unix_error(ENOENT,_,_)->User_error.raise[Pp.textf"Cannot create external build directory %s. Make sure that the \
parent dir %s exists."p(Filename.dirnamep)])letextend_basenamet~suffix=matchtwith|In_source_treet->in_source_tree(Local.extend_basenamet~suffix)|In_build_dirt->in_build_dir(Local.extend_basenamet~suffix)|Externalt->external_(External.extend_basenamet~suffix)letinsert_after_build_dir_exn=leterrorab=Code_error.raise"Path.insert_after_build_dir_exn"[("path",to_dyna);("insert",Stringb)]infunab->matchawith|In_build_dira->in_build_dir(Local.append(Local.of_stringb)a)|In_source_tree_|External_->errorabletrm_rf=letrecloopdir=Array.iter(Sys.readdirdir)~f:(funfn->letfn=Filename.concatdirfninmatchUnix.lstatfnwith|{st_kind=S_DIR;_}->loopfn|_->unlink_operationfn);Unix.rmdirdirinfun?(allow_external=false)t->if(notallow_external)&¬(is_managedt)thenCode_error.raise"Path.rm_rf called on external dir"[("t",to_dynt)];letfn=to_stringtinmatchUnix.lstatfnwith|exceptionUnix.Unix_error(ENOENT,_,_)->()|_->loopfnletmkdir_p?perms=function|Externals->External.mkdir_ps?perms|In_source_trees->Relative_to_source_root.mkdir_ps?perms|In_build_dirk->Kind.mkdir_p?perms(Kind.append_local(Fdecl.getBuild.build_dir)k)lettouch?(create=true)p=letp=matchpwith|Externals->External.to_strings|In_source_trees->Local_gen.to_strings|In_build_dirk->Kind.to_string(Kind.append_local(Fdecl.getBuild.build_dir)k)intryUnix.utimesp0.00.0withUnix.Unix_error(Unix.ENOENT,_,_)->ifcreatethenUnix.close(Unix.openfilep[Unix.O_CREAT]0o777)letcomparexy=match(x,y)with|Externalx,Externaly->External.comparexy|External_,_->Lt|_,External_->Gt|In_source_treex,In_source_treey->Local.comparexy|In_source_tree_,_->Lt|_,In_source_tree_->Gt|In_build_dirx,In_build_diry->Local.comparexyletextensiont=matchtwith|Externalt->External.extensiont|In_build_dirt|In_source_treet->Local.extensiontletsplit_extensiont=matchtwith|Externalt->lett,ext=External.split_extensiontin(external_t,ext)|In_build_dirt->lett,ext=Local.split_extensiontin(in_build_dirt,ext)|In_source_treet->lett,ext=Local.split_extensiontin(in_source_treet,ext)letset_extensiont~ext=matchtwith|Externalt->external_(External.set_extensiont~ext)|In_build_dirt->in_build_dir(Local.set_extensiont~ext)|In_source_treet->in_source_tree(Local.set_extensiont~ext)moduleO=Comparable.Make(T)moduleSet=structincludeO.Setletof_listing~dir~filenames=of_list_mapfilenames~f:(funf->relativedirf)endletin_sources=in_source_tree(Local.of_strings)letsources=in_source_treesletbuilds=in_build_dirsmoduleTable=Hashtbl.Make(T)moduleL=struct(* TODO more efficient implementation *)letrelativet=List.fold_left~init:t~f:relativeendletlocal_part=function|Externale->Local.of_string(External.as_locale)|In_source_treel->l|In_build_dirl->lletstatt=Unix.stat(to_stringt)include(Comparator.Operators(T):Comparator.OPSwithtypet:=t)letpath_of_local=of_localmoduleSource=structincludeSource0letis_in_build_dirs=is_in_build_dir(path_of_locals)letto_localt=tendletset_of_source_pathsset=Source.Set.to_listset|>Set.of_list_map~f:sourceletset_of_build_paths_list=List.fold_left~init:Set.empty~f:(funacce->Set.addacc(builde))letstring_of_file_kind=function|Unix.S_REG->"regular file"|Unix.S_DIR->"directory"|Unix.S_CHR->"character device"|Unix.S_BLK->"block device"|Unix.S_LNK->"symbolic link"|Unix.S_FIFO->"named pipe"|Unix.S_SOCK->"socket"letrand_digits()=letrand=Random.State.(bits(make_self_init())land0xFFFFFF)inPrintf.sprintf"%06x"randletget_temp_dir_name()=of_string(Filename.get_temp_dir_name())lettemp_dir?(temp_dir=get_temp_dir_name())?(mode=0o700)prefixsuffix=letattempts=512inletrecloopcount=ifStdlib.(>=)countattemptsthenCode_error.raise"Path.temp_dir: too many failing attemps"[("attempts",Intattempts)]elseletdir=relativetemp_dir(String.concat~sep:""[prefix;rand_digits();suffix])intrymkdir_p~perms:modedir;dirwith|Unix.Unix_error(Unix.EEXIST,_,_)->loop(count-1)|Unix.Unix_error(Unix.EINTR,_,_)->loopcountinloop0letrenameold_pathnew_path=Sys.rename(to_stringold_path)(to_stringnew_path)letchmod~mode?(stats=None)?(op=`Set)path=letmode=matchopwith|`Set->mode|`Add|`Remove->letstats=matchstatswith|Somestats->stats|None->statpathinifStdlib.(=)op`Addthenstats.st_permlormodeelsestats.st_permlandlnotmodeinUnix.chmod(to_stringpath)mode