123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145(* YOCaml a static blog generator.
Copyright (C) 2024 The Funkyworkers and The YOCaml's developers
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. *)letto_kv_pathx=let_,r=Yocaml.Path.to_pairxinMirage_kv.Key.v(r|>String.concatFilename.dir_sep)moduleMake(Source:Required.SOURCE)(Config:Required.CONFIG)(Store:Mirage_kv.RWwithtypet=Git_kv.t)=structmoduleRuntime=structtype'at='aLwt.tletbindfx=Lwt.bindxfletreturn=Lwt.returnletlog?srclevelmessage=Source.lift@@Source.log?srclevelmessagetyperuntime_error=|GitofYocaml_runtime.Error.common|SourceofSource.runtime_errorletstore=Config.storeletruntime_error_to_string=function|Giterr->Yocaml_runtime.Error.common_to_stringerr|Sourceerr->Source.runtime_error_to_stringerrletlift_resultx=x|>Source.bind(function|Okx->Source.return@@Okx|Errorerr->Source.return@@Error(Sourceerr))|>Source.liftletmap_errorf_err=function|Okx->Okx|Errorerr->Error(Git(f_errerr))lethash_contentx=Source.lift@@Source.hash_contentxletget_time()=Source.lift@@Source.get_time()letfile_exists~onpath=matchonwith|`Source->Source.lift@@Source.file_exists~onpath|`Target->letopenLwt.Syntaxinlet+exists=Store.existsstore(to_kv_pathpath)inexists|>Result.fold~ok:Option.is_some~error:(Fun.constfalse)letread_file~onpath=matchonwith|`Source->lift_result@@Source.read_file~onpath|`Target->letopenLwt.Syntaxinlet+content=Store.getstore(to_kv_pathpath)inmap_error(Fun.const@@Yocaml_runtime.Error.Unable_to_read_filepath)contentletget_mtime~onpath=matchonwith|`Source->lift_result@@Source.get_mtime~onpath|`Target->letopenLwt.Syntaxinlet+mtime=Store.last_modifiedstore(to_kv_pathpath)inmtime|>Result.map(funx->x|>Ptime.to_float_s|>Float.to_int)|>map_error(Fun.const@@Yocaml_runtime.Error.Unable_to_read_filepath)letcreate_directory~onpath=matchonwith|`Source->lift_result@@Source.create_directory~onpath|`Target->(* Path are Keys in Git_kv so [create_dir] is useless*)Lwt.return@@Ok()letwrite_file~onpathcontent=matchonwith|`Source->lift_result@@Source.write_file~onpathcontent|`Target->letopenLwt.Syntaxinlet+result=Store.setstore(to_kv_pathpath)contentinmap_error(Fun.const@@Yocaml_runtime.Error.Unable_to_read_filepath)resultleterase_file~onpath=matchonwith|`Source->lift_result@@Source.erase_file~onpath|`Target->letopenLwt.InfixinStore.removestore(to_kv_pathpath)>|=map_error(Fun.const@@Yocaml_runtime.Error.Unable_to_erase_filepath)letis_directory~onpath=matchonwith|`Source->Source.lift@@Source.is_directory~onpath|`Target->letopenLwt.InfixinStore.existsstore(to_kv_pathpath)>|=Result.fold~ok:(functionSome`Dictionary->true|_->false)~error:(Fun.constfalse)letis_file~onpath=matchonwith|`Source->Source.lift@@Source.is_file~onpath|`Target->letopenLwt.InfixinStore.existsstore(to_kv_pathpath)>|=Result.fold~ok:(functionSome`Value->true|_->false)~error:(Fun.constfalse)letexec?is_successprogargs=lift_result@@Source.exec?is_successprogargsletread_dir~onpath=matchonwith|`Source->lift_result@@Source.read_dir~onpath|`Target->(* Should be used on the source side *)Lwt.return@@Ok[]endmoduleRunner=Yocaml.Runtime.Make(Runtime)includeRuntimeend