123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018-2021 Tarides <contact@tarides.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)(* Irmin 1.4 uses int8 to store filename lengths.
Irmin 2 use a variable-size encoding for strings; this is using int8
for strings of size strictly less than 128 (e.g. 2^7) which happen to
be the case for all filenames ever produced by Irmin 1.4. *)modulePath=Irmin.Path.String_listmoduleMetadata=Irmin.Metadata.NonemoduleBranch=Irmin.Branch.StringmoduleInfo=Irmin.InfomoduleConf=structletentries=32letstable_hash=256endmoduleHash:sigincludeIrmin.Hash.Svalto_raw_string:t->stringvalto_context_hash:t->Context_hash.tvalof_context_hash:Context_hash.t->tend=structmoduleH=Digestif.Make_BLAKE2B(structletdigest_size=32end)typet=H.tletto_raw_string=H.to_raw_stringletof_context_hashs=H.of_raw_string(Context_hash.to_strings)letto_context_hashh=Context_hash.of_string_exn(H.to_raw_stringh)letppppft=Context_hash.ppppf(to_context_hasht)letof_stringx=matchContext_hash.of_b58checkxwith|Okx->Ok(of_context_hashx)|Errorerr->Error(`Msg(Format.asprintf"Failed to read b58check_encoding data: %a"Error_monad.pp_print_traceerr))letshort_hash_string=Irmin.Type.(unstage(short_hashstring))letshort_hash?seedt=short_hash_string?seed(H.to_raw_stringt)lett:tIrmin.Type.t=Irmin.Type.map~pp~of_stringIrmin.Type.(string_of(`FixedH.digest_size))~short_hashH.of_raw_stringH.to_raw_stringletshort_hash=letf=short_hash_string?seed:Noneinfunt->f(H.to_raw_stringt)lethash_size=H.digest_sizelethash=H.digesti_stringendmoduleNode(Hash:Irmin.Hash.S)(Path:sigtypestepvalstep_t:stepIrmin.Type.tend)(Metadata:Irmin.Metadata.S)=structmoduleM=Irmin.Private.Node.Make(Hash)(Path)(Metadata)(* [V1] is only used to compute preimage hashes. [assert false]
statements should be unreachable.*)moduleV1:sigvalpre_hash:M.t->(string->unit)->unitend=structmoduleHash=Irmin.Hash.V1(Hash)typeentry=Path.step*M.valueletmetadata_t=letsome="\255\000\000\000\000\000\000\000"inletnone="\000\000\000\000\000\000\000\000"inIrmin.Type.(map(string_of(`Fixed8)))(fun_->assertfalse)(functionSome_->some|None->none)letmetadata_of_entry(_,t)=matchtwith`Node_->None|`Contents(_,m)->Somemlethash_of_entry(_,t)=matchtwith`Nodeh->h|`Contents(h,_)->h(* Irmin 1.4 uses int64 to store list lengths *)letentry_t:entryIrmin.Type.t=letopenIrmin.Typeinrecord"Tree.entry"(fun___->assertfalse)|+field"kind"metadata_tmetadata_of_entry|+field"name"Path.step_tfst|+field"hash"Hash.thash_of_entry|>sealrletentries_t:entrylistIrmin.Type.t=Irmin.Type.(list~len:`Int64entry_t)letpre_hash_entries=Irmin.Type.(unstage(pre_hashentries_t))letcompare_entry=letcompare_key=Irmin.Type.(unstage(comparePath.step_t))infun(x,_)(y,_)->compare_keyxyletpre_hasht=M.listt|>List.fast_sortcompare_entry|>pre_hash_entriesendincludeMlett=Irmin.Type.(liket~pre_hash:V1.pre_hash)endmoduleCommit(Hash:Irmin.Type.S)=structmoduleM=Irmin.Private.Commit.Make(Hash)moduleV1=Irmin.Private.Commit.V1(M)includeMletpre_hash_v1_t=Irmin.Type.(unstage(pre_hashV1.t))letpre_hash_v1t=pre_hash_v1_t(V1.importt)lett=Irmin.Type.(liket~pre_hash:pre_hash_v1)endmoduleContents=structtypet=bytesletty=Irmin.Type.(pair(bytes_of`Int64)unit)letpre_hash_ty=Irmin.Type.(unstage(pre_hashty))letpre_hash_v1x=pre_hash_ty(x,())lett=Irmin.Type.(likebytes~pre_hash:pre_hash_v1)letmerge=Irmin.Merge.(idempotent(Irmin.Type.optiont))end