diff options
| author | ยท๐๐ด๐๐๐ฉ๐ค | 2025-12-10 13:00:26 +0000 |
|---|---|---|
| committer | ยท๐๐ด๐๐๐ฉ๐ค | 2025-12-10 13:00:26 +0000 |
| commit | 3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0 (patch) | |
| tree | 5ce28db0cd6a4f15a7626fb1b9982e13a7b6f086 /lib/nixtamal.ml | |
| parent | d3f85acf813d78c6d9972c8f10ff9c3a76bd0f08 (diff) | |
| download | nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar.gz nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar.bz2 nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar.lz nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar.xz nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.tar.zst nixtaml-3df27ffb2bd40f3eaeed6dfb08ef3041cc60bfe0.zip | |
ocaml onset
Diffstat (limited to 'lib/nixtamal.ml')
| -rw-r--r-- | lib/nixtamal.ml | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/lib/nixtamal.ml b/lib/nixtamal.ml new file mode 100644 index 0000000..bb865f6 --- /dev/null +++ b/lib/nixtamal.ml @@ -0,0 +1,190 @@ +(*โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ +โ SPDX-FileCopyrightText: 2025 toastal <https://toast.al/contact/> โ +โ SPDX-License-Identifier: LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception โ +โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ*) +module Error = Error +module Name = Name +module Manifest = Manifest +module Input = Input +module Input_foreman = Input_foreman +module Working_directory = Working_directory + +type error = Error.error + +let meld_input_with_lock (input : Input.t) (lock : Lockfile.Input'.t) : Input.t = {input with + kind = ( + match input.kind, lock.kind with + | `File file, `File _ -> + `File file + | `Archive archive, `Archive _ -> + `Archive archive + | `Git git, `Git({latest_revision; _}: Lockfile.Git.t) -> + `Git {git with latest_revision} + | `Darcs darcs, `Darcs({reference; latest_weak_hash; _}: Lockfile.Darcs.t) -> + `Darcs {darcs with + latest_weak_hash; + reference = ( + match darcs.reference, reference with + | `Context (`Assumed None), `Context (`Assumed Some _) -> reference + | _ -> darcs.reference + ); + } + | `Pijul pijul, `Pijul({latest_state; _}: Lockfile.Pijul.t) -> + `Pijul {pijul with latest_state} + | _, _ -> failwith "Input kind mismatch." + ); + hash = {input.hash with value = lock.hash.value}; + latest = {input.latest with value = lock.latest_value} +} + +let read_manifest_and_lockfile () : (Name.Name.t list, error) result = + let (let*) = Result.bind in + let* manifest = + Error.tag_manifest @@ begin + match Manifest.read () with + | Ok(kdl : Kdl.t) -> + Manifest.document_to_t kdl + |> Result.map_error (fun err -> `Parsing err) + | Error(e : Kdl.error) -> + let v_errs : Util.KDL.Valid.err list = [`ParseError e] in + Error (`Parsing v_errs) + end + in + let* lockfile_opt = + Error.tag_lockfile @@ begin + Lockfile.read () + |> Result.map_error (fun e -> `Parsing e) + end + in + match lockfile_opt with + | Some lock when not (String.equal manifest.version lock.version) -> + Error (`Version_mismatch (manifest.version, lock.version)) + | _ -> + let to_input d = + let input = Manifest.Input'.of_manifest d in + let found_input = + Option.bind lockfile_opt (fun lock -> Name.NameMap.find_opt input.name lock.inputs) + in + match found_input with + | None -> input + | Some locked -> meld_input_with_lock input locked + in + Error.tag_input_foreman @@ begin + let rec set_input_htbl ret mnfsts = + match ret, mnfsts with + | Error err, _ -> Error err + | Ok names, [] -> Ok names + | Ok names, d :: ds -> + let input : Input.t = to_input d in + let res = + Input_foreman.add input.name input + |> Result.map (fun () -> input.name :: names) + in + set_input_htbl res ds + in + let* names = set_input_htbl (Ok []) manifest.inputs in + Logs.debug (fun m -> m "Names from reckoning manifest ร lockfile: %a" Fmt.(brackets (list ~sep: semi Name.Name.pp)) names); + Ok names + end + +let set_up ~env ?nixpkgs: nixpkgs_opt () : (unit, error) result = + let (let*) = Result.bind in + Eio.Switch.run @@ fun sw -> + let proc_mgr = Eio.Stdenv.process_mgr env in + Working_directory.set_up_root (); + if Manifest.exists () then + begin + Logs.err (fun m -> + m + "Found existing โ%sโ file, so project is already set up. Quitting." + Manifest.filename + ); + Error (`Manifest `File_already_exists) + end + else + (* TODO: returns a bool for success, so what to do? *) + let* () = + match nixpkgs_opt with + | None -> Ok () + | Some npkgs -> + let* () = + Error.tag_input_foreman @@ begin + let* () = Input_foreman.add Input.Nixpkgs.name npkgs in + Input_foreman.lock_one ~env ~sw ~proc_mgr ~force: false ~name: Input.Nixpkgs.name + end + in + let _lockfile = Lockfile.make () in + Ok () + in + let* () = + Error.tag_manifest @@ begin + let () = Manifest.make () in + Manifest.write () + end + in + let* () = + Error.tag_lockfile @@ begin + Lockfile.write ~create: (`Exclusive 0o644) () + end + in + Lock_loader.write (); + Ok () + +let check_soundness ~env: _ () : (unit, error) result = + let (let*) = Result.bind in + let* _all_names = read_manifest_and_lockfile () in + Logs.app (fun m -> m "All sound."); + Ok () + +let tweak ~env () : (unit, error) result = + let working_dir = Working_directory.get () in + let manifest_file : string = + let path = Eio.Path.(working_dir / Manifest.filename) in + Eio.Path.native_exn path + in + let () = Editor.run_on manifest_file in + check_soundness ~env () + +let show ~env: _ () : (unit, error) result = + let (let*) = Result.bind in + let* _all_names = read_manifest_and_lockfile () in + Logs.app (fun m -> m "%t" Input_foreman.pp_for_earthlings); + Ok () + +let lock ~env ~domain_count ?(force = false) ?names () : (unit, error) result = + Eio.Switch.run @@ fun sw -> + let (let*) = Result.bind in + let proc_mgr = Eio.Stdenv.process_mgr env in + let* all_names = read_manifest_and_lockfile () in + let* () = + Error.tag_input_foreman @@ begin + let names = + match names with + | None | Some [] -> all_names + | Some ns -> ns + in + Input_foreman.lock ~env ~sw ~proc_mgr ~domain_count ~force ~names () + end + in + let* () = Error.tag_lockfile @@ Lockfile.write () in + Lock_loader.write (); + Ok () + +let refresh ~env ~domain_count ?names () : (unit, error) result = + Eio.Switch.run @@ fun sw -> + let (let*) = Result.bind in + let proc_mgr = Eio.Stdenv.process_mgr env in + let* all_names = read_manifest_and_lockfile () in + let* () = + Error.tag_input_foreman @@ begin + let names = + match names with + | None | Some [] -> all_names + | Some ns -> ns + in + Input_foreman.refresh ~env ~sw ~proc_mgr ~domain_count ~names () + end + in + let* () = Error.tag_lockfile @@ Lockfile.write () in + Lock_loader.write (); + Ok () |
