Reorganisation of the frontend
Dependencies
- [2]
BQ4E3XLAForwarding stdout/stderr - [3]
Q6PRCWS6Optional argument to set the Ubuntu release for each individual package - [4]
GM4Q532KAdding a post_setup method before unpacking - [5]
VAKO4QFFFormatting - [6]
HX4TXY2DFixed-output derivations enable the network - [7]
ODUDDQRYAdding the OCaml interface - [8]
7Q4257EPFormatting, cleanup and Rust 2021 compatibility - [9]
UWQB743KFirst working shell (with ocaml code) - [*]
KOWYPLMXNix and config.toml
Change contents
- edit in shell.nix at line 98[11.2728][11.2728]
ocamlPackages.yojsonocamlPackages.tomlocamlPackages.hex - edit in elpe/lib/elpe.ml at line 3
include Derivation - replacement in elpe/lib/elpe.ml at line 5[6.56192]→[6.56192:56239](∅→∅),[6.56239]→[6.63961:63997](∅→∅),[6.63997]→[6.56662:58003](∅→∅),[6.56662]→[6.56662:58003](∅→∅),[6.58003]→[6.63998:64595](∅→∅)
exception Error of H2.Client_connection.errortype store_path = { path : string }let ubuntu_release connection ~release ~arch ~repository =let req =Elpegrpc.Elpe.UbuntuReleaseRequest.make ~release ~arch ~repository ()inlet open Ocaml_protoc_plugin inlet open Elpegrpc.Elpe inlet encode, decode = Service.make_client_functions Elpe.ubuntuRelease inlet enc = encode req |> Writer.contents inClient.call ~service:"elpe.Elpe" ~rpc:"UbuntuRelease"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.unary enc ~f:(fun decoder ->let+ decoder = decoder inmatch decoder with| Some decoder -> (Reader.create decoder |> decode |> function| Ok v -> v| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e)))| None -> Elpe.Derivation.Response.make ()))()let ubuntu_package connection ~index ~name =let req = Elpegrpc.Elpe.UbuntuPackageRequest.make ~index ~name () inlet open Ocaml_protoc_plugin inlet open Elpegrpc.Elpe inlet encode, decode = Service.make_client_functions Elpe.ubuntuPackage inlet enc = encode req |> Writer.contents inClient.call ~service:"elpe.Elpe" ~rpc:"UbuntuPackage"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.unary enc ~f:(fun decoder ->let+ decoder = decoder inmatch decoder with| Some decoder -> (Reader.create decoder |> decode |> function| Ok v -> v| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e)))| None -> Elpe.Derivation.Response.make ()))()module Rust = structinclude Rustend - replacement in elpe/lib/elpe.ml at line 9[6.64596]→[6.290:624](∅→∅),[6.624]→[6.64739:64918](∅→∅),[6.64739]→[6.64739:64918](∅→∅),[6.64918]→[2.6654:6743](∅→∅),[2.6743]→[6.58003:58134](∅→∅),[6.64971]→[6.58003:58134](∅→∅),[6.58003]→[6.58003:58134](∅→∅),[6.58134]→[2.6744:7380](∅→∅),[2.7380]→[6.58365:58489](∅→∅),[6.58365]→[6.58365:58489](∅→∅),[6.58489]→[2.7381:7594](∅→∅)
let derivation connection ~name ~builder ~paths ~target ~output_hash =let req =match output_hash with| None ->Elpegrpc.Elpe.DerivationRequest.make ~name ~builder ~paths ~target ()| Some output_hash ->Elpegrpc.Elpe.DerivationRequest.make ~name ~builder ~paths ~target~output_hash ()inlet open Ocaml_protoc_plugin inlet open Elpegrpc.Elpe inlet encode, decode = Service.make_client_functions Elpe.derivation inlet enc = encode req |> Writer.contents inlet result = ref None inlet* _ = Client.call ~service:"elpe.Elpe" ~rpc:"Derivation"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.server_streaming enc ~f:(fun responses ->Lwt_stream.iter_s(fun str ->Reader.create str |> decode |> function| Ok (`Ok path) -> (result := Some(`Ok path); Lwt.return ())| Ok (`Error path) -> (result := Some(`Error path); Lwt.return ())| Ok (`Stdout buf) -> (let buf = Bytes.unsafe_to_string buf inPrintf.printf "%s" buf; Lwt.return ())| Ok (`Stderr buf) -> (let buf = Bytes.unsafe_to_string buf inPrintf.eprintf "%s" buf; Lwt.return ())| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e))| _ -> Lwt.return ())responses))()inmatch !result withSome v -> Lwt.return v| None -> assert falseexception Error of H2.Client_connection.error - edit in elpe/lib/elpe.ml at line 21
let entry : string = entry in - replacement in elpe/lib/elpe.ml at line 102
type build_result = { destdir : string list; paths : string list }class virtual derivation =let local_src p = - edit in elpe/lib/elpe.ml at line 104[6.68548]→[6.58644:58677](∅→∅),[6.58644]→[6.58644:58677](∅→∅),[6.58677]→[6.68549:68805](∅→∅),[6.68805]→[6.58780:58816](∅→∅),[6.58780]→[6.58780:58816](∅→∅),[6.58816]→[3.0:40](∅→∅),[3.40]→[6.58834:58843](∅→∅),[6.58834]→[6.58834:58843](∅→∅)
method virtual name : string(* Returns the script to setup the build process, also used in shells. *)method setup : string Lwt.t = Lwt.return ""(* List of paths resulting from building the package. *)method build : build_result Lwt.t = failwith "Not implemented"endlet backend_conn = ref Nonelet ubuntu ?(release = "plucky") name =object - replacement in elpe/lib/elpe.ml at line 105
method name = namemethod name = Filename.basename p - edit in elpe/lib/elpe.ml at line 110[6.58998]→[6.58998:59078](∅→∅),[6.59078]→[3.41:117](∅→∅),[3.117]→[6.59188:59234](∅→∅),[6.59188]→[6.59188:59234](∅→∅),[6.59234]→[6.68806:68947](∅→∅),[6.68947]→[6.59267:59300](∅→∅),[6.59267]→[6.59267:59300](∅→∅)
inlet* index =Lwt_list.map_p(fun repository ->let* res = ubuntu_release c ~release ~arch:Amd64 ~repository inlet res, _ = Result.get_ok res inmatch res with| `Ok r -> Lwt.return r.destdir| `Error e -> failwith e| _ -> assert false)[ "main"; "universe" ] - replacement in elpe/lib/elpe.ml at line 111
let index = List.concat index inlet* res = ubuntu_package c ~index ~name inlet* res = add_path c p in - edit in elpe/lib/elpe.ml at line 114[6.68969]→[6.68969:69095](∅→∅),[6.69095]→[6.59465:59678](∅→∅),[6.59465]→[6.59465:59678](∅→∅),[6.59678]→[6.69096:69191](∅→∅),[6.69191]→[6.625:688](∅→∅),[6.688]→[6.69191:69473](∅→∅),[6.69191]→[6.69191:69473](∅→∅),[6.69473]→[6.59678:59679](∅→∅),[6.59678]→[6.59678:59679](∅→∅),[6.59679]→[6.69474:70130](∅→∅),[6.70130]→[6.59679:59699](∅→∅),[6.59679]→[6.59679:59699](∅→∅),[6.59699]→[6.70131:70319](∅→∅),[6.70319]→[6.59856:59908](∅→∅),[6.59856]→[6.59856:59908](∅→∅),[6.59908]→[6.70320:70423](∅→∅),[6.70423]→[6.59983:59992](∅→∅),[6.59983]→[6.59983:59992](∅→∅),[6.59992]→[4.0:43](∅→∅),[4.43]→[6.70424:70496](∅→∅),[6.59992]→[6.70424:70496](∅→∅),[6.70517]→[6.70517:70629](∅→∅),[6.70629]→[4.44:121](∅→∅),[4.121]→[6.60214:60215](∅→∅),[6.70692]→[6.60214:60215](∅→∅),[6.60214]→[6.60214:60215](∅→∅),[6.60215]→[4.122:160](∅→∅),[4.160]→[6.70693:70770](∅→∅),[6.60215]→[6.70693:70770](∅→∅),[6.70770]→[6.60343:60344](∅→∅),[6.60343]→[6.60343:60344](∅→∅),[6.60344]→[6.70771:71021](∅→∅),[6.71021]→[6.60588:60589](∅→∅),[6.60588]→[6.60588:60589](∅→∅),[6.60589]→[6.71022:71105](∅→∅),[6.71105]→[6.61249:61250](∅→∅),[6.61249]→[6.61249:61250](∅→∅),[6.61250]→[6.71106:71380](∅→∅),[6.71380]→[6.61359:61360](∅→∅),[6.61359]→[6.61359:61360](∅→∅),[6.61360]→[6.71381:71456](∅→∅),[6.71456]→[6.61596:61597](∅→∅),[6.61596]→[6.61596:61597](∅→∅),[6.61597]→[6.71457:71567](∅→∅),[6.71567]→[6.689:795](∅→∅),[6.795]→[6.71663:71689](∅→∅),[6.71663]→[6.71663:71689](∅→∅),[6.71689]→[6.61678:61679](∅→∅),[6.61678]→[6.61678:61679](∅→∅),[6.61679]→[6.71690:71769](∅→∅),[6.71769]→[6.61761:61762](∅→∅),[6.61761]→[6.61761:61762](∅→∅),[6.61762]→[6.71770:71886](∅→∅),[6.71886]→[6.796:922](∅→∅),[6.922]→[6.71990:72016](∅→∅),[6.71990]→[6.71990:72016](∅→∅),[6.72016]→[6.61943:61944](∅→∅),[6.61943]→[6.61943:61944](∅→∅),[6.61944]→[6.72017:72403](∅→∅),[6.72403]→[6.923:968](∅→∅),[6.968]→[2.7595:7610](∅→∅),[2.7610]→[6.985:1103](∅→∅),[6.985]→[6.985:1103](∅→∅),[6.1103]→[2.7611:7630](∅→∅)
| `Ok r -> Lwt.return { destdir = r.destdir; paths = r.paths }| `Error e -> failwith e| _ -> assert falseendclass virtual std_derivation =object (self)inherit derivationmethod environment : (string * string) List.t Lwt.t = Lwt.return []method build_inputs : derivation list Lwt.t = Lwt.return []method target : string = "x86_64-linux-gnu"val extra_paths : string list ref = ref []method output_hash : string option Lwt.t = Lwt.return Nonemethod derivation (drv : derivation) =let* path = drv#build inextra_paths := path.destdir @ !extra_paths;Lwt.return pathmethod local_src p =let path_drv =objectinherit derivationmethod name = Filename.basename pmethod! build =let c =match !backend_conn with| None -> failwith "no conn"| Some c -> cinlet* res = add_path c p inlet res, _ = Result.get_ok res inmatch res with| `Ok r -> Lwt.return { destdir = r.destdir; paths = r.paths }| `Error e -> failwith e| _ -> assert falseendinlet* built = path_drv#build inextra_paths := built.destdir @ !extra_paths;Lwt.return (List.hd built.destdir)method src : string Lwt.t = failwith ("No src defined for " ^ self#name)method! setup =let* bash = self#derivation (ubuntu "bash-static") inlet bash = List.hd bash.destdir inlet* build_inputs = self#build_inputs inlet* () =Lwt_list.iter_p(fun d ->let* p = d#build inextra_paths := p.destdir @ !extra_paths;Lwt.return ())build_inputsinlet* post_setup = self#post_setup inLwt.return("#!" ^ bash^ "/usr/bin/bash-static\n\export PATH=/usr/bin\n\export LIBRARY_PATH=/lib/" ^ self#target ^ ":/lib64/" ^ self#target^ ":/usr/lib:/usr/lib64:/usr/lib/x86_64-linux-gnu\n"^post_setup^"\n")method post_setup = Lwt.return ""method pre_unpack = Lwt.return ""method post_unpack = Lwt.return ""method unpack_phase =let* src = self#src inlet* all = Lwt.all [ self#pre_unpack; self#post_unpack ] inmatch all with| pre :: post :: _ -> Lwt.return (pre ^ "\ncp -R " ^ src ^ "/* .\n" ^ post)| _ -> assert falsemethod pre_configure = Lwt.return ""method post_configure = Lwt.return ""method configure_phase =let* all = Lwt.all [ self#pre_configure; self#post_configure ] inmatch all with| pre :: post :: _ ->Lwt.return(pre ^ "\nif [[ -e configure ]]; then ./configure; fi\n" ^ post)| _ -> assert falsemethod pre_build = Lwt.return ""method post_build = Lwt.return ""method build_phase =let* all = Lwt.all [ self#pre_build; self#post_build ] inmatch all with| pre :: post :: _ ->Lwt.return (pre ^ "\nif [[ -e Makefile ]]; then make; fi\n" ^ post)| _ -> assert falsemethod pre_install = Lwt.return ""method post_install = Lwt.return ""method install_phase =let* all = Lwt.all [ self#pre_install; self#post_install ] inmatch all with| pre :: post :: _ ->Lwt.return(pre ^ "\nif [[ -e Makefile ]]; then make install; fi\n" ^ post)| _ -> assert falsemethod! build =let* phases =Lwt.all[self#setup;self#unpack_phase;self#configure_phase;self#build_phase;self#install_phase;]inlet builder = String.concat "\n" phases inlet c =match !backend_conn with None -> failwith "no conn" | Some c -> cinlet* output_hash = self#output_hash inlet* r =derivation c ~name:self#name ~builder ~paths:!extra_paths~target:self#target ~output_hashinmatch r with - replacement in elpe/lib/dune at line 5
(libraries grpc-lwt lwt lwt.unix h2 h2-lwt-unix ocaml-protoc-plugin))(libraries grpc-lwt lwt lwt.unix h2 h2-lwt-unix ocaml-protoc-plugin core yojson toml hex)) - file addition: derivation.ml[6.55449]
open Lwt.Syntaxtype store_path = { path : string }type build_result = { destdir : string list; paths : string list }let backend_conn = ref Noneclass virtual derivation =objectmethod virtual name : stringval stdout_ : Buffer.t option ref = ref Noneval stderr_ : Buffer.t option ref = ref Nonemethod stdout = stdout_method stderr = stderr_method set_stdout =let buf = Buffer.create 1024 instdout_ := Some buf;bufmethod set_stderr =let buf = Buffer.create 1024 instderr_ := Some buf;buf(* Returns the script to setup the build process, also used in shells. *)method setup : string Lwt.t = Lwt.return ""(* List of paths resulting from building the package. *)method build : build_result Lwt.t = failwith "Not implemented"endopen Grpc_lwtlet ubuntu_release connection ~release ~arch ~repository =let req =Elpegrpc.Elpe.UbuntuReleaseRequest.make ~release ~arch ~repository ()inlet open Ocaml_protoc_plugin inlet encode, decode =Service.make_client_functions Elpegrpc.Elpe.Elpe.ubuntuReleaseinlet enc = encode req |> Writer.contents inClient.call ~service:"elpe.Elpe" ~rpc:"UbuntuRelease"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.unary enc ~f:(fun decoder ->let+ decoder = decoder inmatch decoder with| Some decoder -> (Reader.create decoder |> decode |> function| Ok v -> v| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e)))| None -> Elpegrpc.Elpe.Elpe.Derivation.Response.make ()))()let ubuntu_package connection ~index ~name =let req = Elpegrpc.Elpe.UbuntuPackageRequest.make ~index ~name () inlet open Ocaml_protoc_plugin inlet encode, decode =Service.make_client_functions Elpegrpc.Elpe.Elpe.ubuntuPackageinlet enc = encode req |> Writer.contents inClient.call ~service:"elpe.Elpe" ~rpc:"UbuntuPackage"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.unary enc ~f:(fun decoder ->let+ decoder = decoder inmatch decoder with| Some decoder -> (Reader.create decoder |> decode |> function| Ok v -> v| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e)))| None -> Elpegrpc.Elpe.Elpe.Derivation.Response.make ()))()let ubuntu ?(release = "plucky") name =objectinherit derivationmethod name = namemethod! build =let c =match !backend_conn with None -> failwith "no conn" | Some c -> cinlet* index =Lwt_list.map_p(fun repository ->let* res = ubuntu_release c ~release ~arch:Amd64 ~repository inlet res, _ = Result.get_ok res inmatch res with| `Ok r -> Lwt.return r.destdir| `Error e -> failwith e| _ -> assert false)[ "main"; "universe" ]inlet index = List.concat index inlet* res = ubuntu_package c ~index ~name inlet res, _ = Result.get_ok res inmatch res with| `Ok r -> Lwt.return { destdir = r.destdir; paths = r.paths }| `Error e -> failwith e| _ -> assert falseendlet derivation ?(stdout = None) ?(stderr = None) connection ~name ~builder~paths ~target ~output_hash =let req =match output_hash with| None ->Elpegrpc.Elpe.DerivationRequest.make ~name ~builder ~paths ~target ()| Some output_hash ->Elpegrpc.Elpe.DerivationRequest.make ~name ~builder ~paths ~target~output_hash ()inlet open Ocaml_protoc_plugin inlet encode, decode =Service.make_client_functions Elpegrpc.Elpe.Elpe.derivationinlet enc = encode req |> Writer.contents inlet result = ref None inlet* _ =Client.call ~service:"elpe.Elpe" ~rpc:"Derivation"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.server_streaming enc ~f:(fun responses ->Lwt_stream.iter_s(fun str ->Reader.create str |> decode |> function| Ok (`Ok path) ->result := Some (`Ok path);Lwt.return ()| Ok (`Error path) ->result := Some (`Error path);Lwt.return ()| Ok (`Stdout buf) ->let _ =match stdout with| Some b -> Buffer.add_bytes b buf| None ->let buf = Bytes.to_string buf inPrintf.printf "%s" bufinLwt.return ()| Ok (`Stderr buf) ->let _ =match stderr with| Some b -> Buffer.add_bytes b buf| None ->let buf = Bytes.to_string buf inPrintf.printf "%s" bufinLwt.return ()| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e))| _ -> Lwt.return ())responses))()inmatch !result with Some v -> Lwt.return v | None -> assert falseclass virtual std_derivation =object (self)inherit derivationmethod environment : (string * string) List.t Lwt.t = Lwt.return []method build_inputs : derivation list Lwt.t = Lwt.return []method target : string = "x86_64-linux-gnu"val extra_paths : string list ref = ref []val extra_paths_h : (string, unit) Hashtbl.t = Hashtbl.create 16method output_hash : string option Lwt.t = Lwt.return Nonemethod derivation (drv : derivation) =let* path = drv#build inList.fold_right(fun r () ->if Hashtbl.find_opt extra_paths_h r = None thenlet _ = Hashtbl.add extra_paths_h r () inextra_paths := r :: !extra_pathselse ())path.destdir ();Lwt.return pathmethod src : derivation Lwt.t = failwith ("No src defined for " ^ self#name)method! setup =let* bash = self#derivation (ubuntu "bash-static") inlet bash = List.hd bash.destdir inlet* build_inputs = self#build_inputs inlet* paths =Lwt_list.map_p(fun d ->let* p = d#build inextra_paths := p.destdir @ !extra_paths;Lwt.return p.destdir)build_inputsinlet path =List.fold_left(List.fold_left (fun acc path ->(if acc = "" then acc ^ path else acc ^ ":" ^ path) ^ "/usr/bin"))"" pathsinlet* post_setup = self#post_setup inLwt.return("#!" ^ bash ^ "/usr/bin/bash-static\nexport PATH=" ^ path^ "\nexport LIBRARY_PATH=/lib/" ^ self#target ^ ":/lib64/" ^ self#target^ ":/usr/lib:/usr/lib64:/usr/lib/x86_64-linux-gnu\n" ^ post_setup ^ "\n")method post_setup = Lwt.return ""method pre_unpack = Lwt.return ""method post_unpack = Lwt.return ""method unpack_phase =let* src = self#src inlet* src_built = src#build inextra_paths := src_built.destdir @ !extra_paths;let* all = Lwt.all [ self#pre_unpack; self#post_unpack ] inmatch all with| pre :: post :: _ ->Lwt.return(pre ^ "\ncp -R " ^ List.hd src_built.destdir ^ "/. .\n" ^ post)| _ -> assert falsemethod pre_configure = Lwt.return ""method post_configure = Lwt.return ""method configure_phase =let* all = Lwt.all [ self#pre_configure; self#post_configure ] inmatch all with| pre :: post :: _ ->Lwt.return(pre ^ "\nif [[ -e configure ]]; then ./configure; fi\n" ^ post)| _ -> assert falsemethod pre_build = Lwt.return ""method post_build = Lwt.return ""method build_phase =let* all = Lwt.all [ self#pre_build; self#post_build ] inmatch all with| pre :: post :: _ ->Lwt.return (pre ^ "\nif [[ -e Makefile ]]; then make; fi\n" ^ post)| _ -> assert falsemethod pre_install = Lwt.return ""method post_install = Lwt.return ""method install_phase =let* all = Lwt.all [ self#pre_install; self#post_install ] inmatch all with| pre :: post :: _ ->Lwt.return(pre ^ "\nif [[ -e Makefile ]]; then make install; fi\n" ^ post)| _ -> assert falsemethod! build =let* phases =Lwt.all[self#setup;self#unpack_phase;self#configure_phase;self#build_phase;self#install_phase;]inlet builder = String.concat "\n" phases inlet c =match !backend_conn with None -> failwith "no conn" | Some c -> cinlet* output_hash = self#output_hash inlet* r =derivation c ~name:self#name ~builder ~paths:!extra_paths~stdout:!(self#stdout) ~stderr:!(self#stderr) ~target:self#target~output_hashinmatch r with| `Ok r -> Lwt.return { destdir = r.destdir; paths = r.paths }| `Error e -> failwith e| _ -> assert falseendlet http ~url ~hash_algorithm ~hash =objectinherit derivationmethod name = "http"method! build =let connection =match !backend_conn with None -> failwith "no conn" | Some c -> cinlet req =Elpegrpc.Elpe.AddUrlRequest.make ~url ~hash_algorithm ~hash ()inlet* res =let open Ocaml_protoc_plugin inlet encode, decode =Service.make_client_functions Elpegrpc.Elpe.Elpe.addUrlinlet enc = encode req |> Writer.contents inClient.call ~service:"elpe.Elpe" ~rpc:"AddUrl"~do_request:(H2_lwt_unix.Client.request connection ~error_handler:(fun _ ->failwith "Error"))~handler:(Client.Rpc.unary enc ~f:(fun decoder ->let+ decoder = decoder inmatch decoder with| Some decoder -> (Reader.create decoder |> decode |> function| Ok v -> v| Error e ->failwith(Printf.sprintf "Could not decode request: %s"(Result.show_error e)))| None -> Elpegrpc.Elpe.Elpe.Derivation.Response.make ()))()inlet res, _ = Result.get_ok res inmatch res with| `Ok r -> Lwt.return { destdir = r.destdir; paths = r.paths }| `Error e -> failwith e| _ -> assert falseend - edit in elpe/dune-project at line 17
(depends ocaml elpe lwt core core_unix) - edit in elpe/dune-project at line 21
(depends ocaml lwt grpc-lwt h2-lwt-unix ocaml-protoc-plugin protoc) - edit in default.nix at line 119
ocamlPackages.hex