1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519moduleSys=Stdlib.Sysletbasename_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]else(matchstart[]path(String.lengthpath-1)with|"."::xs->xs|xs->xs);;letappend_with_slashxy=letlen_x=String.lengthxinletlen_y=String.lengthyinletdst=Bytes.create(len_x+1+len_y)inBytes.blit_string~src:x~src_pos:0~dst~dst_pos:0~len:len_x;Bytes.setdstlen_x'/';Bytes.blit_string~src:y~src_pos:0~dst~dst_pos:(len_x+1)~len:len_y;Bytes.unsafe_to_stringdst;;moduleUnspecified=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 '/'. *)type_t=stringmoduleTable=String.Tableletto_stringt=tlethash=String.hashletcompare=String.compareletequal=String.equalletroot="."letis_roott=Ordering.is_eq(comparetroot)letparentt=ifis_roottthenNoneelse(matchString.rindex_fromt(String.lengtht-1)'/'with|None->Someroot|Somei->Some(String.taketi));;letunlink_no_errt=Fpath.unlink_no_errtletbasenamet=ifis_roottthenCode_error.raise"Path.Local.basename called on the root"[]else(letlen=String.lengthtinmatchString.rindex_fromt(len-1)'/'with|None->t|Somei->String.subt~pos:(i+1)~len:(len-i-1));;letto_dynt=Dyn.StringtmoduleL=structletrelative_resulttcomponents=letreclooptcomponents=matchcomponentswith|[]->Result.Okt|"."::rest->looptrest|".."::rest->(matchparenttwith|None->Result.Error`Outside_the_workspace|Someparent->loopparentrest)|fn::rest->ifis_roottthenloopfnrestelseloop(append_with_slashtfn)restinlooptcomponents;;letrelative?error_loctcomponents=matchrelative_resulttcomponentswith|Result.Okt->t|Error`Outside_the_workspace->User_error.raise?loc:error_loc[Pp.textf"path outside the workspace: %s from %s"(String.concat~sep:"/"components)t];;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`Outside_the_workspace->User_error.raise?loc:error_loc[Pp.textf"path outside the workspace: %s from %s"patht];;(* Check whether a path is in canonical form: no '.' or '..' components, no
repeated '/' components, no backslashes '\\' (on Windows only), and not
ending in a slash '/'. *)letis_canonicalized=letrecbefore_slashsi=ifi<0thenfalseelse(matchs.[i]with|'/'->false|'.'->before_dot_slashs(i-1)|'\\'whenSys.win32->false|_->in_components(i-1))andbefore_dot_slashsi=ifi<0thenfalseelse(matchs.[i]with|'/'->false|'.'->before_dot_dot_slashs(i-1)|'\\'whenSys.win32->false|_->in_components(i-1))andbefore_dot_dot_slashsi=ifi<0thenfalseelse(matchs.[i]with|'/'->false|'\\'whenSys.win32->false|_->in_components(i-1))andin_componentsi=ifi<0thentrueelse(matchs.[i]with|'/'->before_slashs(i-1)|'\\'whenSys.win32->false|_->in_components(i-1))infuns->letlen=String.lengthsinlen=0||before_slashs(len-1);;letparse_string_exn~locs=matchswith|""|"."->root|_whenis_canonicalizeds->s|_->relativeroots~error_loc:loc;;letof_strings=parse_string_exn~loc:Loc0.nonesletappendab=matchis_roota,is_rootbwith|true,_->b|_,true->a|_,_->append_with_slashab;;letdescendantt~of_=ifis_rootof_thenSometelseift=of_thenSomerootelse(letof_len=String.lengthof_inlett_len=String.lengthtinift_len>of_len&&t.[of_len]='/'&&String.is_prefixt~prefix:of_thenSome(String.dropt(of_len+1))elseNone);;letis_descendantt~of_=is_rootof_||t=of_||letof_len=String.lengthof_inlett_len=String.lengthtint_len>of_len&&t.[of_len]='/'&&String.is_prefixt~prefix:of_;;moduleReach=struct(* count the number of times we need to do ".." *)letparent_remaining_componentsposfrom=letlen=String.lengthfrominifpos>=lenthen0else(letcount=ref1inletpos=ifChar.equalfrom.[pos]'/'thenpos+1elseposinfori=postolen-1doifChar.equalfrom.[i]'/'thenincrcountdone;!count);;(* generate a sequence of ".." separated by "/" [times] in [buf] *)letgen_blit_go_upbuf~times=iftimes>0then(String_builder.add_stringbuf"..";for_=1totimes-1doString_builder.add_stringbuf"/.."done);;(* because the ".." above are so common, we precompute the first 20 cases *)letblit_go_up_table=Array.init20~f:(funi->List.init(i+1)~f:(fun_->"..")|>String.concat~sep:"/");;letblit_go_upbuf~times=iftimes>0theniftimes>Array.lengthblit_go_up_tablethen(* doing the work in a single blit is fastest *)gen_blit_go_upbuf~timeselse(letsrc=blit_go_up_table.(times-1)inString_builder.add_stringbufsrc);;(* the size of the "../.." string we need to generate *)letgo_up_components_buffer_sizetimes=(times*2)+max0(times-1)letreach_root~frompos=letgo_up_this_many_times=parent_remaining_componentsposfrominifgo_up_this_many_times=0then"."elseifgo_up_this_many_times<=Array.lengthblit_go_up_tablethenblit_go_up_table.(go_up_this_many_times-1)else(letsize=go_up_components_buffer_sizego_up_this_many_timesinletbuf=String_builder.createsizeinblit_go_upbuf~times:go_up_this_many_times;String_builder.build_exact_exnbuf[@nontail]);;(* if we have "a/b" and "a", we need to skip over the "a", even if the last
component position is [0] *)letextend_to_comp~smaller~bigger~pos~comp=ifpos=String.lengthsmaller&&bigger.[pos]='/'thenposelsecomp;;letmake_from_common_prefix~to_~fromto_pos=letto_len=String.lengthto_inletto_pos=ifto_pos<to_len&&to_.[to_pos]='/'thento_pos+1elseto_posinletto_len=to_len-to_posinletgo_up_this_many_times=parent_remaining_componentsto_posfrominifto_len=0thenreach_root~fromto_poselse(letsize=go_up_components_buffer_sizego_up_this_many_timesinletadd_extra_slash=size>0&&to_len>0in(* the final length of the buffer we need to compute *)letsize=to_len+size+ifadd_extra_slashthen1else0in(* our position inside the buffer *)letbuf=String_builder.createsizeinblit_go_upbuf~times:go_up_this_many_times;ifadd_extra_slashthenString_builder.add_charbuf'/';String_builder.add_substringbufto_~pos:to_pos~len:to_len;String_builder.build_exact_exnbuf[@nontail]);;letreccommon_prefix~to_~from~pos~comp=ifInt.equalpos(String.lengthto_)then((* the case where we exhausted [to_] first. *)letpos=extend_to_comp~smaller:to_~bigger:from~pos~compinmake_from_common_prefix~to_~frompos)elseifInt.equalpos(String.lengthfrom)then((* we exhausted [from] first *)letpos=extend_to_comp~smaller:from~bigger:to_~pos~compinmake_from_common_prefix~to_~frompos)elseifChar.equalto_.[pos]from.[pos]then((* eat another common character. *)letcomp=(* if we find '/', then we advance the last common component position *)ifto_.[pos]='/'thenposelsecompincommon_prefix~to_~from~pos:(pos+1)~comp)elsemake_from_common_prefix~to_~fromcomp;;letreachto_~from=ifis_rootfromthento_elseifis_rootto_thenreach_root~from0elseifequalto_fromthen"."elsecommon_prefix~to_~from~pos:0~comp:0;;endletreach=Reach.reachletextend_basenamet~suffix=t^suffixletextensiont=Filename.extensiontletsplit_extensiont=lets,ext=Filename.split_extensiontins,ext;;letset_extensiont~ext=letbase,_=split_extensiontinbase^ext;;letmap_extensiont~f=letbase,ext=split_extensiontinbase^fext;;modulePrefix=structtype_t={len:int;path:string;path_slash:string}letmakep=ifis_rootpthenCode_error.raise"Path.Local.Prefix.make"["path",to_dynp];{len=String.lengthp;path=p;path_slash=p^"/"};;letdroptp=letlen=String.lengthpiniflen=t.len&&p=t.paththenSomerootelseString.drop_prefixp~prefix:t.path_slash;;letinvalid={len=-1;path="/";path_slash="/"}endletsplit_first_componentt=ifis_roottthenNoneelse(matchString.lsplit2t~on:'/'with|None->Some(t,root)|Some(before,after)->Some(before,after|>of_string));;letexplodep=ifis_rootpthen[]elseString.splitp~on:'/'letto_string_maybe_quotedt=String.maybe_quotedtletparent_exnt=matchparenttwith|None->Code_error.raise"Path.Local.parent:exn t is root"["t",to_dynt]|Someparent->parent;;moduleFix_root(Root:sigtypewend)=structtype_w=Root.wmoduleTable=TablemoduleMap=String.MapmoduleSet=structincludeString.Setletof_listing~dir~filenames=of_list_mapfilenames~f:(funf->relativedirf)endendendmoduleLocal:sigtypew=Unspecified.wtypet=wLocal_gen.tincludePath_intf.Swithtypet:=tmoduleTable:Hashtbl.Swithtypekey=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->tvalrelative_result:t->stringlist->(t,[`Outside_the_workspace])Result.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~basenameendmoduleExternal:sigincludePath_intf.SmoduleTable:Hashtbl.Swithtypekey=tvalroot:tvalrelative:t->string->tvalmkdir_p:?perms:int->t->unitvalinitial_cwd:tvalcwd:unit->tvalas_local:t->stringvalappend_local:t->Local.t->tvalof_filename_relative_to_initial_cwd:string->tvalis_broken_symlink:t->boolend=structmoduleTable=String.Tabletypet=stringletto_stringt=tletequal=String.equallethash=String.hashletcompare=String.compareletextend_basenamet~suffix=t^suffixletof_stringt=ifFilename.is_relativetthenCode_error.raise"Path.External.of_string: relative path given"["t",Stringt];t;;letparse_string_exn~loct=ifFilename.is_relativetthenUser_error.raise~loc[Pp.textf"path %s is not absolute"t];t;;letto_dynt=Dyn.variant"External"[Dyn.stringt]letrelativexy=matchywith|"."->x|_->Filename.concatxy;;letappend_localtlocal=relativet(Local.to_stringlocal)letbasenamet=Filename.basenametletroot=of_string"/"letis_root=equalrootletbasename_opt=basename_opt~is_root~basenameletparentt=ifis_roottthenNoneelseSome(Filename.dirnamet)letparent_exnt=matchparenttwith|None->Code_error.raise"Path.External.parent_exn called on a root path"[]|Somep->p;;letmkdir_p?permspath=ignore(Fpath.mkdir_p?permspath:Fpath.mkdir_p_result)letunlink_no_errt=Fpath.unlink_no_errtletextensiont=Filename.extensiontletsplit_extensiont=lets,ext=Filename.split_extensiontins,ext;;letset_extensiont~ext=letbase,_=split_extensiontinbase^ext;;letmap_extensiont~f=letbase,ext=split_extensiontinbase^fext;;letcwd()=Sys.getcwd()letinitial_cwd=Fpath.initial_cwdletas_localt=lets=tin"."^s;;letof_filename_relative_to_initial_cwdfn=ifFilename.is_relativefnthenrelativeinitial_cwdfnelseof_stringfn;;letis_broken_symlink=Fpath.is_broken_symlinkinclude(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);;moduleMap=String.MapmoduleSet=structincludeString.Setletof_listing~dir~filenames=of_list_mapfilenames~f:(funf->relativedirf)endendmoduleRelative_to_source_root=structletmkdir_p?permspath=ignore(Fpath.mkdir_p?perms(Local.to_stringpath):Fpath.mkdir_p_result);;endmoduleSource0=structincludeLocalletto_dyns=Dyn.variant"In_source_tree"[to_dyns]letappend_local=Local.appendendletabs_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)inabs_root,set_root;;moduleOutside_build_dir=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_stringt;;letto_dyn=function|In_source_dirt->Source0.to_dynt|Externalt->External.to_dynt;;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?permst;;letrelativets=matchtwith|In_source_dirt->In_source_dir(Local.relativets)|Externalt->External(External.relativets);;letextend_basenamet~suffix=matchtwith|In_source_dirt->In_source_dir(Local.extend_basenamet~suffix)|Externalt->External(External.extend_basenamet~suffix);;letappend_localxy=matchxwith|In_source_dirx->In_source_dir(Local.appendxy)|Externalx->External(External.relativex(Local.to_stringy));;letto_string_maybe_quotedt=String.maybe_quoted(to_stringt)letequal(x:t)(y:t)=matchx,ywith|Externalx,Externaly->External.equalxy|External_,In_source_dir_->false|In_source_dirx,In_source_diry->Local.equalxy|In_source_dir_,External_->false;;lethash=Poly.hashletparent=function|In_source_dirt->(matchLocal.parenttwith|None->None|Somes->Some(In_source_dirs))|Externalt->(matchExternal.parenttwith|None->None|Somes->Some(Externals));;moduleTable=Hashtbl.Make(structtypenonrect=tlethash=Poly.hashletequal=Poly.equalletto_dyn=to_dynend)endmodulePermissions=structtypet={current_user:int;all_users:int}letexecute={current_user=0o100;all_users=0o111}letwrite={current_user=0o200;all_users=0o222}letaddtperm=permlort.current_userlettesttperm=permlandt.current_user<>0letremovetperm=permlandlnott.all_usersendmoduleBuild=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_dirinctx_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];;letdrop_build_context_maybe_sandboxed_exnt=matchextract_build_context_dir_maybe_sandboxedtwith|Some(_,t)->t|None->Code_error.raise"Path.Build.drop_build_context_maybe_sandboxed_exn"["t",to_dynt];;letbuild_dir=Fdecl.createOutside_build_dir.to_dynletbuild_dir_prefix=Fdecl.createDyn.opaqueletset_build_dir(new_build_dir:Outside_build_dir.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_prefix;;letto_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);;letto_string_maybe_quotedp=String.maybe_quoted(to_stringp)letof_localt=tletchmodt~mode=Unix.chmod(to_stringt)modeletlstatt=Unix.lstat(to_stringt)letunlinkt=Fpath.unlink(to_stringt)letunlink_no_errt=Fpath.unlink_no_err(to_stringt)letto_dyns=Dyn.variant"In_build_dir"[to_dyns]endmoduleT:sigtypet=|ExternalofExternal.t|In_source_treeofLocal.t|In_build_dirofLocal.tvalto_dyn:t->Dyn.t(** [External _] < [In_source_tree _] < [In_build_dir _]
Path of the same kind are compared using the standard lexical order *)valcompare:t->t->Ordering.tvalhash: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=matchx,ywith|Externalx,Externaly->External.comparexy|External_,_->Lt|_,External_->Gt|In_source_treex,In_source_treey->Local.comparexy|In_source_tree_,In_build_dir_->Lt|In_build_dir_,In_source_tree_->Gt|In_build_dirx,In_build_diry->Local.comparexy;;lethash=Poly.hashletin_build_dirs=In_build_dirsletin_source_trees=In_source_treesletexternal_e=Externaleletto_dyn=function|In_build_dirs->Build.to_dyns|In_source_trees->Source0.to_dyns|Externals->External.to_dyns;;endincludeTletbuild_dir=in_build_dirLocal.rootletis_root=function|In_source_trees->Local.is_roots|In_build_dir_|External_->false;;letlocal_or_external:t->Outside_build_dir.t=function|In_build_dirp->Outside_build_dir.append_local(Fdecl.getBuild.build_dir)p|In_source_trees->In_source_dirs|Externals->Externals;;letis_managed=function|In_build_dir_|In_source_tree_->true|External_->false;;letto_stringt=matchtwith|In_source_treep->Local.to_stringp|Externalp->External.to_stringp|In_build_dirp->Build.to_stringp;;letto_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_dirp;;letof_local=make_local_pathletrelative?error_loctfn=matchfnwith|""|"."->t|_whennot(Filename.is_relativefn)->external_(External.of_stringfn)|_->(matchtwith|In_source_treep->letfn'=explode_pathfnin(matchLocal.L.relative_resultpfn'with|Okl->make_local_pathl|Error`Outside_the_workspace->external_(External.relative(External.of_string(Outside_build_dir.to_absolute_filename(local_or_externalt)))fn))|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.nonesletof_filename_relative_to_initial_cwdfn=external_(External.of_filename_relative_to_initial_cwdfn);;letto_absolute_filenamet=Outside_build_dir.to_absolute_filename(local_or_externalt)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=matcht,fromwith|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|_->fn;;letdescendantt~of_=matcht,of_with|In_source_treet,In_source_treeof_|In_build_dirt,In_build_dirof_->Option.map~f:in_source_tree(Local.descendantt~of_)|_->None;;letis_descendantt~of_=matcht,of_with|In_source_treet,In_source_treeof_|In_build_dirt,In_build_dirof_->Local.is_descendantt~of_|_->false;;letappend_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=matchtwith|In_build_dirp->Local.basenamep|In_source_trees->Local.basenames|Externals->External.basenames;;letis_a_root=function|In_build_dirp->Local.is_rootp|In_source_trees->Local.is_roots|Externals->External.is_roots;;letbasename_opt=basename_opt~is_root:is_a_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_dir;;letparent_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_->false;;letis_in_build_dir=function|In_build_dir_->true|In_source_tree_|External_->false;;letis_in_source_tree=function|In_source_tree_->true|In_build_dir_|External_->false;;letas_in_source_tree=function|In_source_trees->Somes|In_build_dir_|External_->None;;letas_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_outside_build_dir:t->Outside_build_dir.toption=function|In_source_trees->Some(In_source_dirs)|Externals->Some(Externals)|In_build_dir_->None;;letas_outside_build_dir_exn:t->Outside_build_dir.t=function|In_source_trees->In_source_dirs|Externals->Externals|In_build_dirpath->Code_error.raise"as_outside_build_dir_exn"["path",Build.to_dynpath];;letdestruct_build_dir:t->[`InsideofBuild.t|`OutsideofOutside_build_dir.t]=function|In_source_treep->`Outside(In_source_dirp)|Externals->`Outside(Externals)|In_build_dirs->`Insides;;letoutside_build_dir:Outside_build_dir.t->t=function|In_source_dird->In_source_treed|Externals->Externals;;letas_in_build_dir=function|In_build_dirb->Someb|In_source_tree_|External_->None;;letas_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->p;;letas_external=function|Externals->Somes|In_build_dir_|In_source_tree_->None;;letextract_build_context=function|In_source_tree_|External_->None|In_build_dirpwhenLocal.is_rootp->None|In_build_dirt->Build.extract_build_contextt;;letextract_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)->t;;letdrop_optional_build_contextt=matchextract_build_contexttwith|None->t|Some(_,t)->in_source_treet;;letpppath=drop_optional_build_contextpath|>to_string_maybe_quoted|>Pp.verbatimletdrop_optional_build_context_maybe_sandboxedt=matchextract_build_context_dir_maybe_sandboxedtwith|None->t|Some(_,t)->in_source_treet;;letdrop_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->p;;letsplit_first_componentt=matchlocal_or_externaltwith|In_source_dirt->Option.map(Local.split_first_componentt)~f:(fun(before,after)->before,after|>in_source_tree)|_->None;;letexplodet=matchlocal_or_externaltwith|In_source_dirpwhenLocal.is_rootp->Some[]|In_source_dirs->Some(String.split(Local.to_strings)~on:'/')|External_->None;;letexplode_exnt=matchexplodetwith|Somes->s|None->Code_error.raise"Path.explode_exn"["path",to_dynt];;letrelative_to_source_in_build_or_external?error_loc~dirs=matchBuild.extract_build_contextdirwith|None->relative?error_loc(In_build_dirdir)s|Some(bctxt,source)->letpath=relative?error_loc(In_source_treesource)sin(matchpathwith|In_source_trees->In_build_dir(Build.relative(Build.of_stringbctxt)(Source0.to_strings))|In_build_dir_|External_->path);;letexistst=trySys.file_exists(to_stringt)with|Sys_error_->false;;letreaddir_unsortedt=Dune_filesystem_stubs.read_directory(to_stringt)letreaddir_unsorted_with_kindst=Dune_filesystem_stubs.read_directory_with_kinds(to_stringt);;letis_directoryt=trySys.is_directory(to_stringt)with|Sys_error_->false;;letrmdirt=Unix.rmdir(to_stringt)letunlink_exnt=Fpath.unlink_exn(to_stringt)letlinksrcdst=matchUnix.link(to_stringsrc)(to_stringdst)with|exceptionUnix.Unix_error(Unix.EUNKNOWNERR-1142,syscall,arg)(* Needed for OCaml < 5.1 on windows *)->Exn.reraise(Unix.Unix_error(Unix.EMLINK,syscall,arg))|s->s;;letunlink_no_errt=Fpath.unlink_no_err(to_stringt)letbuild_dir_exists()=is_directorybuild_dirletensure_build_dir_exists()=letperms=0o777inmatchlocal_or_externalbuild_dirwith|In_source_dirp->Relative_to_source_root.mkdir_pp~perms|Externalp->letp=External.to_stringpin(matchFpath.mkdir~permspwith|Created|Already_exists->()|Missing_parent_directory->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);;letclear_dirdir=Fpath.clear_dir(to_stringdir)letrm_rf?(allow_external=false)t=if(notallow_external)&¬(is_managedt)thenCode_error.raise"Path.rm_rf called on external dir"["t",to_dynt];Fpath.rm_rf(to_stringt);;letmkdir_p?perms=function|Externals->External.mkdir_ps?perms|In_source_trees->Relative_to_source_root.mkdir_ps?perms|In_build_dirk->Outside_build_dir.mkdir_p?perms(Outside_build_dir.append_local(Fdecl.getBuild.build_dir)k);;letextensiont=matchtwith|Externalt->External.extensiont|In_build_dirt|In_source_treet->Local.extensiont;;letsplit_extensiont=matchtwith|Externalt->lett,ext=External.split_extensiontinexternal_t,ext|In_build_dirt->lett,ext=Local.split_extensiontinin_build_dirt,ext|In_source_treet->lett,ext=Local.split_extensiontinin_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);;letmap_extensiont~f=letbase,ext=split_extensiontinextend_basename~suffix:(fext)base;;moduleO=Comparable.Make(T)moduleMap=O.MapmoduleSet=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=structtypekey=ttype'at={source:'aSource0.Table.t;build:'aBuild.Table.t;external_:'aExternal.Table.t}letcreate()={source=Source0.Table.create0;build=Build.Table.create0;external_=External.Table.create0};;letclear{source;build;external_}=Source0.Table.clearsource;Build.Table.clearbuild;External.Table.clearexternal_;;let[@inline]mem{source;build;external_}key=matchkeywith|In_source_treep->Source0.Table.memsourcep|In_build_dirp->Build.Table.membuildp|Externalp->External.Table.memexternal_p;;let[@inline]set{source;build;external_}kv=matchkwith|In_source_treep->Source0.Table.setsourcepv|In_build_dirp->Build.Table.setbuildpv|Externalp->External.Table.setexternal_pv;;let[@inline]remove{source;build;external_}k=matchkwith|In_source_treep->Source0.Table.removesourcep|In_build_dirp->Build.Table.removebuildp|Externalp->External.Table.removeexternal_p;;letiter{source;build;external_}~f=Source0.Table.itersource~f;Build.Table.iterbuild~f;External.Table.iterexternal_~f;;let[@inline]find{source;build;external_}=function|In_source_treep->Source0.Table.findsourcep|In_build_dirp->Build.Table.findbuildp|Externalp->External.Table.findexternal_p;;letfilteri_inplace{source;build;external_}~f=Source0.Table.filteri_inplacesource~f:(fun[@inline]~key~data->f~key:(In_source_treekey)~data);Build.Table.filteri_inplacebuild~f:(fun[@inline]~key~data->f~key:(In_build_dirkey)~data);External.Table.filteri_inplaceexternal_~f:(fun[@inline]~key~data->f~key:(Externalkey)~data);;letfilter_inplace{source;build;external_}~f=Source0.Table.filteri_inplacesource~f:(fun[@inline]~key:_~data->fdata);Build.Table.filteri_inplacebuild~f:(fun[@inline]~key:_~data->fdata);External.Table.filteri_inplaceexternal_~f:(fun[@inline]~key:_~data->fdata);;letto_dynf{source;build;external_}=letopenDyninrecord["source",Source0.Table.to_dynfsource;"build",Build.Table.to_dynfbuild;"external_",External.Table.to_dynfexternal_];;endmoduleL=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->l;;letstat_exnt=Unix.stat(to_stringt)letstatt=Dune_filesystem_stubs.Unix_error.Detailed.catchstat_exntletlstat_exnt=Unix.lstat(to_stringt)letlstatt=Dune_filesystem_stubs.Unix_error.Detailed.catchlstat_exntinclude(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));;letset_of_external_pathsset=External.Set.to_listset|>Set.of_list_map~f:external_letrenameold_pathnew_path=Unix.rename(to_stringold_path)(to_stringnew_path)letchmodt~mode=Unix.chmod(to_stringt)modeletfollow_symlinkpath=Fpath.follow_symlink(to_stringpath)|>Result.map~f:of_stringletdrop_prefixpath~prefix=letprefix_s=to_stringprefixinletpath_s=to_stringpathinmatchInt.compare(String.lengthprefix_s)(String.lengthpath_s)with|Eq->ifprefix=paththenSomeLocal.rootelseNone|Gt->None|Lt->letopenOption.Oinlet*prefix=let*last=String.lastprefix_sinifis_dir_seplastthenSomeprefix_selseifis_dir_seppath_s.[String.lengthprefix_s]thenSome(prefix_s^String.make1path_s.[String.lengthprefix_s])elseNoneinlet+suffix=String.drop_prefixpath_s~prefixinLocal.of_stringsuffix;;letdrop_prefix_exnt~prefix=matchdrop_prefixt~prefixwith|None->Code_error.raise"Path.drop_prefix_exn"["t",to_dynt;"prefix",to_dynprefix]|Somep->p;;letis_broken_symlink=function|Externale->External.is_broken_symlinke|In_source_tree_|In_build_dir_->(* Paths within the source tree and build dir are always fully-expanded,
so there's no possibility for them to be broken symlinks. *)false;;moduleExpert=structletdrop_absolute_prefix~prefixp=matchString.drop_prefix~prefix:(Outside_build_dir.to_absolute_filenameprefix)pwith|None->None|Some""->SomeLocal.root|Somep->Some(Local.of_string(ifis_dir_sepp.[0]thenString.dropp1elsep));;lettry_localize_externalext=letp=External.to_stringextinmatchFdecl.getBuild.build_dirwith|Externals->(matchdrop_absolute_prefix~prefix:(Externals)pwith|Somes->Some(in_build_dirs)|None->drop_absolute_prefix~prefix:(In_source_dirLocal.root)p|>Option.map~f:in_source_tree)|In_source_dir_->drop_absolute_prefix~prefix:(In_source_dirLocal.root)p|>Option.map~f:make_local_path;;lettry_localize_externalt=matchtwith|Externale->Option.value~default:t(try_localize_externale)|_->t;;end