meat/meat.nu
2026-05-20 15:11:17 +10:00

297 lines
8 KiB
Text

#!/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> = []] {
if ($env.MONITOR? | is-empty) {
^nix-build --out-link $out $source -A $attr ...$extras
} else {
^nix-build --log-format internal-json -v --out-link $out $source -A $attr ...$extras out+err>| ^$env.MONITOR --json
}
}
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"
nix-build-nom $build $"($env.MEATS)/entry.nix" (system-attr) $extras
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.."
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 }
}
}