Skip to content

Instantly share code, notes, and snippets.

@frankitox
Created November 23, 2024 15:58
Show Gist options
  • Save frankitox/b8a74c934d728b280116cf2b30317b57 to your computer and use it in GitHub Desktop.
Save frankitox/b8a74c934d728b280116cf2b30317b57 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bb
(ns print-nvd-diff
(:require
[babashka.cli :as cli]
[babashka.fs :as fs]
[babashka.process :as proc]
[clojure.string :as string]))
(defmacro ensure!
[x msg info-map]
`(when-not ~x
(throw (ex-info ~msg ~info-map))))
(def docstring
"List all builds that match #\"/nix/var/nix/profiles/system-([0-9]+)-link\"
and prints an nvd diff of the two latest (higher integer) builds
Use LATEST~n to change the default builds to compare
eg: LATEST~2 LATEST~ compares third to last and second to last builds.
defaults to LATEST~ LATEST")
(defn parse-arg [arg]
(or (some-> (re-matches #"LATEST(~*)" arg)
(second)
(count))
(some-> (re-matches #"LATEST~([0-9]+)" arg)
(second)
(Integer/parseInt))
(throw (ex-info "Can't parse arg" {:arg arg}))))
(defn get-nvd-diff! [from-offset to-offset]
(let [versions (->> (fs/list-dir "/nix/var/nix/profiles")
(mapv str)
(filterv (fn [f]
(string/starts-with?
f
"/nix/var/nix/profiles/system-")))
(mapv (fn [f]
{:link f
:version (-> (re-matches #"/nix/var/nix/profiles/system-([0-9]+)-link" f)
(second)
(Integer/parseInt))}))
(sort-by :version)
(reverse)
(vec))
_ (ensure! (>= (count versions)
(max from-offset to-offset))
"Not enough versions to apply these offsets"
{:offsets [from-offset to-offset]})
to (nth versions to-offset)
from (nth versions from-offset)]
(->> (proc/sh {:out :string
:err :string}
"nvd" "--color" "never" "diff"
(str "/nix/var/nix/profiles/system-" (:version from) "-link")
(str "/nix/var/nix/profiles/system-" (:version to) "-link"))
(:out)
(string/split-lines)
(mapv (fn [line]
(if (string/starts-with? line "[")
(let [number (second (re-matches #".*\s(\#[0-9]+)\s.*" line))
number-idx (string/index-of line number)]
(-> (str (subs line 0 (dec number-idx))
(subs line (+ number-idx
(count number)
2)))
(string/replace #"\s+" " ")))
line)))
(reduce conj ["Update system" ""])
(string/join \newline))))
(defn -main [& cli-args]
(let [{:keys [args opts] :as cli} (cli/parse-args
cli-args
{:spec
{:help {:coerce :boolean}}})]
(ensure! (<= (count args) 2)
"Can't have more than 2 positional args"
cli)
(if (:help opts)
(println docstring)
(let [from-offset (-> (first args)
(or "LATEST~")
(parse-arg))
to-offset (-> (second args)
(or "LATEST")
(parse-arg))]
(println (get-nvd-diff! from-offset to-offset))))))
(when (= *file* (System/getProperty "babashka.file"))
(apply -main *command-line-args*))
;; vi: ft=clojure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment