123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113openAstringopenModelopen!ImportincludeLog_trap_intfmoduleMake(Promise:Monad.EXTENDED)(Platform:Platform.Swithtype'apromise:='aPromise.t)=structopenPromise.Syntaxtypestate={root:string;uuid:string;suite_name:string;has_alias:bool;}typet=Inactive|Activeofstate(** Take a string path and collapse a leading [$HOME] path segment to [~]. *)letmaybe_collapse_homepath=matchPlatform.home_directory()with|Error_->path|Okhome->((* Astring doesn't have [cut_prefix]. *)matchString.is_prefix~affix:homepathwith|false->path|true->lettail=String.Sub.to_string(String.sub~start:(String.lengthhome)path)in"~"^tail)letinactive=Inactiveletactive~root~uuid~suite_name=Platform.prepare_log_trap~root~uuid~name:suite_name;lethas_alias=Platform.file_exists(Filename.concatrootsuite_name)inActive{root;uuid;suite_name;has_alias}letpp_path=Fmt.usingmaybe_collapse_homeFmt.stringletiter_linesfpath~f=letic=open_infpathintrywhiletruedof(input_lineic)done;assertfalsewithEnd_of_file->close_inic(** Show the last lines of a log file. *)letpp_tailmax_linesfpathppf=matchmax_lineswith|`Unlimited->iter_linesfpath~f:(Fmt.pfppf"%s@\n")|`Limitlimit->letrev_lines=ref[]initer_linesfpath~f:(funl->rev_lines:=l::!rev_lines);letselected_lines=List.rev_headlimit!rev_linesinletomitted_count=List.length!rev_lines-List.lengthselected_linesinletdisplay_lines=ifomitted_count=0thenselected_lineselseFmt.str"... (omitting %i line%a)"omitted_countPp.pp_pluralomitted_count::selected_linesinListLabels.iterdisplay_lines~f:(Fmt.pfppf"%s@\n")letlog_dir~via_symlink{suite_name;uuid;root;has_alias}=letvia_symlink=via_symlink&&has_aliasinFilename.concatroot(ifvia_symlinkthensuite_nameelseuuid)letoutput_fpath~via_symlinkttname=Filename.concat(log_dir~via_symlinkt)(Test_name.filetname)letactive_or_exn=function|Activet->t|Inactive->failwith"internal error: no log location"letpp_current_run_dirtppf=lett=active_or_exntinpp_pathppf(log_dir~via_symlink:truet)letpp_log_locationttnameppf=lett=active_or_exntinletpath=output_fpath~via_symlink:truettnameinpp_pathppfpathletrecover_logst~tailtname=matchtwith|Inactive->None|Activet->(letfpath=output_fpath~via_symlink:falsettnameinmatchPlatform.file_existsfpathwith|false->None|true->Some(funppf->pp_tailtailfpathppf))letwith_captured_logsttnamefx=matchtwith|Inactive->fx|Activet->letfd=Platform.open_write_only(output_fpath~via_symlink:falsettname)inlet*()=Promise.return()inlet+a=Platform.with_redirectfd(fun()->fx)inPlatform.closefd;aend