package dkml-install
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
API and registry for Diskuv OCaml (DKML) installation components
Install
dune-project
Dependency
Authors
Maintainers
Sources
dkml-install-api-0.4.0.tar.gz
md5=1b3f42a06b0643eb502e6f65d1769b98
sha512=55d47cb8c570f3e9fbdb5f4f7960c86fbe357df6c5364c82c9eb326150693fa1dbffe3fa3f5682e355f770c5f3c53bd7ce88ec1d1d9eefecceb8f44ed8b1d326
doc/src/dkml-install.register/registry.ml.html
Source file registry.ml
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 176open Dkml_install_api let ( let* ) = Forward_progress.bind let ( let+ ) r f = Forward_progress.map f r let return = Forward_progress.return type t = (string, (module Component_config)) Hashtbl.t type component_selector = | All_components | Just_named_components_plus_their_dependencies of string list let global_registry : t = Hashtbl.create 17 let get () = global_registry let on_error s = function | Some true -> raise (Invalid_argument s) | _ -> prerr_endline s; exit (Forward_progress.Exit_code.to_int_exitcode Exit_unrecoverable_failure) let add_component ?raise_on_error reg cfg = let module Cfg = (val cfg : Component_config) in match Validate.validate (module Cfg) with | Ok () -> ( match Hashtbl.find_opt reg Cfg.component_name with | Some _component -> on_error (Fmt.str "FATAL [debe504f]. The component named '%s' has already been \ added to the registry" Cfg.component_name) raise_on_error | None -> Logs.debug (fun m -> m "@[Adding component '%s' to the registry with installation \ dependencies:@]@ @[<v>%a@]@ @[and uninstallation \ dependencies:@]@ @[<v>%a@]" Cfg.component_name Fmt.(Dump.list string) Cfg.install_depends_on Fmt.(Dump.list string) Cfg.uninstall_depends_on); Hashtbl.add reg Cfg.component_name cfg) | Error s -> on_error (Fmt.str "FATAL [7c039d7e]. %s" s) raise_on_error let validate ?raise_on_error reg = Hashtbl.to_seq_values reg |> List.of_seq |> List.iter (fun cfg -> let module Cfg = (val cfg : Component_config) in List.iter (fun dependency -> if Hashtbl.mem reg dependency then () else let msg = Fmt.str "FATAL [14b63c08]. The component '%s' declares a dependency \ on '%s' but that dependency is not available as a plugin. \ Check the following in order: 1) Has `dkml-component-%s` \ been added as an Opam (or findlib) dependency? 2) Does \ `dkml-component-%s` call [Registry.add_component] using \ [component_name=%a]?" Cfg.component_name dependency dependency dependency Fmt.Dump.string dependency in on_error msg raise_on_error) (Cfg.install_depends_on @ Cfg.uninstall_depends_on)) let toposort reg ~dependency_getter ~selector ~fl = let vertex_map = Hashtbl.to_seq_values reg |> List.of_seq |> List.map (fun cfg -> let module Cfg = (val cfg : Component_config) in (Cfg.component_name, dependency_getter cfg)) in let+ tsorted_all = match Tsort.sort vertex_map with | Sorted lst -> return ( List.filter_map (fun component_name -> Hashtbl.find_opt reg component_name) lst, fl ) | ErrorCycle lst -> fl ~id:"2b217eea" Fmt.( str "There is a circular dependency chain: %a" (list ~sep:(any "->@ ") string) lst); Halted_progress Exit_unrecoverable_failure in match selector with | All_components -> tsorted_all | Just_named_components_plus_their_dependencies named_components -> let tsorted_all_names = List.map (fun cfg -> let module Cfg = (val cfg : Component_config) in Cfg.component_name) tsorted_all in (* visit each named component and each of their dependencies *) let named_components_plus_dependencies = let visited = Hashtbl.create (List.length tsorted_all) in let rec walk_each_named_component = function | [] -> () | hd :: tl -> let rec visit_dep_graph cfg_name = match Hashtbl.find_opt reg cfg_name with | Some cfg -> let module Cfg = (val cfg : Component_config) in (* theoretically we don't have to check for cycles since we used topological sort. however `reg` is a mutable global and subject to race conditions, so double-check for cycles *) if not (Hashtbl.mem visited cfg_name) then ( Hashtbl.add visited cfg_name (); List.iter (fun cfg_name' -> visit_dep_graph cfg_name') (dependency_getter cfg)) | None -> () in visit_dep_graph hd; walk_each_named_component tl in walk_each_named_component named_components; visited in (* order `named_components_plus_dependencies` in topological order *) List.filter_map (fun cfg_name -> if Hashtbl.mem named_components_plus_dependencies cfg_name then Hashtbl.find_opt reg cfg_name else None) tsorted_all_names let eval_each ~f ~fl lst = List.fold_left (fun acc cfg -> let* v, _fl = acc in match f cfg with | Dkml_install_api.Forward_progress.Continue_progress (v2, fl) -> return (v2 :: v, fl) | Halted_progress v -> Halted_progress v | Completed -> Completed) (return ([], fl)) lst let install_eval reg ~selector ~f ~fl = let dependency_getter cfg = let module Cfg = (val cfg : Component_config) in Cfg.install_depends_on in let* res, _fl = Forward_progress.map (eval_each ~f ~fl) (toposort ~dependency_getter ~selector ~fl reg) in Forward_progress.map List.rev res let uninstall_eval reg ~selector ~f ~fl = let dependency_getter cfg = let module Cfg = (val cfg : Component_config) in Cfg.uninstall_depends_on in let* res, _fl = Forward_progress.map (eval_each ~f ~fl) (Forward_progress.map List.rev (toposort ~dependency_getter ~selector ~fl reg)) in Forward_progress.map List.rev res module Private = struct let reset () = Hashtbl.clear global_registry end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>