Run the source on disk, not the source in git
`nix run .#frq` builds the flake's own copy of the tree, which is the tree as git has it: an uncommitted edit, or one committed on a branch the command was not pointed at, runs as whatever was there before and says nothing about it. A run whose whole purpose is to answer "does my change work" cannot be reading a different file than the one that changed. So: the pins for everything that is not the source — jolt from scripts/jolt, the two native libraries from scripts/lib*.dotslash, both fetched by digest — and jolt started on this directory. `just lib` runs on the way through rather than being asked for first; the pins say what those bytes are, so there was never anything for a person to decide. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
66ba416 parent: bccb134 modified
scripts/run.bb +28 -36 | @@ -3,49 +3,41 @@ | ||
| 3 | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | 4 | ) |
| 5 | 5 | |
| 6 | -;; The app. | |
| 6 | +;; The app, from this working tree. | |
| 7 | 7 | ;; |
| 8 | 8 | ;; run.bb [args...] |
| 9 | 9 | ;; |
| 10 | -;; `nix run .#frq`, which is the whole build: the native libraries, the jolt | |
| 11 | -;; runtime, the dependency graph, and a launcher that puts nixGL in front off | |
| 12 | -;; NixOS so the window opens. Nothing here needs `just lib` first. | |
| 10 | +;; Everything but the source is pinned: jolt comes from scripts/jolt.dotslash | |
| 11 | +;; and the two native libraries from scripts/lib*.dotslash, fetched by digest | |
| 12 | +;; and linked into build/lib, which is the one directory the loader is pointed | |
| 13 | +;; at. `just lib` is done here rather than asked for — the pins say what those | |
| 14 | +;; bytes are, so there is nothing for a person to decide before running. | |
| 13 | 15 | ;; |
| 14 | -;; Nix is not on every host that has this checkout — on the developer's it | |
| 15 | -;; lives in the Arch distrobox — so a host without it is not an error, it is | |
| 16 | -;; the same command run one layer in. The worktree path is the same inside the | |
| 17 | -;; container as outside, which is what lets the `cd` be this path verbatim. | |
| 18 | -(require '[babashka.classpath :as cp]) | |
| 19 | -(cp/add-classpath (str (babashka.fs/parent *file*))) | |
| 20 | -(require '[frq.paths :as paths] | |
| 21 | - '[babashka.fs :as fs] | |
| 22 | - '[babashka.process :as p] | |
| 23 | - '[clojure.string :as str]) | |
| 16 | +;; Deliberately not `nix run .#frq`. That builds the flake's own copy of the | |
| 17 | +;; source, which is the tree as git has it — so an edit that has not been | |
| 18 | +;; committed, or has been committed on a branch the command was not pointed at, | |
| 19 | +;; runs as whatever was there before, silently. A run that is meant to answer | |
| 20 | +;; "does my change work" has to be the files on disk. | |
| 21 | +(require '[babashka.fs :as fs] | |
| 22 | + '[babashka.process :as p]) | |
| 24 | 23 | |
| 25 | 24 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 26 | -(def box (paths/env "FRQ_DISTROBOX" "arch")) | |
| 25 | +(def lib (str (fs/path root "build" "lib"))) | |
| 27 | 26 | |
| 28 | -(defn quote-arg | |
| 29 | - "One argument, safe for a shell that will read the whole line as a string." | |
| 30 | - [s] | |
| 31 | - (str "'" (str/replace (str s) "'" "'\\''") "'")) | |
| 27 | +;; The pinned jolt — scripts/jolt is a DotSlash script, so running it is | |
| 28 | +;; fetching it. Off linux-x86_64 the pin has no asset and the fallback is | |
| 29 | +;; whatever `jolt` is on PATH, which is what that manifest says to do. | |
| 30 | +(def jolt | |
| 31 | + (let [pin (fs/path root "scripts" "jolt")] | |
| 32 | + (if (and (fs/exists? pin) (fs/which "dotslash")) (str pin) "jolt"))) | |
| 32 | 33 | |
| 33 | -;; `--` and then the args: everything past it is the app's, not nix's. | |
| 34 | -(def nix-args | |
| 35 | - (concat ["nix" "run" ".#frq"] | |
| 36 | - (when (seq *command-line-args*) (cons "--" *command-line-args*)))) | |
| 37 | - | |
| 38 | -(def command | |
| 39 | - (if (fs/which "nix") | |
| 40 | - (cons {:dir root} nix-args) | |
| 41 | - (do | |
| 42 | - (when-not (fs/which "distrobox") | |
| 43 | - (paths/die "no nix and no distrobox — install nix, or set FRQ_DISTROBOX" | |
| 44 | - "to a container that has it.")) | |
| 45 | - [{} "distrobox" "enter" box "--" | |
| 46 | - "bash" "-lc" (str "cd " (quote-arg root) " && " | |
| 47 | - (str/join " " (map quote-arg nix-args)))]))) | |
| 34 | +(p/shell (str (fs/path root "scripts" "lib.bb"))) | |
| 48 | 35 | |
| 49 | 36 | (System/exit |
| 50 | - (:exit @(apply p/process (assoc (first command) :inherit true) | |
| 51 | - (rest command)))) | |
| 37 | + (:exit @(apply p/process | |
| 38 | + {:inherit true | |
| 39 | + :dir root | |
| 40 | + :extra-env {"LD_LIBRARY_PATH" | |
| 41 | + (str lib (when-let [p (System/getenv "LD_LIBRARY_PATH")] | |
| 42 | + (str ":" p)))}} | |
| 43 | + jolt "-M:frq" *command-line-args*))) | |
| @@ -3,49 +3,41 @@ | |||
| 3 | exec "$(dirname "$0")/bb" "$0" "$@" | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | ) | 4 | ) |
| 5 | 5 | ||
| 6 | -;; The app. | 6 | +;; The app, from this working tree. |
| 7 | ;; | 7 | ;; |
| 8 | ;; run.bb [args...] | 8 | ;; run.bb [args...] |
| 9 | ;; | 9 | ;; |
| 10 | -;; `nix run .#frq`, which is the whole build: the native libraries, the jolt | 10 | +;; Everything but the source is pinned: jolt comes from scripts/jolt.dotslash |
| 11 | -;; runtime, the dependency graph, and a launcher that puts nixGL in front off | 11 | +;; and the two native libraries from scripts/lib*.dotslash, fetched by digest |
| 12 | -;; NixOS so the window opens. Nothing here needs `just lib` first. | 12 | +;; and linked into build/lib, which is the one directory the loader is pointed |
| 13 | +;; at. `just lib` is done here rather than asked for — the pins say what those | ||
| 14 | +;; bytes are, so there is nothing for a person to decide before running. | ||
| 13 | ;; | 15 | ;; |
| 14 | -;; Nix is not on every host that has this checkout — on the developer's it | 16 | +;; Deliberately not `nix run .#frq`. That builds the flake's own copy of the |
| 15 | -;; lives in the Arch distrobox — so a host without it is not an error, it is | 17 | +;; source, which is the tree as git has it — so an edit that has not been |
| 16 | -;; the same command run one layer in. The worktree path is the same inside the | 18 | +;; committed, or has been committed on a branch the command was not pointed at, |
| 17 | -;; container as outside, which is what lets the `cd` be this path verbatim. | 19 | +;; runs as whatever was there before, silently. A run that is meant to answer |
| 18 | -(require '[babashka.classpath :as cp]) | 20 | +;; "does my change work" has to be the files on disk. |
| 19 | -(cp/add-classpath (str (babashka.fs/parent *file*))) | 21 | +(require '[babashka.fs :as fs] |
| 20 | -(require '[frq.paths :as paths] | 22 | + '[babashka.process :as p]) |
| 21 | - '[babashka.fs :as fs] | ||
| 22 | - '[babashka.process :as p] | ||
| 23 | - '[clojure.string :as str]) | ||
| 24 | 23 | ||
| 25 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 24 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 26 | -(def box (paths/env "FRQ_DISTROBOX" "arch")) | 25 | +(def lib (str (fs/path root "build" "lib"))) |
| 27 | 26 | ||
| 28 | -(defn quote-arg | 27 | +;; The pinned jolt — scripts/jolt is a DotSlash script, so running it is |
| 29 | - "One argument, safe for a shell that will read the whole line as a string." | 28 | +;; fetching it. Off linux-x86_64 the pin has no asset and the fallback is |
| 30 | - [s] | 29 | +;; whatever `jolt` is on PATH, which is what that manifest says to do. |
| 31 | - (str "'" (str/replace (str s) "'" "'\\''") "'")) | 30 | +(def jolt |
| 31 | + (let [pin (fs/path root "scripts" "jolt")] | ||
| 32 | + (if (and (fs/exists? pin) (fs/which "dotslash")) (str pin) "jolt"))) | ||
| 32 | 33 | ||
| 33 | -;; `--` and then the args: everything past it is the app's, not nix's. | 34 | +(p/shell (str (fs/path root "scripts" "lib.bb"))) |
| 34 | -(def nix-args | ||
| 35 | - (concat ["nix" "run" ".#frq"] | ||
| 36 | - (when (seq *command-line-args*) (cons "--" *command-line-args*)))) | ||
| 37 | - | ||
| 38 | -(def command | ||
| 39 | - (if (fs/which "nix") | ||
| 40 | - (cons {:dir root} nix-args) | ||
| 41 | - (do | ||
| 42 | - (when-not (fs/which "distrobox") | ||
| 43 | - (paths/die "no nix and no distrobox — install nix, or set FRQ_DISTROBOX" | ||
| 44 | - "to a container that has it.")) | ||
| 45 | - [{} "distrobox" "enter" box "--" | ||
| 46 | - "bash" "-lc" (str "cd " (quote-arg root) " && " | ||
| 47 | - (str/join " " (map quote-arg nix-args)))]))) | ||
| 48 | 35 | ||
| 49 | (System/exit | 36 | (System/exit |
| 50 | - (:exit @(apply p/process (assoc (first command) :inherit true) | 37 | + (:exit @(apply p/process |
| 51 | - (rest command)))) | 38 | + {:inherit true |
| 39 | + :dir root | ||
| 40 | + :extra-env {"LD_LIBRARY_PATH" | ||
| 41 | + (str lib (when-let [p (System/getenv "LD_LIBRARY_PATH")] | ||
| 42 | + (str ":" p)))}} | ||
| 43 | + jolt "-M:frq" *command-line-args*))) | ||