meat/meat.nu
2026-05-29 01:32:31 +10:00

284 lines
7.7 KiB
Text
Executable file

#!/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 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, build_args: list<string>] {
if ($env.MONITOR? | is-empty) {
^nix-build --out-link $out ...$build_args
} else {
^nix-build --log-format internal-json --out-link $out ...$build_args out+err>| ^$env.MONITOR --json
}
# Piping to MONITOR masks nix-build's exit code, so detect failure by the
# absence of the out-link.
if not ($out | path exists) {
error make { msg: "nix-build produced no output" }
}
}
def differ-step [build: string] {
if ($env.DIFFER? | is-empty) {
meat-print " (no DIFFER set; skipping diff)"
} else {
^$env.DIFFER /nix/var/nix/profiles/system $build
}
}
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"
warm-pins
let start = date now
let drv = ^nix-instantiate $"($env.MEATS)/entry.nix" -A (system-attr) ...$extras | lines | last | str trim
meat-print $"MASTICATION TAKING ((date now) - $start)"
nix-build-nom $build [$drv]
differ-step $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.."
warm-pins
try { ^nix-build --no-out-link $"($env.MEATS)/entry.nix" -A (system-attr) ...$args }
}
}
def cmd-poke [...args: string] {
with-frame {
meat-print "PREPARING SUSPICIOUS MEATS.."
warm-pins
try { ^nix-build --no-out-link --show-trace $"($env.MEATS)/entry.nix" -A (system-attr) ...$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 lock-path [] { $"($env.MEATS)/.tack/pins.lock.json" }
def load-lock [] {
let p = lock-path
if ($p | path exists) { open --raw $p | from json } else { {} }
}
# Fetch one locked input into the store, mirroring the tack resolver's
# `builtins.fetchTree lock.<name>`. Returns the name on failure, else null.
def warm-pin [name: string, node: record] {
let tmp = ^mktemp -t "meat-pin.XXXXXX.json" | str trim
$node | to json | save -f $tmp
let expr = $"\(builtins.fetchTree \(builtins.fromJSON \(builtins.readFile \"($tmp)\"\)\)\).outPath"
let r = ^nix eval --impure --raw --expr $expr | complete
try { rm $tmp }
if $r.exit_code != 0 { $name } else { null }
}
# Pre-fetch every locked input in parallel so the serial fetchTree calls
# during evaluation become cache hits. Warming is idempotent and non-fatal:
# anything that fails here is simply re-fetched by the build itself.
def warm-pins [] {
let lock = load-lock
let names = $lock | columns
if ($names | is-empty) { return }
meat-print "GATHERING MEATS.."
let failed = $names | par-each { |name| warm-pin $name ($lock | get $name) } | compact
for name in $failed {
meat-print $" COULDN'T GATHER ($name | str upcase) \(BUILD WILL RETRY\)"
}
}
def cmd-fresh [...names: string] {
with-frame {
meat-print "HUNTING FRESH MEATS.."
do { cd $env.MEATS; ^$env.TACK update ...$names }
}
}
def cmd-look [...names: string] {
with-frame {
meat-print "LOOK FOR NEW MEATS.."
do { cd $env.MEATS; ^$env.TACK look ...$names }
}
}
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 {
warm-pins
nix-build-nom $nix_conf [$"($meats)/entry.nix" "-A" (nix-conf-attr)]
meat-print "CONSUMING MEATS.."
with-env { NIX_USER_CONF_FILES: $nix_conf } {
nix-build-nom $build [$"($meats)/entry.nix" "-A" (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 ...$rest }
"fresh" => { cmd-fresh ...$rest }
"hunt" => { cmd-hunt ...$rest }
"ritual" => { cmd-ritual }
"shelter" => { cmd-shelter $rest }
_ => { cmd-help }
}
}