1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
open Conex_utils open Conex_resource open Conex_opam_repository_layout open Conex_opam_encoding type t = { basedir : string ; description : string ; file_type : path -> (file_type, string) result ; read : path -> (string, string) result ; write : path -> string -> (unit, string) result ; read_dir : path -> (item list, string) result ; exists : path -> bool ; } (*BISECT-IGNORE-BEGIN*) let pp ppf t = Format.fprintf ppf "repository %s: %s" t.basedir t.description (*BISECT-IGNORE-END*) type cc_err = [ `FileNotFound of name | `NotADirectory of name ] (*BISECT-IGNORE-BEGIN*) let pp_cc_err ppf = function | `FileNotFound n -> Format.fprintf ppf "couldn't find file %a" pp_name n | `NotADirectory n -> Format.fprintf ppf "expected %a to be a directory, but it is a file" pp_name n (*BISECT-IGNORE-END*) let checksum_files t pv = (match authorisation_of_package pv with | Some de -> Ok (data_path@[ de ; pv ]) | None -> Error (`FileNotFound pv )) >>= fun st -> let rec collect1 acc d = function | File, f when d = [] && f = release_filename -> acc | File, f -> (d@[f]) :: acc | Directory, dir -> let sub = d @ [ dir ] in match t.read_dir (st@sub) with | Error _ -> [] | Ok data -> List.fold_left (fun acc x -> collect1 acc sub x) acc data in match t.read_dir st with | Error _ -> Error (`FileNotFound pv) | Ok data -> Ok (List.fold_left (fun acc x -> collect1 [] [] x @ acc) [] data) let compute_release digest t now name = let checksum filename data = let digest = digest data in { Release.filename ; digest } in match t.file_type (release_dir name) with | Error _ -> Error (`FileNotFound name) | Ok File -> Error (`NotADirectory name) | Ok Directory -> checksum_files t name >>= fun fs -> let d = release_dir name in foldM (fun acc f -> match t.read (d@f) with | Error _ -> Error (`FileNotFound (path_to_string (d@f))) | Ok data -> Ok (data :: acc)) [] fs >>= fun ds -> let r = List.(map2 checksum (map path_to_string fs) (rev ds)) in Ok (Release.t now name r) let read_dir f t path = t.read_dir path >>= fun data -> Ok (S.of_list (filter_map ~f data)) let ids t = read_dir (function File, f -> Some f | _ -> None) t id_path let dirs = (function Directory, d -> Some d | _ -> None) let packages t = read_dir dirs t data_path let releases t name = read_dir dirs t (data_path@[name]) let compute_package t now name = releases t name >>= fun releases -> Ok (Package.t ~releases now name) type r_err = [ `NotFound of typ * name | `ParseError of typ * name * string | `NameMismatch of typ * name * name ] (*BISECT-IGNORE-BEGIN*) let pp_r_err ppf = function | `NotFound (res, nam) -> Format.fprintf ppf "%a %a was not found in repository" pp_typ res pp_name nam | `ParseError (res, n, e) -> Format.fprintf ppf "parse error while parsing %a %a: %s" pp_typ res pp_name n e | `NameMismatch (res, should, is) -> Format.fprintf ppf "%a %a is named %a" pp_typ res pp_name should pp_name is (*BISECT-IGNORE-END*) let read_team t name = match t.read (id_file name) with | Error _ -> Error (`NotFound (`Team, name)) | Ok data -> match decode data >>= Team.of_wire with | Error p -> Error (`ParseError (`Team, name, p)) | Ok team -> if id_equal team.Team.name name then Ok team else Error (`NameMismatch (`Team, name, team.Team.name)) let write_team t team = let id = team.Team.name in t.write (id_file id) (encode (Team.wire team)) let read_author t name = match t.read (id_file name) with | Error _ -> Error (`NotFound (`Author, name)) | Ok data -> match decode data >>= Author.of_wire with | Error p -> Error (`ParseError (`Author, name, p)) | Ok i -> if id_equal i.Author.name name then Ok i else Error (`NameMismatch (`Author, name, i.Author.name)) let write_author t i = let name = id_file i.Author.name in t.write name (encode (Author.wire i)) let read_id t id = match read_team t id with | Ok team -> Ok (`Team team) | Error _ -> match read_author t id with | Ok idx -> Ok (`Author idx) | Error e -> Error e let read_authorisation t name = match t.read (authorisation_path name) with | Error _ -> Error (`NotFound (`Authorisation, name)) | Ok data -> match decode data >>= Authorisation.of_wire with | Error p -> Error (`ParseError (`Authorisation, name, p)) | Ok auth -> if name_equal auth.Authorisation.name name then Ok auth else Error (`NameMismatch (`Authorisation, name, auth.Authorisation.name)) let write_authorisation t a = t.write (authorisation_path a.Authorisation.name) (encode (Authorisation.wire a)) let read_package t name = match t.read (package_path name) with | Error _ -> Error (`NotFound (`Package, name)) | Ok data -> match decode data >>= Package.of_wire with | Error p -> Error (`ParseError (`Package, name, p)) | Ok r -> if name_equal r.Package.name name then Ok r else Error (`NameMismatch (`Package, name, r.Package.name)) let write_package t r = let name = package_path r.Package.name in t.write name (encode (Package.wire r)) let read_release t name = match t.read (release_path name) with | Error _ -> Error (`NotFound (`Release, name)) | Ok data -> match decode data >>= Release.of_wire with | Error p -> Error (`ParseError (`Release, name, p)) | Ok csum -> if name_equal csum.Release.name name then Ok csum else Error (`NameMismatch (`Release, name, csum.Release.name)) let write_release t csum = let name = release_path csum.Release.name in t.write name (encode (Release.wire csum))