pijul nest
guest [sign in]

Fork channel

Create a new channel as a copy of main.

Rename channel

Rename main to:

Delete channel

Delete main? This cannot be undone.

elpe_bin.ml
open Lwt.Syntax

let connection address port =
  let open Lwt.Syntax in
  (* Setup Http/2 connection *)
  let* addresses =
    Lwt_unix.getaddrinfo address (string_of_int port)
      [ Unix.(AI_FAMILY PF_INET) ]
  in
  let socket = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
  let* () = Lwt_unix.connect socket (List.hd addresses).Unix.ai_addr in
  let error_handler e = raise (Elpe.Error e) in
  H2_lwt_unix.Client.create_connection ~error_handler socket

let run_shell (spec : Elpe.derivation) cmd =
  let* b = spec#setup in

  let* bash = (Elpe.ubuntu "bash-static")#build in
  let bash = List.hd bash.destdir in

  let f = Filename.temp_dir "elpe-" "" ^ "/setup" in
  Unix.mkfifo f 0o666;

  let pid =
    Unix.create_process
      (bash ^ "/usr/bin/bash-static")
      (match cmd with
      | None -> [| "bash"; "--init-file"; f; "-i" |]
      | Some cmd -> [| "bash"; "--init-file"; f; "-i"; "-c"; cmd |])
      Unix.stdin Unix.stdout Unix.stderr
  in

  let p = Unix.openfile f [ Unix.O_WRONLY ] 0o644 in
  let _ = Unix.write_substring p b 0 (String.length b) in
  Unix.close p;

  match Unix.waitpid [] pid with
  | _, Unix.WEXITED e -> Lwt.return e
  | _ -> failwith "Unknown"

let run_build (spec : Elpe.derivation) =
  let* b = spec#build in
  print_endline (List.fold_left (fun _ x -> x) "" b.destdir);
  Lwt.return ()

let compile input_files =
  (* Compile *)
  let args =
    Array.of_list
      ([
         "ocamlfind";
         (if Dynlink.is_native then "ocamlopt" else "ocamlc");
         "-package";
         "elpe";
         "-c";
       ]
      @ input_files)
  in
  let pid =
    let rd, wr = Unix.pipe () in
    let pid = Unix.create_process "ocamlfind" args rd Unix.stdout Unix.stderr in
    Unix.close wr;
    pid
  in
  let _ =
    match Unix.waitpid [] pid with
    | _, Unix.WEXITED 0 -> ()
    | _, Unix.WEXITED e -> Unix._exit e
    | _ -> print_endline "other"
  in
  let port = 50051 in
  let address = "127.0.0.1" in
  let* c = connection address port in
  Elpe.backend_conn := Some c;

  (* Link *)
  Dynlink.set_allowed_units [ "Elpe" ];
  let obj =
    Dynlink.adapt_filename
      (Filename.remove_extension (Array.get args (Array.length args - 1))
      ^ ".cmo")
  in
  Lwt.return (Dynlink.loadfile obj)

let shell =
  Core.Command.basic ~summary:""
    (let%map_open.Command cmd =
       flag "-c" (optional string) ~doc:"Command to run in this shell"
     and files = anon (sequence ("file" %: string)) in
     fun () ->
       Elpe.last_built_module := None;
       Lwt_main.run
         (let* _ = compile (if files = [] then [ "shell.ml" ] else files) in
          match !Elpe.last_built_module with
          | None -> Unix._exit 0
          | Some last ->
              let* last = last in
              let* shell = run_shell last cmd in
              Unix._exit shell))

let build =
  Core.Command.basic ~summary:""
    (let%map_open.Command files = anon (sequence ("file" %: string)) in
     fun () ->
       Elpe.last_built_module := None;
       Lwt_main.run
         (let* _ = compile (if files = [] then [ "build.ml" ] else files) in
          match !Elpe.last_built_module with
          | None -> Lwt.return ()
          | Some last ->
              let* last = last in
              run_build (last :> Elpe.derivation)))

let command =
  Core.Command.group ~summary:"Elpe" [ ("shell", shell); ("build", build) ]

let () = Command_unix.run command
(* if !input_files != [] then *)
(*   let exit = compile_and_run () in *)
(*   Unix._exit exit *)
(* else Printf.eprintf "\n" *)