parent
e598b04cae
commit
eeb050b821
28 changed files with 352 additions and 741 deletions
4
bin/dune
4
bin/dune
|
|
@ -1,4 +0,0 @@
|
|||
(executable
|
||||
(public_name meat)
|
||||
(name main)
|
||||
(libraries meat))
|
||||
21
bin/main.ml
21
bin/main.ml
|
|
@ -1,21 +0,0 @@
|
|||
open Meat
|
||||
|
||||
let () =
|
||||
match Sys.getenv_opt "MEATS" with
|
||||
| Some _ ->
|
||||
if Array.length Sys.argv >= 2 then
|
||||
match String.lowercase_ascii (Array.get Sys.argv 1) with
|
||||
| "yum" -> yum ()
|
||||
| "cook" -> cook ()
|
||||
| "poke" -> poke ()
|
||||
| "gut" -> gut ()
|
||||
| "trade" -> trade ()
|
||||
| "look" -> look ()
|
||||
| "fresh" -> fresh ()
|
||||
| "hunt" -> hunt ()
|
||||
| "ritual" -> ritual ()
|
||||
| _ -> help ()
|
||||
else help ()
|
||||
| None ->
|
||||
meat_print "NO PATH TO RUNESTONE FOUND!";
|
||||
help ()
|
||||
26
dune-project
26
dune-project
|
|
@ -1,26 +0,0 @@
|
|||
(lang dune 3.16)
|
||||
|
||||
(name meat)
|
||||
|
||||
(generate_opam_files true)
|
||||
|
||||
(source
|
||||
(github username/reponame))
|
||||
|
||||
(authors "Author Name <author@example.com>")
|
||||
|
||||
(maintainers "Maintainer Name <maintainer@example.com>")
|
||||
|
||||
(license LICENSE)
|
||||
|
||||
(documentation https://url/to/documentation)
|
||||
|
||||
(package
|
||||
(name meat)
|
||||
(synopsis "A short synopsis")
|
||||
(description "A longer description")
|
||||
(depends ocaml dune)
|
||||
(tags
|
||||
("add topics" "to describe" your project)))
|
||||
|
||||
; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html
|
||||
26
flake.lock
generated
26
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1773478949,
|
||||
"narHash": "sha256-8rMpSs2OWGaDlDFO5FS6Pf9WutHBXxM2omPr6hfKydI=",
|
||||
"lastModified": 1779030999,
|
||||
"narHash": "sha256-PLR0pNxIN3JPs/rSVnXTIPXzkPLaGAdt/wjPq7+k1PE=",
|
||||
"owner": "feel-co",
|
||||
"repo": "ndg",
|
||||
"rev": "c3bc1541668e6f6632a7005c7e4963c0a5dedc7b",
|
||||
"rev": "b363612b524436520c85100192ec2bdab9a675c0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -35,11 +35,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774078191,
|
||||
"narHash": "sha256-nyxxxW1/2ouu9dU0I02ul5pHrmUrE1JVFhfFlmYe3Lw=",
|
||||
"lastModified": 1778869304,
|
||||
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "09061f748ee21f68a089cd5d91ec1859cd93d0be",
|
||||
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -51,11 +51,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1773282481,
|
||||
"narHash": "sha256-oFe06TmOy8UUT1f7xMHqDpSYq2Fy1mkIsXZUvdnyfeY=",
|
||||
"rev": "fe416aaedd397cacb33a610b33d60ff2b431b127",
|
||||
"lastModified": 1775036866,
|
||||
"narHash": "sha256-ByAX1LkhCwZ94+KnFAmnJSMAvui7kgCxjHgUHsWAbfI=",
|
||||
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre962285.fe416aaedd39/nixexprs.tar.xz?lastModified=1773282481&rev=fe416aaedd397cacb33a610b33d60ff2b431b127"
|
||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre972949.6201e203d095/nixexprs.tar.xz?lastModified=1775036866&rev=6201e203d09599479a3b3450ed24fa81537ebc4e"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
|
|
@ -64,11 +64,11 @@
|
|||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1774078191,
|
||||
"narHash": "sha256-nyxxxW1/2ouu9dU0I02ul5pHrmUrE1JVFhfFlmYe3Lw=",
|
||||
"lastModified": 1778869304,
|
||||
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "09061f748ee21f68a089cd5d91ec1859cd93d0be",
|
||||
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
60
flake.nix
60
flake.nix
|
|
@ -10,67 +10,26 @@
|
|||
with inputs;
|
||||
let
|
||||
version = builtins.toString self.lastModified;
|
||||
collectPkgs = builtins.attrValues;
|
||||
forEachSystem =
|
||||
function:
|
||||
nixpkgs.lib.genAttrs (import nix-systems) (
|
||||
system: function nixpkgs.legacyPackages.${system} system
|
||||
);
|
||||
deps = forEachSystem (
|
||||
pkgs: _: {
|
||||
build = collectPkgs {
|
||||
inherit (pkgs.ocamlPackages)
|
||||
dune_3
|
||||
ocaml
|
||||
yojson
|
||||
ssl
|
||||
;
|
||||
inherit (pkgs.openssl) dev;
|
||||
};
|
||||
dev = collectPkgs {
|
||||
inherit (pkgs.ocamlPackages)
|
||||
utop
|
||||
ocaml-lsp
|
||||
ocamlformat
|
||||
ocamlformat-rpc-lib
|
||||
;
|
||||
};
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
devShells = forEachSystem (
|
||||
pkgs: sys: {
|
||||
pkgs: _: {
|
||||
default = pkgs.mkShell {
|
||||
packages = pkgs.lib.mapAttrsToList (_: v: v) deps.${sys};
|
||||
shellHook =
|
||||
let
|
||||
justFile = ''
|
||||
default:
|
||||
@just --list
|
||||
|
||||
@build:
|
||||
nix build .#debug --offline
|
||||
|
||||
@release:
|
||||
nix build --offline
|
||||
|
||||
@test:
|
||||
printf "\\n\\n\\t************ running nix+dune tests ************\\n\\n\\n"
|
||||
nix flake check --offline
|
||||
'';
|
||||
in
|
||||
''
|
||||
printf '${justFile}' > justfile
|
||||
'';
|
||||
packages = [
|
||||
pkgs.nushell
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
packages = forEachSystem (
|
||||
pkgs: sys: {
|
||||
pkgs: _: {
|
||||
default = pkgs.callPackage ./nix/default.nix {
|
||||
buildInputs = deps.${sys}.build;
|
||||
inherit version;
|
||||
};
|
||||
docs = pkgs.callPackage unf.lib.pak-chooie {
|
||||
|
|
@ -88,11 +47,18 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.meat;
|
||||
in
|
||||
{
|
||||
imports = [ ./nix/module.nix ];
|
||||
programs.meat.package = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
programs.meat.package = self.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs {
|
||||
differ = cfg.differ;
|
||||
monitor = cfg.monitor;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "PREPARING DELICIOUS MEATS..";
|
||||
let build_target =
|
||||
Unix.getenv "MEATS" ^ "#nixosConfigurations." ^ Unix.gethostname ()
|
||||
^ ".config.system.build.toplevel"
|
||||
in
|
||||
Common.do_cmd @@ "nix build --no-link" ^ build_target |> ignore;
|
||||
print_string Common.footer
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "HUNTING FRESH MEATS..";
|
||||
let argv_len = Array.length Sys.argv in
|
||||
let root = Sys.getenv "MEATS" in
|
||||
if argv_len >= 3 then
|
||||
let open Array in
|
||||
let flakes = sub Sys.argv 2 (argv_len - 2) in
|
||||
flakes
|
||||
|> iter (fun f ->
|
||||
if Common.all_low f = "meat" then Common.meat_print "PROCESSING REAL MEAT.."
|
||||
else Common.meat_print ("PROCESSING FRESH MEAT " ^ Common.all_caps f ^ "..");
|
||||
Common.do_cmd ~args:false @@ "nix flake update " ^ f ^ " --flake " ^ root
|
||||
|> ignore)
|
||||
else Common.do_cmd @@ "nix flake update --flake " ^ root |> ignore;
|
||||
print_string Common.footer;
|
||||
print_newline ()
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "CLEANING MEAT STORES..";
|
||||
Common.do_cmd "nh clean all" |> ignore;
|
||||
print_string Common.footer
|
||||
|
|
@ -1 +0,0 @@
|
|||
let run () = print_string (Common.header ^ Common.help_text ^ Common.footer ^ "\n")
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
let es_host = "nixos-search-7-1733963800.us-east-1.bonsaisearch.net"
|
||||
|
||||
let es_query term =
|
||||
Printf.sprintf
|
||||
{|{"from":0,"size":20,"sort":[{"_score":"desc","package_attr_name":"desc","package_pversion":"desc"}],"collapse":{"field":"package_attr_name"},"query":{"bool":{"must":[{"term":{"type":"package"}},{"multi_match":{"type":"cross_fields","query":"%s","fields":["package_attr_name^9","package_pname^6","package_description^1.3","package_longDescription^1"]}}]}}}|}
|
||||
term
|
||||
|
||||
let truncate n s = if String.length s > n then String.sub s 0 n ^ ".." else s
|
||||
|
||||
let run () =
|
||||
print_string Common.header;
|
||||
let argv_len = Array.length Sys.argv in
|
||||
if argv_len < 3 then (
|
||||
Common.meat_print "WHAT MEAT ARE YOU HUNTING?";
|
||||
print_string Common.footer)
|
||||
else
|
||||
let query =
|
||||
Array.sub Sys.argv 2 (argv_len - 2)
|
||||
|> Array.to_list |> String.concat " "
|
||||
in
|
||||
Common.meat_print ("HUNTING FOR " ^ Common.all_caps query ^ "..");
|
||||
let body = es_query query in
|
||||
let path = "/nixos-*-unstable-*/_search" in
|
||||
(try
|
||||
let resp = Http.https_post ~host:es_host ~path ~body in
|
||||
let json = Json.parse_json resp in
|
||||
let hits =
|
||||
match Option.bind (Json.jfield "hits" json) (fun h -> Json.jfield "hits" h) with
|
||||
| Some (`List items) -> items
|
||||
| _ -> []
|
||||
in
|
||||
if hits = [] then
|
||||
Common.meat_print "NO MEATS FOUND!"
|
||||
else
|
||||
List.iter
|
||||
(fun hit ->
|
||||
let src =
|
||||
match Json.jfield "_source" hit with Some s -> s | None -> `Null
|
||||
in
|
||||
let name =
|
||||
match Option.bind (Json.jfield "package_attr_name" src) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> "?"
|
||||
in
|
||||
let version =
|
||||
match Option.bind (Json.jfield "package_pversion" src) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> ""
|
||||
in
|
||||
let desc =
|
||||
match Option.bind (Json.jfield "package_description" src) Json.jstring with
|
||||
| Some s -> truncate 60 s
|
||||
| None -> ""
|
||||
in
|
||||
let ver_str = if version <> "" then " (" ^ version ^ ")" else "" in
|
||||
Printf.printf " \tnixpkgs#%s%s\n" name ver_str;
|
||||
if desc <> "" then Printf.printf " \t %s\n" desc)
|
||||
hits
|
||||
with e ->
|
||||
Common.meat_print ("HUNT FAILED: " ^ Printexc.to_string e));
|
||||
print_string Common.footer
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "LOOKING FOR FRESHER MEATS..";
|
||||
let lockfile = Http.read_file (Unix.getenv "MEATS" ^ "/flake.lock") in
|
||||
let json = Json.parse_json lockfile in
|
||||
let nodes =
|
||||
match Json.jfield "nodes" json with Some n -> n | None -> failwith "no nodes"
|
||||
in
|
||||
let root_node =
|
||||
match Json.jfield "root" nodes with Some n -> n | None -> failwith "no root"
|
||||
in
|
||||
let root_inputs =
|
||||
match Json.jfield "inputs" root_node with
|
||||
| Some n -> n
|
||||
| None -> failwith "no root inputs"
|
||||
in
|
||||
let input_pairs =
|
||||
match Json.jassoc root_inputs with
|
||||
| Some p -> p
|
||||
| None -> failwith "root inputs not object"
|
||||
in
|
||||
let any_stale = ref false in
|
||||
List.iter
|
||||
(fun (name, node_ref) ->
|
||||
let node_name =
|
||||
match Json.jstring node_ref with Some s -> s | None -> name
|
||||
in
|
||||
let node =
|
||||
match Json.jfield node_name nodes with
|
||||
| Some n -> n
|
||||
| None -> failwith ("no node: " ^ node_name)
|
||||
in
|
||||
let locked =
|
||||
match Json.jfield "locked" node with
|
||||
| Some n -> n
|
||||
| None -> failwith "no locked"
|
||||
in
|
||||
let original =
|
||||
match Json.jfield "original" node with
|
||||
| Some n -> n
|
||||
| None -> failwith "no original"
|
||||
in
|
||||
let locked_rev =
|
||||
match Option.bind (Json.jfield "rev" locked) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> failwith "no rev"
|
||||
in
|
||||
let locked_type =
|
||||
match Option.bind (Json.jfield "type" locked) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> failwith "no type"
|
||||
in
|
||||
let original_ref = Option.bind (Json.jfield "ref" original) Json.jstring in
|
||||
let host, path =
|
||||
match locked_type with
|
||||
| "github" ->
|
||||
let owner =
|
||||
match Option.bind (Json.jfield "owner" locked) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> failwith "no owner"
|
||||
in
|
||||
let repo =
|
||||
match Option.bind (Json.jfield "repo" locked) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> failwith "no repo"
|
||||
in
|
||||
( "github.com",
|
||||
"/" ^ owner ^ "/" ^ repo
|
||||
^ ".git/info/refs?service=git-upload-pack" )
|
||||
| "git" ->
|
||||
let url =
|
||||
match Option.bind (Json.jfield "url" original) Json.jstring with
|
||||
| Some s -> s
|
||||
| None -> failwith "no url"
|
||||
in
|
||||
let prefix = "https://" in
|
||||
let plen = String.length prefix in
|
||||
if String.length url > plen && String.sub url 0 plen = prefix then
|
||||
let after =
|
||||
String.sub url plen (String.length url - plen)
|
||||
in
|
||||
let slash =
|
||||
match String.index_opt after '/' with
|
||||
| Some i -> i
|
||||
| None -> failwith "no path in url"
|
||||
in
|
||||
let h = String.sub after 0 slash in
|
||||
let p =
|
||||
String.sub after slash (String.length after - slash)
|
||||
in
|
||||
(h, p ^ "/info/refs?service=git-upload-pack")
|
||||
else failwith ("unsupported url: " ^ url)
|
||||
| t -> failwith ("unsupported type: " ^ t)
|
||||
in
|
||||
try
|
||||
let body = Http.https_get ~host ~path in
|
||||
let refs = Http.parse_pktline body in
|
||||
let target_ref =
|
||||
match original_ref with
|
||||
| Some r -> "refs/heads/" ^ r
|
||||
| None -> "HEAD"
|
||||
in
|
||||
let latest_rev =
|
||||
match List.assoc_opt target_ref refs with
|
||||
| Some rev -> rev
|
||||
| None -> failwith ("ref not found: " ^ target_ref)
|
||||
in
|
||||
if latest_rev <> locked_rev then (
|
||||
any_stale := true;
|
||||
Common.meat_print (Common.all_caps name ^ " HAS FRESHER MEAT!"))
|
||||
with _ -> Common.meat_print ("COULD NOT REACH " ^ Common.all_caps name ^ ".."))
|
||||
input_pairs;
|
||||
if not !any_stale then Common.meat_print "ALL MEATS ARE FRESH!";
|
||||
print_string Common.footer
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "PREPARING SUSPICIOUS MEATS..";
|
||||
let build_target =
|
||||
Unix.getenv "MEATS" ^ "#nixosConfigurations." ^ Unix.gethostname ()
|
||||
^ ".config.system.build.toplevel"
|
||||
in
|
||||
Common.do_cmd @@ "nix build --no-link " ^ build_target ^ " --show-trace" |> ignore;
|
||||
print_string Common.footer
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "PREPARING RITUAL GROUND..";
|
||||
let ( >>= ) = Result.bind in
|
||||
let ( >|= ) = Fun.flip Result.map in
|
||||
let tmpdir = Filename.temp_dir "meat-chew" "" in
|
||||
let meats = Unix.getenv "MEATS" in
|
||||
let hostname = Unix.gethostname () in
|
||||
let nix_conf_target =
|
||||
meats ^ "/entry.nix -A nixosConfigurations." ^ hostname
|
||||
^ {|'.config.environment.etc."nix/nix.conf"'|}
|
||||
in
|
||||
let build_target =
|
||||
meats ^ "/entry.nix -A nixosConfigurations." ^ hostname
|
||||
^ ".config.system.build.toplevel"
|
||||
in
|
||||
( Common.do_cmd ~args:false
|
||||
@@ "nix-build --log-format internal-json -v --out-link " ^ tmpdir
|
||||
^ "/nix.conf " ^ nix_conf_target ^ " |& nom --json"
|
||||
>>= fun () ->
|
||||
Common.meat_print "CONSUMING MEATS..";
|
||||
Common.do_cmd ~args:false
|
||||
@@ "NIX_USER_CONF_FILES=" ^ tmpdir
|
||||
^ "/nix.conf nix-build --log-format internal-json -v --out-link " ^ tmpdir
|
||||
^ "/build " ^ build_target ^ " |& nom --json"
|
||||
>>= fun () ->
|
||||
Common.do_cmd ~args:false @@ "dix /nix/var/nix/profiles/system " ^ tmpdir
|
||||
^ "/build"
|
||||
>>= fun () ->
|
||||
Common.do_cmd ~args:false
|
||||
@@ "sudo sh -c 'nix-env --set -p /nix/var/nix/profiles/system " ^ tmpdir
|
||||
^ "/build && " ^ tmpdir ^ "/build/bin/switch-to-configuration switch'"
|
||||
>|= fun () ->
|
||||
Unix.unlink @@ tmpdir ^ "/nix-conf";
|
||||
Unix.unlink @@ tmpdir ^ "/build" )
|
||||
|> ( function
|
||||
| Error _ -> print_string "FAILED TO CONSUME MEATS."
|
||||
| _ -> () );
|
||||
print_string Common.footer
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "TRADING FOREIGN MEATS..";
|
||||
Common.do_remote () |> function
|
||||
| Error _ -> print_string "FAILED TO TRADE MEATS."
|
||||
| _ ->
|
||||
();
|
||||
print_string Common.footer
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
let run () =
|
||||
print_string Common.header;
|
||||
Common.meat_print "CONSUMING DELICIOUS MEATS..";
|
||||
( Common.do_build () |> function
|
||||
| Error _ -> print_string "FAILED TO CONSUME MEATS."
|
||||
| _ -> () );
|
||||
print_string Common.footer
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
let header = "\n ----- MEAT ----------------------------------------\n"
|
||||
let footer = "\n ---------------------------------------------------\n"
|
||||
|
||||
let help_text =
|
||||
{|
|
||||
YUM - CONSUME DELICIOUS MEATS
|
||||
COOK - ONLY PREPARE MEATS
|
||||
POKE - TASTE SUSPICIOUS MEATS
|
||||
GUT - CLEAN MEAT STORES
|
||||
FRESH - HUNT FRESH MEATS
|
||||
LOOK - LOOK FOR FRESHER MEATS
|
||||
HUNT - HUNT FOR MEATS IN NIXPKGS
|
||||
RITUAL - PERFORM RITUAL THEN CONSUME
|
||||
TRADE - SEND MEATS FAR AWAY
|
||||
..-A - ..ALL MEATS|}
|
||||
open Sys
|
||||
|
||||
let pass_args () =
|
||||
let len = Array.length argv and sconcat acc el = acc ^ " " ^ el in
|
||||
match len with
|
||||
| 3 -> argv.(2)
|
||||
| n when n > 3 ->
|
||||
print_int (n - 1);
|
||||
Array.fold_left sconcat " " (Array.sub argv 2 (n - 2))
|
||||
| _ -> ""
|
||||
|
||||
let do_cmd ?(args = true) cmd =
|
||||
match command (if args then cmd ^ " " ^ pass_args () else cmd) with
|
||||
| 0 -> Ok ()
|
||||
| e -> Error e
|
||||
|
||||
let meat_print text = print_endline ("\n \t" ^ text ^ "\n")
|
||||
|
||||
let do_build () =
|
||||
let ( >>= ) = Result.bind in
|
||||
let ( >|= ) = Fun.flip Result.map in
|
||||
let tmpdir = Filename.temp_dir "meat-build" "" in
|
||||
let build_target =
|
||||
Unix.getenv "MEATS" ^ "/entry.nix -A nixosConfigurations."
|
||||
^ Unix.gethostname () ^ ".config.system.build.toplevel"
|
||||
in
|
||||
do_cmd @@ "nix-build --log-format internal-json -v --out-link " ^ tmpdir
|
||||
^ "/build " ^ build_target ^ " |& nom --json"
|
||||
>>= fun () ->
|
||||
do_cmd @@ "dix /nix/var/nix/profiles/system " ^ tmpdir ^ "/build"
|
||||
>>= fun () ->
|
||||
do_cmd @@ "sudo sh -c 'nix-env --set -p /nix/var/nix/profiles/system " ^ tmpdir
|
||||
^ "/build && " ^ tmpdir ^ "/build/bin/switch-to-configuration switch'"
|
||||
>|= fun () -> Unix.unlink @@ tmpdir ^ "/build"
|
||||
|
||||
let do_remote () =
|
||||
meat_print "tbd";
|
||||
Ok ()
|
||||
|
||||
let all_flag () =
|
||||
if Array.length argv >= 3 then
|
||||
match Array.get argv 2 with "-a" | "--all" -> true | _ -> false
|
||||
else false
|
||||
|
||||
let all_caps s = s |> String.map (fun c -> Char.uppercase_ascii c)
|
||||
let all_low s = s |> String.map (fun c -> Char.lowercase_ascii c)
|
||||
4
lib/dune
4
lib/dune
|
|
@ -1,4 +0,0 @@
|
|||
(include_subdirs qualified)
|
||||
(library
|
||||
(name meat)
|
||||
(libraries unix ssl yojson))
|
||||
232
lib/http.ml
232
lib/http.ml
|
|
@ -1,232 +0,0 @@
|
|||
let read_file path =
|
||||
let ic = open_in path in
|
||||
let n = in_channel_length ic in
|
||||
let s = really_input_string ic n in
|
||||
close_in ic;
|
||||
s
|
||||
|
||||
let contains_sub haystack needle =
|
||||
let hl = String.length haystack and nl = String.length needle in
|
||||
if nl > hl then false
|
||||
else
|
||||
let rec check i =
|
||||
if i + nl > hl then false
|
||||
else if String.sub haystack i nl = needle then true
|
||||
else check (i + 1)
|
||||
in
|
||||
check 0
|
||||
|
||||
let decode_chunked body =
|
||||
let len = String.length body in
|
||||
let buf = Buffer.create (len / 2) in
|
||||
let i = ref 0 in
|
||||
(try
|
||||
while !i < len do
|
||||
let line_end =
|
||||
let rec find j =
|
||||
if j >= len then raise Exit else if body.[j] = '\r' then j
|
||||
else find (j + 1)
|
||||
in
|
||||
find !i
|
||||
in
|
||||
let size_str = String.sub body !i (line_end - !i) in
|
||||
let size_str =
|
||||
match String.index_opt size_str ';' with
|
||||
| Some idx -> String.sub size_str 0 idx
|
||||
| None -> size_str
|
||||
in
|
||||
let size = int_of_string ("0x" ^ String.trim size_str) in
|
||||
if size = 0 then raise Exit;
|
||||
i := line_end + 2;
|
||||
if !i + size <= len then
|
||||
Buffer.add_string buf (String.sub body !i size);
|
||||
i := !i + size + 2
|
||||
done
|
||||
with Exit -> ());
|
||||
Buffer.contents buf
|
||||
|
||||
let b64_encode src =
|
||||
let tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
|
||||
let len = String.length src in
|
||||
let buf = Buffer.create (len * 4 / 3 + 4) in
|
||||
let i = ref 0 in
|
||||
while !i + 2 < len do
|
||||
let a = Char.code src.[!i] and b = Char.code src.[!i+1] and c = Char.code src.[!i+2] in
|
||||
Buffer.add_char buf tbl.[(a lsr 2) land 0x3f];
|
||||
Buffer.add_char buf tbl.[((a lsl 4) lor (b lsr 4)) land 0x3f];
|
||||
Buffer.add_char buf tbl.[((b lsl 2) lor (c lsr 6)) land 0x3f];
|
||||
Buffer.add_char buf tbl.[c land 0x3f];
|
||||
i := !i + 3
|
||||
done;
|
||||
(match len - !i with
|
||||
| 2 ->
|
||||
let a = Char.code src.[!i] and b = Char.code src.[!i+1] in
|
||||
Buffer.add_char buf tbl.[(a lsr 2) land 0x3f];
|
||||
Buffer.add_char buf tbl.[((a lsl 4) lor (b lsr 4)) land 0x3f];
|
||||
Buffer.add_char buf tbl.[(b lsl 2) land 0x3f];
|
||||
Buffer.add_char buf '='
|
||||
| 1 ->
|
||||
let a = Char.code src.[!i] in
|
||||
Buffer.add_char buf tbl.[(a lsr 2) land 0x3f];
|
||||
Buffer.add_char buf tbl.[(a lsl 4) land 0x3f];
|
||||
Buffer.add_string buf "=="
|
||||
| _ -> ());
|
||||
Buffer.contents buf
|
||||
|
||||
let ssl_inited = ref false
|
||||
|
||||
let https_request ~meth ~host ~path ?(headers=[]) ?(body="") () =
|
||||
if not !ssl_inited then (
|
||||
Ssl.init ();
|
||||
ssl_inited := true);
|
||||
let he = Unix.gethostbyname host in
|
||||
let addr = he.h_addr_list.(0) in
|
||||
let sockaddr = Unix.ADDR_INET (addr, 443) in
|
||||
let ctx = Ssl.create_context Ssl.TLSv1_2 Ssl.Client_context in
|
||||
let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
|
||||
Unix.connect sock sockaddr;
|
||||
let ssl = Ssl.embed_socket sock ctx in
|
||||
Ssl.set_client_SNI_hostname ssl host;
|
||||
Ssl.connect ssl;
|
||||
let extra_headers =
|
||||
List.fold_left (fun acc (k, v) -> acc ^ k ^ ": " ^ v ^ "\r\n") "" headers
|
||||
in
|
||||
let content_len = if body <> "" then
|
||||
Printf.sprintf "Content-Length: %d\r\n" (String.length body)
|
||||
else "" in
|
||||
let req =
|
||||
Printf.sprintf "%s %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: meat/1.0\r\nConnection: close\r\n%s%s\r\n%s"
|
||||
meth path host extra_headers content_len body
|
||||
in
|
||||
ignore (Ssl.write ssl (Bytes.of_string req) 0 (String.length req));
|
||||
let buf = Buffer.create 8192 in
|
||||
let chunk = Bytes.create 4096 in
|
||||
(try
|
||||
while true do
|
||||
let n = Ssl.read ssl chunk 0 4096 in
|
||||
if n = 0 then raise Exit;
|
||||
Buffer.add_subbytes buf chunk 0 n
|
||||
done
|
||||
with _ -> ());
|
||||
(try Ssl.shutdown_connection ssl with _ -> ());
|
||||
Unix.close sock;
|
||||
let response = Buffer.contents buf in
|
||||
let rlen = String.length response in
|
||||
let header_end =
|
||||
let rec find pos =
|
||||
if pos + 3 >= rlen then rlen
|
||||
else if
|
||||
response.[pos] = '\r'
|
||||
&& response.[pos + 1] = '\n'
|
||||
&& response.[pos + 2] = '\r'
|
||||
&& response.[pos + 3] = '\n'
|
||||
then pos
|
||||
else find (pos + 1)
|
||||
in
|
||||
find 0
|
||||
in
|
||||
let resp_headers = String.sub response 0 header_end in
|
||||
let body_start = min (header_end + 4) rlen in
|
||||
let resp_body = String.sub response body_start (rlen - body_start) in
|
||||
if
|
||||
contains_sub
|
||||
(String.lowercase_ascii resp_headers)
|
||||
"transfer-encoding: chunked"
|
||||
then decode_chunked resp_body
|
||||
else resp_body
|
||||
|
||||
let https_get ~host ~path =
|
||||
https_request ~meth:"GET" ~host ~path
|
||||
~headers:[("User-Agent", "git/2.0")] ()
|
||||
|
||||
let https_post ~host ~path ~body =
|
||||
https_request ~meth:"POST" ~host ~path
|
||||
~headers:[
|
||||
("Content-Type", "application/json");
|
||||
("Accept", "application/json");
|
||||
("Authorization", "Basic " ^ b64_encode "aWVSALXpZv:X8gPHnzL52wFEekuxsfQ9cSh");
|
||||
] ~body ()
|
||||
|
||||
let parse_pktline body =
|
||||
let len = String.length body in
|
||||
let i = ref 0 in
|
||||
let refs = ref [] in
|
||||
let hex_val c =
|
||||
match c with
|
||||
| '0' .. '9' -> Char.code c - Char.code '0'
|
||||
| 'a' .. 'f' -> Char.code c - Char.code 'a' + 10
|
||||
| 'A' .. 'F' -> Char.code c - Char.code 'A' + 10
|
||||
| _ -> 0
|
||||
in
|
||||
let read_pkt_len () =
|
||||
if !i + 4 > len then 0
|
||||
else
|
||||
let a = hex_val body.[!i]
|
||||
and b = hex_val body.[!i + 1]
|
||||
and c = hex_val body.[!i + 2]
|
||||
and d = hex_val body.[!i + 3] in
|
||||
i := !i + 4;
|
||||
(a * 4096) + (b * 256) + (c * 16) + d
|
||||
in
|
||||
let plen = read_pkt_len () in
|
||||
if plen > 4 then i := !i + (plen - 4);
|
||||
ignore (read_pkt_len ());
|
||||
let continue = ref true in
|
||||
while !continue do
|
||||
let plen = read_pkt_len () in
|
||||
if plen = 0 then continue := false
|
||||
else
|
||||
let payload_len = plen - 4 in
|
||||
if !i + payload_len <= len && payload_len >= 41 then (
|
||||
let payload = String.sub body !i payload_len in
|
||||
i := !i + payload_len;
|
||||
let sha = String.sub payload 0 40 in
|
||||
let rest = String.sub payload 41 (String.length payload - 41) in
|
||||
let refname =
|
||||
let s =
|
||||
match String.index_opt rest '\000' with
|
||||
| Some idx -> String.sub rest 0 idx
|
||||
| None -> rest
|
||||
in
|
||||
match String.index_opt s '\n' with
|
||||
| Some idx -> String.sub s 0 idx
|
||||
| None -> s
|
||||
in
|
||||
refs := (refname, sha) :: !refs)
|
||||
else i := !i + max 0 payload_len
|
||||
done;
|
||||
List.rev !refs
|
||||
|
||||
let derelativise base = List.map (fun a -> base ^ "/" ^ a)
|
||||
|
||||
let filter_dirs fullpath dirs =
|
||||
dirs |> derelativise fullpath
|
||||
|> List.filter (fun d -> (Unix.stat d).st_kind = Unix.S_DIR)
|
||||
|
||||
let readdir d = try Sys.readdir d with Sys_error _ -> [||]
|
||||
|
||||
let walk entry =
|
||||
let open List in
|
||||
let rec loop dir : string list =
|
||||
let contents = readdir dir |> Array.to_list in
|
||||
let is_flake = mem "flake.nix" contents in
|
||||
if dir = entry then
|
||||
let subdirs = contents |> filter_dirs dir in
|
||||
flatten (map loop subdirs)
|
||||
else if is_flake then
|
||||
let subdirs = contents |> filter_dirs dir in
|
||||
let children = flatten (map loop subdirs) in
|
||||
[ dir ] @ children
|
||||
else []
|
||||
in
|
||||
loop entry
|
||||
|
||||
let countdepth s =
|
||||
s |> String.fold_left (fun acc el -> acc + if el = '/' then 1 else 0) 0
|
||||
|
||||
let compdepth a b =
|
||||
let ad = countdepth a and bd = countdepth b in
|
||||
let dif = ad - bd in
|
||||
match dif with 0 -> 0 | _ -> dif / abs dif
|
||||
|
||||
let fmt_dir d = String.split_on_char '/' d |> List.rev |> List.hd |> Common.all_caps
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
let parse_json src = Yojson.Basic.from_string src
|
||||
|
||||
let jfield key = function
|
||||
| `Assoc pairs -> List.assoc_opt key pairs
|
||||
| _ -> None
|
||||
|
||||
let jstring = function `String s -> Some s | _ -> None
|
||||
let jassoc = function `Assoc pairs -> Some pairs | _ -> None
|
||||
11
lib/meat.ml
11
lib/meat.ml
|
|
@ -1,11 +0,0 @@
|
|||
let yum = Commands.Yum.run
|
||||
let cook = Commands.Cook.run
|
||||
let poke = Commands.Poke.run
|
||||
let gut = Commands.Gut.run
|
||||
let trade = Commands.Trade.run
|
||||
let look = Commands.Look.run
|
||||
let fresh = Commands.Fresh.run
|
||||
let hunt = Commands.Hunt.run
|
||||
let ritual = Commands.Ritual.run
|
||||
let help = Commands.Help.run
|
||||
let meat_print = Common.meat_print
|
||||
285
meat.nu
Normal file
285
meat.nu
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
#!/usr/bin/env nu
|
||||
|
||||
const HEADER = "
|
||||
----- MEAT ----------------------------------------
|
||||
"
|
||||
|
||||
const FOOTER = "
|
||||
---------------------------------------------------
|
||||
"
|
||||
|
||||
const HELP_TEXT = "
|
||||
YUM - CONSUME DELICIOUS MEATS
|
||||
COOK - ONLY PREPARE MEATS
|
||||
POKE - TASTE SUSPICIOUS MEATS
|
||||
GUT - CLEAN MEAT STORES
|
||||
FRESH - HUNT FRESH MEATS
|
||||
LOOK - LOOK FOR FRESHER MEATS
|
||||
HUNT - HUNT FOR MEATS IN NIXPKGS
|
||||
RITUAL - PERFORM RITUAL THEN CONSUME
|
||||
TRADE - SEND MEATS FAR AWAY
|
||||
..-A - ..ALL MEATS"
|
||||
|
||||
def meat-print [text: string] {
|
||||
print $"\n \t($text)\n"
|
||||
}
|
||||
|
||||
def with-frame [body: closure] {
|
||||
print -n $HEADER
|
||||
do $body
|
||||
print -n $FOOTER
|
||||
}
|
||||
|
||||
def hn []: nothing -> string {
|
||||
^hostname | str trim
|
||||
}
|
||||
|
||||
def flake-target []: nothing -> string {
|
||||
$"($env.MEATS)#nixosConfigurations.(hn).config.system.build.toplevel"
|
||||
}
|
||||
|
||||
def system-attr []: nothing -> string {
|
||||
$"nixosConfigurations.(hn).config.system.build.toplevel"
|
||||
}
|
||||
|
||||
def nix-conf-attr []: nothing -> string {
|
||||
$"nixosConfigurations.(hn).config.environment.etc.\"nix/nix.conf\""
|
||||
}
|
||||
|
||||
def nix-build-nom [out: string, source: string, attr: string, extras: list<string> = []] {
|
||||
^nix-build --log-format internal-json -v --out-link $out $source -A $attr ...$extras out+err>| ^$env.MONITOR --json
|
||||
}
|
||||
|
||||
def activate [build_path: string] {
|
||||
^sudo $nu.current-exe -c $"nix-env --set -p /nix/var/nix/profiles/system ($build_path); ($build_path)/bin/switch-to-configuration switch"
|
||||
}
|
||||
|
||||
def do-build [extras: list<string> = []] {
|
||||
let tmpdir = ^mktemp -d -t "meat-build.XXXXXX" | str trim
|
||||
let build = $"($tmpdir)/build"
|
||||
nix-build-nom $build $"($env.MEATS)/entry.nix" (system-attr) $extras
|
||||
^$env.DIFFER /nix/var/nix/profiles/system $build
|
||||
activate $build
|
||||
try { rm $build }
|
||||
}
|
||||
|
||||
def cmd-help [] {
|
||||
print -n $"($HEADER)($HELP_TEXT)($FOOTER)\n"
|
||||
}
|
||||
|
||||
def cmd-yum [...args: string] {
|
||||
with-frame {
|
||||
meat-print "CONSUMING DELICIOUS MEATS.."
|
||||
try { do-build $args } catch { print "FAILED TO CONSUME MEATS." }
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-cook [...args: string] {
|
||||
with-frame {
|
||||
meat-print "PREPARING DELICIOUS MEATS.."
|
||||
try { ^nix build --no-link (flake-target) ...$args }
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-poke [...args: string] {
|
||||
with-frame {
|
||||
meat-print "PREPARING SUSPICIOUS MEATS.."
|
||||
try { ^nix build --no-link (flake-target) --show-trace ...$args }
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-gut [...args: string] {
|
||||
with-frame {
|
||||
meat-print "CLEANING MEAT STORES.."
|
||||
try { ^nh clean all ...$args }
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-trade [] {
|
||||
with-frame {
|
||||
meat-print "TRADING FOREIGN MEATS.."
|
||||
meat-print "tbd"
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-fresh [...flakes: string] {
|
||||
with-frame {
|
||||
meat-print "HUNTING FRESH MEATS.."
|
||||
let root = $env.MEATS
|
||||
if ($flakes | is-empty) {
|
||||
try { ^nix flake update --flake $root }
|
||||
} else {
|
||||
for f in $flakes {
|
||||
if ($f | str downcase) == "meat" {
|
||||
meat-print "PROCESSING REAL MEAT.."
|
||||
} else {
|
||||
meat-print $"PROCESSING FRESH MEAT ($f | str upcase).."
|
||||
}
|
||||
try { ^nix flake update $f --flake $root }
|
||||
}
|
||||
}
|
||||
}
|
||||
print ""
|
||||
}
|
||||
|
||||
def lookup-input [nodes: record, name: string, node_ref: any] {
|
||||
let node_name = if (($node_ref | describe) == "string") { $node_ref } else { $name }
|
||||
let node = $nodes | get $node_name
|
||||
let locked = $node.locked
|
||||
let original = $node.original
|
||||
let url = match $locked.type {
|
||||
"github" => $"https://github.com/($locked.owner)/($locked.repo).git"
|
||||
"git" => $original.url
|
||||
_ => { error make { msg: $"unsupported type: ($locked.type)" } }
|
||||
}
|
||||
let target_ref = if ('ref' in $original) { $"refs/heads/($original.ref)" } else { "HEAD" }
|
||||
let out = ^git ls-remote $url $target_ref | complete
|
||||
if $out.exit_code != 0 {
|
||||
error make { msg: "git ls-remote failed" }
|
||||
}
|
||||
let first_line = $out.stdout | str trim | lines | get 0?
|
||||
if ($first_line | is-empty) {
|
||||
error make { msg: "no refs returned" }
|
||||
}
|
||||
let latest = $first_line | split row "\t" | first
|
||||
{ name: $name, locked: $locked.rev, latest: $latest }
|
||||
}
|
||||
|
||||
def cmd-look [] {
|
||||
with-frame {
|
||||
meat-print "LOOK FOR NEW MEATS.."
|
||||
let lock = open --raw $"($env.MEATS)/flake.lock" | from json
|
||||
let nodes = $lock.nodes
|
||||
let root_inputs = $nodes.root.inputs
|
||||
let stale = $root_inputs | transpose name node_ref | each { |row|
|
||||
try {
|
||||
let r = lookup-input $nodes $row.name $row.node_ref
|
||||
if $r.latest != $r.locked {
|
||||
meat-print $"($r.name | str upcase) MEAT RIPE!"
|
||||
$r.name
|
||||
} else { null }
|
||||
} catch {
|
||||
meat-print $"NO FIND ($row.name | str upcase).."
|
||||
null
|
||||
}
|
||||
} | compact
|
||||
if ($stale | is-empty) {
|
||||
meat-print "NO MEAT FRESHER"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def truncate-desc [s: string, n: int]: nothing -> string {
|
||||
if (($s | str length) > $n) {
|
||||
($s | str substring 0..$n) + ".."
|
||||
} else {
|
||||
$s
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-hunt [...query: string] {
|
||||
with-frame {
|
||||
if ($query | is-empty) {
|
||||
meat-print "WHAT MEAT YOU SEEK?"
|
||||
return
|
||||
}
|
||||
let q = $query | str join " "
|
||||
meat-print $"HUNTING FOR ($q | str upcase).."
|
||||
let body = {
|
||||
from: 0,
|
||||
size: 20,
|
||||
sort: [{ _score: "desc", package_attr_name: "desc", package_pversion: "desc" }],
|
||||
collapse: { field: "package_attr_name" },
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{ term: { type: "package" } },
|
||||
{ multi_match: {
|
||||
type: "cross_fields",
|
||||
query: $q,
|
||||
fields: ["package_attr_name^9", "package_pname^6", "package_description^1.3", "package_longDescription^1"]
|
||||
} }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
let resp = (
|
||||
http post
|
||||
--user "aWVSALXpZv"
|
||||
--password "X8gPHnzL52wFEekuxsfQ9cSh"
|
||||
--content-type "application/json"
|
||||
"https://nixos-search-7-1733963800.us-east-1.bonsaisearch.net/nixos-*-unstable-*/_search"
|
||||
$body
|
||||
)
|
||||
let hits = $resp.hits?.hits? | default []
|
||||
if ($hits | is-empty) {
|
||||
meat-print "NO MEATS FOUND!"
|
||||
} else {
|
||||
for hit in $hits {
|
||||
let src = $hit._source
|
||||
let name = $src.package_attr_name? | default "?"
|
||||
let ver = $src.package_pversion? | default ""
|
||||
let desc = $src.package_description? | default ""
|
||||
let ver_str = if ($ver | is-empty) { "" } else { $" \(($ver)\)" }
|
||||
print $" \tnixpkgs#($name)($ver_str)"
|
||||
if not ($desc | is-empty) {
|
||||
print $" \t (truncate-desc $desc 60)"
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch { |e|
|
||||
meat-print $"HUNT FAILED: ($e.msg)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-ritual [] {
|
||||
with-frame {
|
||||
meat-print "PREPARING RITUAL GROUND.."
|
||||
let tmpdir = ^mktemp -d -t "meat-chew.XXXXXX" | str trim
|
||||
let meats = $env.MEATS
|
||||
let nix_conf = $"($tmpdir)/nix.conf"
|
||||
let build = $"($tmpdir)/build"
|
||||
try {
|
||||
nix-build-nom $nix_conf $"($meats)/entry.nix" (nix-conf-attr)
|
||||
meat-print "CONSUMING MEATS.."
|
||||
with-env { NIX_USER_CONF_FILES: $nix_conf } {
|
||||
nix-build-nom $build $"($meats)/entry.nix" (system-attr)
|
||||
}
|
||||
^$env.DIFFER /nix/var/nix/profiles/system $build
|
||||
activate $build
|
||||
try { rm $nix_conf }
|
||||
try { rm $build }
|
||||
} catch {
|
||||
print "FAILED TO CONSUME MEATS."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def cmd-shelter [new_closure: string] {
|
||||
activate $new_closure
|
||||
}
|
||||
|
||||
def main [...args: string] {
|
||||
if ($env.MEATS? | is-empty) {
|
||||
meat-print "NO PATH TO RUNESTONE FOUND!"
|
||||
cmd-help
|
||||
return
|
||||
}
|
||||
let sub = $args | get 0? | default "" | str downcase
|
||||
let rest = $args | skip 1
|
||||
match $sub {
|
||||
"yum" => { cmd-yum ...$rest }
|
||||
"cook" => { cmd-cook ...$rest }
|
||||
"poke" => { cmd-poke ...$rest }
|
||||
"gut" => { cmd-gut ...$rest }
|
||||
"trade" => { cmd-trade }
|
||||
"look" => { cmd-look }
|
||||
"fresh" => { cmd-fresh ...$rest }
|
||||
"hunt" => { cmd-hunt ...$rest }
|
||||
"ritual" => { cmd-ritual }
|
||||
"shelter" => { cmd-shelter $rest }
|
||||
_ => { cmd-help }
|
||||
}
|
||||
}
|
||||
31
meat.opam
31
meat.opam
|
|
@ -1,31 +0,0 @@
|
|||
# This file is generated by dune, edit dune-project instead
|
||||
opam-version: "2.0"
|
||||
synopsis: "A short synopsis"
|
||||
description: "A longer description"
|
||||
maintainer: ["Maintainer Name <maintainer@example.com>"]
|
||||
authors: ["Author Name <author@example.com>"]
|
||||
license: "LICENSE"
|
||||
tags: ["add topics" "to describe" "your" "project"]
|
||||
homepage: "https://github.com/username/reponame"
|
||||
doc: "https://url/to/documentation"
|
||||
bug-reports: "https://github.com/username/reponame/issues"
|
||||
depends: [
|
||||
"ocaml"
|
||||
"dune" {>= "3.16"}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
"-p"
|
||||
name
|
||||
"-j"
|
||||
jobs
|
||||
"@install"
|
||||
"@runtest" {with-test}
|
||||
"@doc" {with-doc}
|
||||
]
|
||||
]
|
||||
dev-repo: "git+https://github.com/username/reponame.git"
|
||||
|
|
@ -1,17 +1,40 @@
|
|||
{
|
||||
ocamlPackages,
|
||||
buildInputs,
|
||||
git,
|
||||
pkgs,
|
||||
lib,
|
||||
stdenvNoCC,
|
||||
nushell,
|
||||
makeBinaryWrapper,
|
||||
version,
|
||||
differ ? pkgs.dix,
|
||||
monitor ? pkgs.nix-output-monitor,
|
||||
...
|
||||
}:
|
||||
ocamlPackages.buildDunePackage {
|
||||
stdenvNoCC.mkDerivation {
|
||||
pname = "meat";
|
||||
version = "0.1-delicious-${version}";
|
||||
|
||||
minimalOCamlVersion = "5.2";
|
||||
|
||||
src = ./..;
|
||||
nativeBuildInputs = [ git ];
|
||||
buildInputs = buildInputs;
|
||||
|
||||
nativeBuildInputs = [ makeBinaryWrapper ];
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -Dm644 meat.nu $out/share/meat/meat.nu
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${nushell}/bin/nu $out/bin/meat \
|
||||
--add-flags "$out/share/meat/meat.nu" \
|
||||
--set DIFFER ${
|
||||
lib.makeBinPath [
|
||||
differ
|
||||
]
|
||||
}
|
||||
--set MONITOR ${
|
||||
lib.makeBinPath [
|
||||
monitor
|
||||
]
|
||||
}
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,21 @@ in
|
|||
type = types.package;
|
||||
description = "your ideal meat";
|
||||
};
|
||||
differ = mkOption {
|
||||
type = types.package;
|
||||
description = "diffing tool to use";
|
||||
default = pkgs.dix;
|
||||
};
|
||||
monitor = mkOption {
|
||||
type = types.package;
|
||||
description = "nix monitoring tool to use";
|
||||
default = pkgs.nix-output-monitor;
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.sessionVariables.MEATS = cfg.flake;
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
pkgs.nh # for now..
|
||||
pkgs.nix-output-monitor
|
||||
pkgs.dix
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
(test
|
||||
(name test_meat))
|
||||
Loading…
Add table
Add a link
Reference in a new issue