123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247(* TODO: remove once we have >= 4.08 *)letresult_is_error=functionOk_v->false|Error_v->trueletresult_get_ok=functionOkv->v|Error_v->invalid_arg"Result.get_ok"moduleScheme_version=structtypet=intletof_string=function|"1"->Ok1|invalid->Error(Format.sprintf"invalid scheme version `%s`"invalid)letof_int=function|1->Ok1|invalid->Error(Format.sprintf"invalid scheme version `%d`"invalid)letto_intx=xletppfmtv=Format.fprintffmt"%d"vletdefault=1endmoduleKind=structtypet=|Contentofstring|Directory|Revision|Release|Snapshotletcomparett'=match(t,t')with|Directory,Directory|Release,Release|Revision,Revision|Snapshot,Snapshot->0|Contentc,Contentc'->String.comparecc'|Content_,_->1|_,Content_->-1|Directory,_->1|_,Directory->-1|Revision,_->1|_,Revision->-1|Release,_->1|_,Release->-1letequaltt'=comparett'=0letof_string=function|"cnt"->Ok(Content"sha1_git")|"dir"->OkDirectory|"rel"->OkRelease|"rev"->OkRevision|"snp"->OkSnapshot|invalid->Error(Format.sprintf"invalid object kind `%s`"invalid)letto_string=function|Content_f->"cnt"|Directory->"dir"|Release->"rel"|Revision->"rev"|Snapshot->"snp"letppfmtv=Format.fprintffmt"%s"(to_stringv)endmoduleHash=structtypet=stringletcompare=String.compareletequal=String.equalletof_strings=letlen=ref0intryString.iter(function|'a'..'f'|'0'..'9'->incrlen|_invalid_char->raiseExit)s;if!len=40thenOkselseraiseExitwithExit->Error(Format.sprintf"invalid object hash `%s`"s)letto_stringv=vletppfmtv=Format.fprintffmt"%s"vend(* TODO: remove once we have > 4.03 *)letstring_split_on_charseps=letr=ref[]inletj=ref(String.lengths)infori=String.lengths-1downto0doifString.unsafe_getsi=septhenbeginr:=String.subs(i+1)(!j-i-1)::!r;j:=ienddone;String.subs0!j::!rmoduleCore_identifier=structtypet=Scheme_version.t*Kind.t*Hash.tletcompare(sch_version,object_type,hash)(sch_version',object_type',hash')=letscheme_version=sch_version-sch_version'inifscheme_version<>0thenscheme_versionelseletobject_type=Kind.compareobject_typeobject_type'inifobject_type<>0thenobject_typeelseHash.comparehashhash'letequaltt'=comparett'=0letof_strings=matchstring_split_on_char':'swith|["swh";"1";t;hash]->beginmatchKind.of_stringtwith|Error_msgase->e|Okt->beginmatchHash.of_stringhashwith|Error_msgase->e|Okhash->letscheme=Scheme_version.defaultinOk(scheme,t,hash)endend|_whatever->Error"invalid core identifier"letmkschemetyphash=(scheme,typ,hash)letppfmt(scheme,typ,hash)=Format.fprintffmt"swh:%a:%a:%a"Scheme_version.ppschemeKind.pptypHash.pphashletto_stringv=Format.asprintf"%a"ppvletget_scheme(scheme,_kind,_hash)=schemeletget_kind(_scheme,kind,_hash)=kindletget_hash(_scheme,_kind,hash)=hashendmoduleQualifier=structtypet=|AnchorofCore_identifier.t|Originofstring|Pathofstring|VisitofCore_identifier.t|Fragmentof(int*intoption)letint_of_string_opts=trySome(int_of_strings)withFailure_->Noneletof_strings=matchstring_split_on_char'='swith|"lines"::lines->beginmatchstring_split_on_char'-'(String.concat""lines)with|[l1]->beginmatchint_of_string_optl1with|None->Error"invalid qualifier"|Somei->Ok(Fragment(i,None))end|[l1;l2]->beginmatch(int_of_string_optl1,int_of_string_optl2)with|Somei1,Somei2->Ok(Fragment(i1,Somei2))|_,_->Error"invalid qualifier"end|_whatever->Error"invalid qualifier"end|"path"::path->(* TODO: check RFC 3987 IRI compliance *)letpath=String.concat""pathinOk(Pathpath)|"origin"::url->(* TODO: check RFC 3987 absolute path compliance *)leturl=String.concat""urlinOk(Originurl)|"visit"::id->(letid=String.concat""idinmatchCore_identifier.of_stringidwith|Error_msgase->e|Okid->Ok(Visitid))|"anchor"::id->(letid=String.concat""idinmatchCore_identifier.of_stringidwith|Error_msgase->e|Okid->Ok(Anchorid))|_whatever->Error"invalid qualifier"letppfmt=function|Anchorid->Format.fprintffmt"anchor=%a"Core_identifier.ppid|Originuri->Format.fprintffmt"origin=%s"uri|Pathpath->Format.fprintffmt"path=%s"path|Visitid->Format.fprintffmt"visit=%a"Core_identifier.ppid|Fragment(l1,l2)->(Format.fprintffmt"lines=%d"l1;matchl2withNone->()|Somel2->Format.fprintffmt"-%d"l2)letto_stringq=Format.asprintf"%a"ppqendtypet=Core_identifier.t*Qualifier.tlist(* TODO: remove once we have >= 4.05 *)letreclist_find_optp=function|[]->None|x::l->ifpxthenSomexelselist_find_optplletof_strings=matchstring_split_on_char';'swith|id::qualifiers->beginmatchCore_identifier.of_stringidwith|Error_msgase->e|Okobject_core_identifier->beginletqualifiers=List.mapQualifier.of_stringqualifiersinmatchlist_find_optresult_is_errorqualifierswith|Some(Error_msgase)->e|Some_->assertfalse|None->letqualifiers=List.mapresult_get_okqualifiersinOk(object_core_identifier,qualifiers)endend|_whatever->Error"invalid swhid"letmkobject_core_identifierqualifiers=(object_core_identifier,qualifiers)letget_core(core,_qualifiers)=coreletget_scheme(core,_qualifiers)=Core_identifier.get_schemecoreletget_kind(core,_qualifiers)=Core_identifier.get_kindcoreletget_hash(core,_qualifiers)=Core_identifier.get_hashcoreletget_qualifiers(_core,qualifiers)=qualifiersletpp_qualifiersfmtq=List.iter(Format.fprintffmt";%a"Qualifier.pp)qletppfmtid=leti=get_coreidinletq=get_qualifiersidinFormat.fprintffmt"%a%a"Core_identifier.ppipp_qualifiersqletto_stringid=Format.asprintf"%a"ppid