diff --git a/bin/fruix b/bin/fruix index f85cf07..99120dd 100755 --- a/bin/fruix +++ b/bin/fruix @@ -7,6 +7,10 @@ legacy_guile_bin=/tmp/guile-freebsd-validate-install/bin/guile legacy_guile_extra_prefix=/tmp/guile-gnutls-freebsd-validate-install legacy_shepherd_prefix=/tmp/shepherd-freebsd-validate-install legacy_guix_source_dir=$HOME/repos/guix +fruix_channel_url=${FRUIX_CHANNEL_URL:-https://git.teralink.net/self/fruix.git} +script=$project_root/scripts/fruix.scm +modules_dir=$project_root/modules + if [ -x "$builder_root/guile/bin/guile" ]; then default_guile_bin=$builder_root/guile/bin/guile else @@ -27,13 +31,23 @@ if [ -d "$builder_root/src/guix/guix" ]; then else default_guix_source_dir=$legacy_guix_source_dir fi + guix_source_dir=${GUIX_SOURCE_DIR:-$default_guix_source_dir} guile_bin=${GUILE_BIN:-$default_guile_bin} guile_extra_prefix=${GUILE_EXTRA_PREFIX:-$default_guile_extra_prefix} shepherd_prefix=${SHEPHERD_PREFIX:-$default_shepherd_prefix} -fruix_channel_url=${FRUIX_CHANNEL_URL:-https://git.teralink.net/self/fruix.git} -script=$project_root/scripts/fruix.scm -modules_dir=$project_root/modules + +discover_guile_newt_store() +{ + if [ -n "${FRUIX_GUILE_NEWT_STORE:-}" ] && [ -d "$FRUIX_GUILE_NEWT_STORE" ]; then + printf '%s\n' "$FRUIX_GUILE_NEWT_STORE" + return 0 + fi + for path in /frx/store/*-fruix-guile-newt-*; do + [ -d "$path" ] || continue + printf '%s\n' "$path" + done | sort | tail -n 1 +} if [ ! -x "$guile_bin" ]; then echo "Guile binary is not executable: $guile_bin" >&2 @@ -49,21 +63,71 @@ fi guile_prefix=$(CDPATH= cd -- "$(dirname "$guile_bin")/.." && pwd) guile_lib_dir=$guile_prefix/lib +guile_version=$(LD_LIBRARY_PATH="$guile_lib_dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" "$guile_bin" -c '(display (effective-version))') +guile_newt_store=$(discover_guile_newt_store || true) +guile_load_path="$modules_dir:$guix_source_dir" +if [ -d "$shepherd_prefix/share/guile/site/$guile_version" ]; then + guile_load_path="$guile_load_path:$shepherd_prefix/share/guile/site/$guile_version" +fi +if [ -d "$guile_extra_prefix/share/guile/site/$guile_version" ]; then + guile_load_path="$guile_load_path:$guile_extra_prefix/share/guile/site/$guile_version" +fi +if [ -n "$guile_newt_store" ] && [ -d "$guile_newt_store/share/guile/site/$guile_version" ]; then + guile_load_path="$guile_load_path:$guile_newt_store/share/guile/site/$guile_version" +fi if [ -n "${GUILE_LOAD_PATH:-}" ]; then - guile_load_path="$modules_dir:$guix_source_dir:$GUILE_LOAD_PATH" -else - guile_load_path="$modules_dir:$guix_source_dir" + guile_load_path="$guile_load_path:$GUILE_LOAD_PATH" +fi + +guile_load_compiled_path= +if [ -d "$shepherd_prefix/lib/guile/$guile_version/site-ccache" ]; then + guile_load_compiled_path="$shepherd_prefix/lib/guile/$guile_version/site-ccache" +fi +if [ -d "$guile_extra_prefix/lib/guile/$guile_version/site-ccache" ]; then + guile_load_compiled_path="${guile_load_compiled_path:+$guile_load_compiled_path:}$guile_extra_prefix/lib/guile/$guile_version/site-ccache" +fi +if [ -n "${GUILE_LOAD_COMPILED_PATH:-}" ]; then + guile_load_compiled_path="${guile_load_compiled_path:+$guile_load_compiled_path:}$GUILE_LOAD_COMPILED_PATH" +fi + +guile_extensions_path= +if [ -d "$guile_extra_prefix/lib/guile/$guile_version/extensions" ]; then + guile_extensions_path="$guile_extra_prefix/lib/guile/$guile_version/extensions" +fi +if [ -n "$guile_newt_store" ] && [ -d "$guile_newt_store/lib/guile/$guile_version/extensions" ]; then + guile_extensions_path="${guile_extensions_path:+$guile_extensions_path:}$guile_newt_store/lib/guile/$guile_version/extensions" +fi +if [ -n "${GUILE_EXTENSIONS_PATH:-}" ]; then + guile_extensions_path="${guile_extensions_path:+$guile_extensions_path:}$GUILE_EXTENSIONS_PATH" +fi + +ld_library_path="$guile_extra_prefix/lib:$guile_lib_dir:/usr/local/lib" +ltdl_library_path="$ld_library_path" +if [ -n "$guile_newt_store" ] && [ -d "$guile_newt_store/lib" ]; then + ld_library_path="$guile_newt_store/lib:$ld_library_path" + ltdl_library_path="$guile_newt_store/lib:$ltdl_library_path" +fi +if [ -n "${LD_LIBRARY_PATH:-}" ]; then + ld_library_path="$ld_library_path:$LD_LIBRARY_PATH" +fi +if [ -n "${LTDL_LIBRARY_PATH:-}" ]; then + ltdl_library_path="$ltdl_library_path:$LTDL_LIBRARY_PATH" fi exec env \ GUILE_AUTO_COMPILE=0 \ GUILE_LOAD_PATH="$guile_load_path" \ - LD_LIBRARY_PATH="$guile_lib_dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \ + GUILE_LOAD_COMPILED_PATH="$guile_load_compiled_path" \ + GUILE_EXTENSIONS_PATH="$guile_extensions_path" \ + LD_LIBRARY_PATH="$ld_library_path" \ + LTDL_LIBRARY_PATH="$ltdl_library_path" \ GUILE_PREFIX="$guile_prefix" \ GUILE_EXTRA_PREFIX="$guile_extra_prefix" \ + GUILE_NEWT_PREFIX="$guile_newt_store" \ SHEPHERD_PREFIX="$shepherd_prefix" \ GUIX_SOURCE_DIR="$guix_source_dir" \ + FRUIX_GUILE_NEWT_STORE="$guile_newt_store" \ FRUIX_PROJECT_ROOT="$project_root" \ FRUIX_CHANNEL_DIR="$project_root" \ FRUIX_CHANNEL_URL="$fruix_channel_url" \ diff --git a/docs/recovery.md b/docs/recovery.md new file mode 100644 index 0000000..b452e08 --- /dev/null +++ b/docs/recovery.md @@ -0,0 +1,70 @@ +What we lost + + Everything below was local-only in fruix and is now gone from the repo checkout. + + ### 1. Newt runtime integration on real FreeBSD + + Lost code/work around: + - guile-newt runtime integration into Fruix + - auto-discovery of prepared guile-newt from bin/fruix + - threading Newt runtime into installer artifacts + - installed wrapper env support for Newt + - LTDL_LIBRARY_PATH handling + - installer-only shared-lib exposure under /usr/local/lib + + ### 2. Installer frontend self-test and launcher split + + Lost: + - run-newt-self-test + - --self-test CLI support for installer-tui + - headless tmux-based TUI smoke harness + - installer media launcher split into: + - dispatcher + - backend apply engine + - rc.d frontend-selection knobs + - headless installer-media self-test harness + - XCP-ng installer-media self-test harness + + ### 3. Real XCP-ng validation of the booted installer frontend + + Lost from repo: + - the actual harness/scripts/docs for the successful XCP-ng self-test run + - all code fixes uncovered by that run: + - termcap exposure + - metadata cleaning fix + - Newt media runtime fixes + - frontend dispatch behavior + + ### 4. Installed system console/default tty work + + Lost: + - declarative console-configuration model + - sane default dual console policy + - default gettys on: + - ttyv0..ttyv7 + - ttyu0 + - xc0 + - freebsd-userland additions needed for real login/getty behavior + - getty + - login + - passwd + - su + - who + - last + - nologin + - /etc/gettytab exposure into installed rootfs + - QEMU and XCP-ng validation scripts/reports for console defaults + + ### 5. The package CLI and dev-tool package work + + Lost: + - fruix package list/search/show/build + - package lookup helpers + - added package defs for: + - freebsd-ripgrep + - freebsd-tmux + - freebsd-nodejs + - freebsd-npm + - freebsd-neovim + + This part was not committed yet. diff --git a/docs/recovery_2.md b/docs/recovery_2.md new file mode 100644 index 0000000..ae669b5 --- /dev/null +++ b/docs/recovery_2.md @@ -0,0 +1,189 @@ +Yes — there are useful recovery artifacts, especially in /tmp and /frx/store. + + Best stuff I found + + ### 1. Generated shell scripts in /tmp + + These are very helpful because they capture the rendered output of lost Scheme code. + + Especially: + + - /tmp/fruix-installer-run.sh + - /tmp/fruix-installer-apply.sh + - /tmp/fruix-installer-rc.sh + - /tmp/fruix-installed-fruix.sh + + Those are gold for reconstructing: + + - installer launcher/dispatcher behavior + - self-test flow + - frontend/apply split + - installed wrapper behavior + - Newt-related environment wiring + + Example: /tmp/fruix-installed-fruix.sh still clearly contains: + - build-base + - deploy + - installer-tui + - GUILE_NEWT_PREFIX + - FRUIX_GUILE_NEWT_STORE + - LTDL_LIBRARY_PATH + + So a lot of the lost render.scm work is still recoverable from there. + + ──────────────────────────────────────────────────────────────────────────────── + + ### 2. Validation workdirs in /tmp + + There are lots of preserved run directories. + + Most valuable: + + #### Installer media / Newt / XCP-ng + + - /tmp/current-installer-media-self-test-xcpng-pass3 + - /tmp/current-installer-media-self-test-xcpng-debug* + - /tmp/current-installer-media-self-test-xcpng-fix* + + These contain: + - metadata + - debug logs + - generated declarations + - installer outputs + + Key file: + - /tmp/current-installer-media-self-test-xcpng-pass3/installer-media-self-test-xcpng-metadata.txt + + That preserves the successful real validation result. + + #### Installed console defaults + + - /tmp/current-installed-console-defaults-qemu3 + - /tmp/current-installed-console-defaults-xcpng3 + + These contain: + - generated declarations + - metadata proving the getty/default-console behavior + + Key file: + - /tmp/current-installed-console-defaults-xcpng3/installed-console-defaults-xcpng-metadata.txt + + That preserves the successful real XCP-ng console-default validation. + + ──────────────────────────────────────────────────────────────────────────────── + + ### 3. Package build outputs are still in /frx/store + + The package work is not in git anymore, but the built package outputs still exist: + + - /frx/store/0d75ed1b2220ced7766a72ff72f0908d8683d2e6-freebsd-ripgrep-15.1.0_4 + - /frx/store/4e91ae1c446a61f5056165c73db0a0018378dbe9-freebsd-tmux-3.6a + - /frx/store/9484fd141436bc6e0d6fa19a7a14a360ece3be42-freebsd-nodejs-24.14.0_2 + - /frx/store/a445350b103e45a6841045bb190e50063edfe6a8-freebsd-npm-11.11.0 + - /frx/store/21da570210730ef32025c4010eca138a37b53dc6-freebsd-neovim-0.12.0 + + And importantly, their manifests are still there: + + - .../.fruix-package + + Those manifests preserve enough to reconstruct package definitions pretty well: + - package name + - version + - build system + - input store paths + - install-plan signatures + + So the package work is not fully lost. + + ──────────────────────────────────────────────────────────────────────────────── + + ### 4. Relevant system closures are still in /frx/store + + Useful recovery closures include: + + #### Console-default system closures + + - /frx/store/8f615a0413ec2ad8596055e18b69795e9d37a2f3-fruix-system-fruix-console-defaults + - plus older variants + + These preserve: + - /etc/ttys + - /boot/loader.conf + - generated installed Fruix wrapper + - actual realized output of the lost console/default logic + + #### Installer / Newt closures and ISOs + + - /frx/store/1616e555f705ae2f6be8a7c671d382afa5346535-fruix-guile-newt-0.0.3 + - various fruix-system-fruix-installer-self-test* + - various fruix-installer-iso-fruix-installer-self-test-installer + + Those preserve the actual built results of the lost integration work. + + ──────────────────────────────────────────────────────────────────────────────── + + Less useful, but still maybe helpful + + ### /var/tmp + + I only found one notable thing: + + - /var/tmp/fruix-freebsd-native-build-f2b94d7bfd1feb56a1c597f15a3a2d527653d5571f7a9dc50c47f94cf9758db8 + + This looks like native-build staging/log output. + Useful for native-base archaeology, but not the main recovery source for the lost installer/package work. + + ──────────────────────────────────────────────────────────────────────────────── + + What I did not find + + I do not currently see: + - another full up-to-date checkout + - another git repo with the lost commits + - an obvious source backup of the lost modules/... files + - hidden extra git objects preserving the lost local commits + + So this is not a simple “recover the repo” situation. + + ──────────────────────────────────────────────────────────────────────────────── + + Best recovery sources now + + If we want to reconstruct efficiently, I’d prioritize: + + ### Source reconstruction from /tmp + + - /tmp/fruix-installed-fruix.sh + - /tmp/fruix-installer-run.sh + - /tmp/fruix-installer-apply.sh + - /tmp/fruix-installer-rc.sh + + ### Behavioral truth from /frx/store + + - console-default system closure(s) + - installer self-test closure(s) + - package outputs + .fruix-package + + ### Validation truth from /tmp/current-* + + - current-installer-media-self-test-xcpng-pass3 + - current-installed-console-defaults-qemu3 + - current-installed-console-defaults-xcpng3 + + ──────────────────────────────────────────────────────────────────────────────── + + My recommendation + + Yes, these are worth preserving immediately before we do anything else. + + I’d suggest we first copy/tar: + - the key /tmp workdirs and generated scripts + - the relevant /frx/store paths list + - maybe the one /var/tmp/fruix-freebsd-native-build-* dir + + That would give us a solid recovery bundle. + + If you want, I can do exactly that next: + 1. collect the useful artifacts into a rescue directory + 2. write an inventory file + 3. then start reconstructing the lost code from them. diff --git a/modules/fruix/installer.scm b/modules/fruix/installer.scm index 4ebd318..b9bb530 100644 --- a/modules/fruix/installer.scm +++ b/modules/fruix/installer.scm @@ -39,4 +39,5 @@ newt-required-bindings missing-newt-bindings newt-available? + run-newt-self-test run-newt-installer)) diff --git a/modules/fruix/installer/newt.scm b/modules/fruix/installer/newt.scm index 0fca249..f21bdbc 100644 --- a/modules/fruix/installer/newt.scm +++ b/modules/fruix/installer/newt.scm @@ -6,6 +6,7 @@ #:export (newt-required-bindings missing-newt-bindings newt-available? + run-newt-self-test run-newt-installer)) (define newt-required-bindings @@ -38,38 +39,69 @@ (error "missing required Newt binding" name)) (apply proc args))) -(define* (run-newt-installer state #:key (steps %default-installer-steps)) - (let ((missing (missing-newt-bindings))) +(define (newt-result base-fields mode available? result error missing) + (append `((ui . newt) + (mode . ,mode) + (available? . ,available?) + (result . ,result) + (error . ,error) + (missing-bindings . ,missing)) + base-fields)) + +(define* (run-newt-self-test #:key (steps %default-installer-steps)) + (let* ((missing (missing-newt-bindings)) + (base-fields `((step-count . ,(length steps)) + (step-ids . ,(map installer-step-id steps))))) (if (pair? missing) - `((ui . newt) - (available? . #f) - (missing-bindings . ,missing) - (result . unavailable) - (state . ,(installer-state-spec state)) - (step-count . ,(length steps)) - (step-ids . ,(map installer-step-id steps))) - (dynamic-wind + (newt-result base-fields 'self-test #f 'unavailable #f missing) + (catch #t (lambda () - (call-newt 'newt-init) - (call-newt 'clear-screen)) + (dynamic-wind + (lambda () + (call-newt 'newt-init) + (call-newt 'clear-screen)) + (lambda () + (newt-result base-fields 'self-test #t 'self-test-ok #f '())) + (lambda () + (false-if-exception + (call-newt 'newt-finish))))) + (lambda args + (newt-result base-fields 'self-test #t 'error args '())))))) + +(define* (run-newt-installer state #:key (steps %default-installer-steps)) + (let* ((missing (missing-newt-bindings)) + (base-fields `((state . ,(installer-state-spec state)) + (step-count . ,(length steps)) + (step-ids . ,(map installer-step-id steps))))) + (if (pair? missing) + (newt-result base-fields 'interactive #f 'unavailable #f missing) + (catch #t (lambda () - (call-newt 'message-window - "Fruix installer" - "Continue" - (installer-state-summary state)) - (let ((result (call-newt 'choice-window - "Fruix installer review" - "Proceed" - "Abort" - (installer-final-summary-text state)))) - `((ui . newt) - (available? . #t) - (result . ,(match result - (1 'proceed) - (2 'abort) - (_ 'unknown))) - (state . ,(installer-state-spec state)) - (step-count . ,(length steps)) - (step-ids . ,(map installer-step-id steps))))) - (lambda () - (call-newt 'newt-finish)))))) + (dynamic-wind + (lambda () + (call-newt 'newt-init) + (call-newt 'clear-screen)) + (lambda () + (call-newt 'message-window + "Fruix installer" + "Continue" + (installer-state-summary state)) + (let ((result (call-newt 'choice-window + "Fruix installer review" + "Proceed" + "Abort" + (installer-final-summary-text state)))) + (newt-result base-fields + 'interactive + #t + (match result + (1 'proceed) + (2 'abort) + (_ 'unknown)) + #f + '()))) + (lambda () + (false-if-exception + (call-newt 'newt-finish))))) + (lambda args + (newt-result base-fields 'interactive #t 'error args '())))))) diff --git a/modules/fruix/system/freebsd/media.scm b/modules/fruix/system/freebsd/media.scm index 2cf4e27..e2e0c3a 100644 --- a/modules/fruix/system/freebsd/media.scm +++ b/modules/fruix/system/freebsd/media.scm @@ -68,6 +68,18 @@ '() table)) +(define (discover-fruix-runtime-store store-dir name-fragment) + (and store-dir + (file-exists? store-dir) + (let ((matches + (sort (filter (lambda (entry) + (and (not (member entry '("." ".."))) + (string-contains entry name-fragment) + (file-is-directory? (string-append store-dir "/" entry)))) + (directory-entries store-dir)) + stringstring realized-storage-layout)) (chmod (string-append install-root "/realized-storage-layout.scm") #o644)))) -(define (render-installer-run-script store-dir plan-directory) +(define (render-installer-apply-script store-dir plan-directory) (let ((target-rootfs (string-append plan-directory "/target-rootfs")) (store-items-file (string-append plan-directory "/store-items")) (install-metadata-source (string-append plan-directory "/install.scm")) @@ -855,6 +884,198 @@ "echo 'fruix-installer:done'\n" "write_state done\n"))) +(define (render-installer-run-script store-dir plan-directory) + (let ((state-file (string-append plan-directory "/state")) + (dispatcher-log-file "/var/log/fruix-installer-dispatch.log") + (apply-script "/usr/local/libexec/fruix-installer-apply") + (tui-transcript (string-append plan-directory "/installer-tui.typescript")) + (tui-metadata-file (string-append plan-directory "/installer-tui-metadata.txt"))) + (string-append + "#!/bin/sh\n" + "set -eu\n" + "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin\n" + "umask 022\n" + "state_file='" state-file "'\n" + "dispatcher_log_file='" dispatcher-log-file "'\n" + "apply_script='" apply-script "'\n" + "tui_transcript='" tui-transcript "'\n" + "tui_metadata_file='" tui-metadata-file "'\n" + "frontend=${FRUIX_INSTALLER_FRONTEND:-auto}\n" + "installer_term=${FRUIX_INSTALLER_TERM:-xterm}\n" + "write_state()\n" + "{\n" + " mkdir -p \"$(dirname \"$state_file\")\"\n" + " printf '%s\\n' \"$1\" >\"$state_file\"\n" + "}\n" + "log()\n" + "{\n" + " mkdir -p \"$(dirname \"$dispatcher_log_file\")\"\n" + " printf '%s %s\\n' \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" \"$*\" >>\"$dispatcher_log_file\"\n" + "}\n" + "clean_tui_metadata()\n" + "{\n" + " source=$1\n" + " destination=$2\n" + " [ -f \"$source\" ] || return 1\n" + " tr -d '\\15' < \"$source\" | tr -cd '\\11\\12\\40-\\176' | awk 'match($0, /[a-z_][a-z_]*=.*/){print substr($0, RSTART)}' > \"$destination\"\n" + "}\n" + "metadata_value()\n" + "{\n" + " key=$1\n" + " file=$2\n" + " [ -f \"$file\" ] || return 1\n" + " sed -n \"s/^${key}=//p\" \"$file\" | tail -n 1\n" + "}\n" + "can_run_tui()\n" + "{\n" + " [ -x /usr/local/bin/fruix ] && command -v script >/dev/null 2>&1\n" + "}\n" + "select_tty_device()\n" + "{\n" + " if [ -n \"${FRUIX_INSTALLER_TTY:-}\" ] && [ -e \"$FRUIX_INSTALLER_TTY\" ]; then\n" + " printf '%s\\n' \"$FRUIX_INSTALLER_TTY\"\n" + " return 0\n" + " fi\n" + " boot_console=$(kenv console 2>/dev/null || true)\n" + " case \"$boot_console\" in\n" + " *vidconsole*)\n" + " if [ -e /dev/ttyv0 ]; then\n" + " printf '%s\\n' /dev/ttyv0\n" + " return 0\n" + " fi\n" + " ;;\n" + " esac\n" + " return 1\n" + "}\n" + "run_apply()\n" + "{\n" + " [ -x \"$apply_script\" ] || { log \"missing apply script: $apply_script\"; write_state apply-missing; exit 1; }\n" + " log \"running noninteractive apply\"\n" + " exec \"$apply_script\"\n" + "}\n" + "run_tui_self_test()\n" + "{\n" + " write_state tui-self-test\n" + " rm -f \"$tui_transcript\" \"$tui_metadata_file\"\n" + " if ! env TERM=\"$installer_term\" script -aq \"$tui_transcript\" /usr/local/bin/fruix system installer-tui --self-test >/dev/null 2>&1; then\n" + " clean_tui_metadata \"$tui_transcript\" \"$tui_metadata_file\" || true\n" + " log \"tui self-test command failed\"\n" + " write_state tui-self-test-failed\n" + " return 1\n" + " fi\n" + " clean_tui_metadata \"$tui_transcript\" \"$tui_metadata_file\" || true\n" + " newt_result=$(metadata_value newt_result \"$tui_metadata_file\" || true)\n" + " if [ \"$newt_result\" = self-test-ok ]; then\n" + " log \"tui self-test ok\"\n" + " write_state tui-self-test-ok\n" + " return 0\n" + " fi\n" + " log \"tui self-test unexpected result: ${newt_result:-missing}\"\n" + " write_state tui-self-test-failed\n" + " return 1\n" + "}\n" + "run_tui_session()\n" + "{\n" + " tty_device=$1\n" + " write_state launching-tui\n" + " rm -f \"$tui_transcript\" \"$tui_metadata_file\"\n" + " if env TERM=\"$installer_term\" script -aq \"$tui_transcript\" /usr/local/bin/fruix system installer-tui < \"$tty_device\" > \"$tty_device\" 2>&1; then\n" + " status=0\n" + " else\n" + " status=$?\n" + " fi\n" + " clean_tui_metadata \"$tui_transcript\" \"$tui_metadata_file\" || true\n" + " newt_result=$(metadata_value newt_result \"$tui_metadata_file\" || true)\n" + " case \"$newt_result\" in\n" + " proceed)\n" + " log \"tui proceed\"\n" + " write_state tui-proceed\n" + " return 0\n" + " ;;\n" + " abort)\n" + " log \"tui abort\"\n" + " write_state tui-abort\n" + " return 20\n" + " ;;\n" + " unavailable)\n" + " log \"tui unavailable\"\n" + " return 30\n" + " ;;\n" + " '')\n" + " log \"tui missing result status=$status\"\n" + " return 31\n" + " ;;\n" + " *)\n" + " log \"tui unexpected result: $newt_result status=$status\"\n" + " return 31\n" + " ;;\n" + " esac\n" + "}\n" + "log \"frontend=$frontend\"\n" + "case \"$frontend\" in\n" + " self-test)\n" + " if ! can_run_tui; then\n" + " log \"self-test requested but TUI runtime is unavailable\"\n" + " write_state tui-unavailable\n" + " exit 1\n" + " fi\n" + " run_tui_self_test\n" + " ;;\n" + " auto|tui)\n" + " if ! can_run_tui; then\n" + " if [ \"$frontend\" = auto ]; then\n" + " log \"tui runtime unavailable, falling back to noninteractive apply\"\n" + " run_apply\n" + " fi\n" + " write_state tui-unavailable\n" + " exit 1\n" + " fi\n" + " tty_device=$(select_tty_device || true)\n" + " if [ -z \"$tty_device\" ]; then\n" + " if [ \"$frontend\" = auto ]; then\n" + " log \"no TTY device found, falling back to noninteractive apply\"\n" + " run_apply\n" + " fi\n" + " write_state tui-no-tty\n" + " exit 1\n" + " fi\n" + " run_tui_session \"$tty_device\"\n" + " status=$?\n" + " case \"$status\" in\n" + " 0)\n" + " run_apply\n" + " ;;\n" + " 20)\n" + " exit 0\n" + " ;;\n" + " 30|31)\n" + " if [ \"$frontend\" = auto ]; then\n" + " log \"tui did not complete cleanly, falling back to noninteractive apply status=$status\"\n" + " run_apply\n" + " fi\n" + " write_state tui-failed\n" + " exit 1\n" + " ;;\n" + " *)\n" + " if [ \"$frontend\" = auto ]; then\n" + " log \"tui command failed, falling back to noninteractive apply status=$status\"\n" + " run_apply\n" + " fi\n" + " write_state tui-failed\n" + " exit \"$status\"\n" + " ;;\n" + " esac\n" + " ;;\n" + " noninteractive|apply)\n" + " run_apply\n" + " ;;\n" + " *)\n" + " log \"unknown frontend mode: $frontend\"\n" + " write_state invalid-frontend\n" + " exit 1\n" + " ;;\n" + "esac\n"))) + (define (render-installer-rc-script plan-directory) (string-append "#!/bin/sh\n" @@ -865,16 +1086,17 @@ "name=fruix_installer\n" "rcvar=fruix_installer_enable\n" ": ${fruix_installer_enable:=YES}\n" + ": ${fruix_installer_frontend:=auto}\n" + ": ${fruix_installer_tty:=}\n" "pidfile=/var/run/fruix-installer.pid\n" "command=/usr/sbin/daemon\n" - "command_args='-c -f -p /var/run/fruix-installer.pid -o /var/log/fruix-installer-bootstrap.out /usr/local/libexec/fruix-installer-run'\n" "start_cmd=fruix_installer_start\n" "stop_cmd=fruix_installer_stop\n" "status_cmd=fruix_installer_status\n\n" "fruix_installer_start()\n" "{\n" " mkdir -p '" plan-directory "' /var/run\n" - " $command $command_args\n" + " $command -c -f -p \"$pidfile\" -o /var/log/fruix-installer-bootstrap.out /usr/bin/env \"FRUIX_INSTALLER_FRONTEND=$fruix_installer_frontend\" \"FRUIX_INSTALLER_TTY=$fruix_installer_tty\" /usr/local/libexec/fruix-installer-run\n" "}\n\n" "fruix_installer_stop()\n" "{\n" @@ -1312,10 +1534,13 @@ (string-append (string-join (freebsd-storage-plan-mount-targets target-storage-plan) "\n") "\n")) (write-file (string-append plan-root "/state") "pending\n") + (write-file (string-append image-rootfs "/usr/local/libexec/fruix-installer-apply") + (render-installer-apply-script store-dir installer-plan-directory)) (write-file (string-append image-rootfs "/usr/local/libexec/fruix-installer-run") (render-installer-run-script store-dir installer-plan-directory)) (write-file (string-append image-rootfs "/usr/local/etc/rc.d/fruix-installer") (render-installer-rc-script installer-plan-directory)) + (chmod (string-append image-rootfs "/usr/local/libexec/fruix-installer-apply") #o555) (chmod (string-append image-rootfs "/usr/local/libexec/fruix-installer-run") #o555) (chmod (string-append image-rootfs "/usr/local/etc/rc.d/fruix-installer") #o555) (mkdir-p (string-append esp-stage "/EFI/BOOT")) @@ -1641,10 +1866,13 @@ (string-append (string-join (freebsd-storage-plan-mount-targets target-storage-plan) "\n") "\n")) (write-file (string-append plan-root "/state") "pending\n") + (write-file (string-append image-rootfs "/usr/local/libexec/fruix-installer-apply") + (render-installer-apply-script store-dir installer-plan-directory)) (write-file (string-append image-rootfs "/usr/local/libexec/fruix-installer-run") (render-installer-run-script store-dir installer-plan-directory)) (write-file (string-append image-rootfs "/usr/local/etc/rc.d/fruix-installer") (render-installer-rc-script installer-plan-directory)) + (chmod (string-append image-rootfs "/usr/local/libexec/fruix-installer-apply") #o555) (chmod (string-append image-rootfs "/usr/local/libexec/fruix-installer-run") #o555) (chmod (string-append image-rootfs "/usr/local/etc/rc.d/fruix-installer") #o555) (rewrite-installer-iso-fstab image-rootfs installer-closure-path) diff --git a/modules/fruix/system/freebsd/render.scm b/modules/fruix/system/freebsd/render.scm index c96c41f..dd3f1b4 100644 --- a/modules/fruix/system/freebsd/render.scm +++ b/modules/fruix/system/freebsd/render.scm @@ -493,8 +493,26 @@ (string-append (getenv "HOME") "/repos/guix"))) (specs `((,(string-append repo-root "/scripts/fruix.scm") . "share/fruix/node/scripts/fruix.scm") + (,(string-append repo-root "/modules/fruix/installer.scm") + . "share/fruix/node/modules/fruix/installer.scm") + (,(string-append repo-root "/modules/fruix/installer/final.scm") + . "share/fruix/node/modules/fruix/installer/final.scm") + (,(string-append repo-root "/modules/fruix/installer/newt.scm") + . "share/fruix/node/modules/fruix/installer/newt.scm") + (,(string-append repo-root "/modules/fruix/installer/state.scm") + . "share/fruix/node/modules/fruix/installer/state.scm") + (,(string-append repo-root "/modules/fruix/installer/steps.scm") + . "share/fruix/node/modules/fruix/installer/steps.scm") (,(string-append repo-root "/modules/fruix/packages/freebsd.scm") . "share/fruix/node/modules/fruix/packages/freebsd.scm") + (,(string-append repo-root "/modules/fruix/system/storage.scm") + . "share/fruix/node/modules/fruix/system/storage.scm") + (,(string-append repo-root "/modules/fruix/system/storage/model.scm") + . "share/fruix/node/modules/fruix/system/storage/model.scm") + (,(string-append repo-root "/modules/fruix/system/storage/render.scm") + . "share/fruix/node/modules/fruix/system/storage/render.scm") + (,(string-append repo-root "/modules/fruix/system/storage/validate.scm") + . "share/fruix/node/modules/fruix/system/storage/validate.scm") (,(string-append repo-root "/modules/fruix/system/freebsd.scm") . "share/fruix/node/modules/fruix/system/freebsd.scm") (,(string-append repo-root "/modules/fruix/system/freebsd/build.scm") @@ -509,6 +527,8 @@ . "share/fruix/node/modules/fruix/system/freebsd/render.scm") (,(string-append repo-root "/modules/fruix/system/freebsd/source.scm") . "share/fruix/node/modules/fruix/system/freebsd/source.scm") + (,(string-append repo-root "/modules/fruix/system/freebsd/storage.scm") + . "share/fruix/node/modules/fruix/system/freebsd/storage.scm") (,(string-append repo-root "/modules/fruix/system/freebsd/utils.scm") . "share/fruix/node/modules/fruix/system/freebsd/utils.scm") (,(string-append guix-root "/guix/build/utils.scm") @@ -518,7 +538,7 @@ (read-source-file-string (car entry)))) specs))) -(define (render-installed-system-fruix os guile-store guile-extra-store shepherd-store) +(define (render-installed-system-fruix os guile-store guile-extra-store shepherd-store guile-newt-store) (string-append "#!/bin/sh\n" "set -eu\n" @@ -547,6 +567,7 @@ "guile_store='" guile-store "'\n" "guile_extra_store='" guile-extra-store "'\n" "shepherd_store='" shepherd-store "'\n" + "guile_newt_store='" (or guile-newt-store "") "'\n" "layout_version=2\n" "host_name='" (operating-system-host-name os) "'\n" "ready_marker='" (operating-system-ready-marker os) "'\n" @@ -558,6 +579,7 @@ " fruix system build [DECLARATION [--system NAME] ...]\n" " fruix system build-base [--jobs COUNT] [--store DIR]\n" " fruix system deploy TARGET DECLARATION [--system NAME] ...\n" + " fruix system installer-tui [DECLARATION [--system NAME] ...]\n" " fruix system reconfigure [DECLARATION [--system NAME] ...]\n" " fruix system switch /frx/store/...-fruix-system-...\n" " fruix system rollback\n" @@ -621,12 +643,23 @@ " [ -d \"$node_module_root\" ] || die \"missing bundled Fruix modules: $node_module_root\"\n" " [ -d \"$node_guix_root\" ] || die \"missing bundled Guix modules: $node_guix_root\"\n" " guile_load_path=\"$node_module_root:$node_guix_root:$shepherd_store/share/guile/site/3.0:$guile_extra_store/share/guile/site/3.0\"\n" + " if [ -n \"$guile_newt_store\" ] && [ -d \"$guile_newt_store/share/guile/site/3.0\" ]; then\n" + " guile_load_path=\"$guile_load_path:$guile_newt_store/share/guile/site/3.0\"\n" + " fi\n" " guile_system_path=\"$guile_store/share/guile/3.0:$guile_store/share/guile/site/3.0:$guile_store/share/guile/site:$guile_store/share/guile\"\n" " guile_system_compiled_path=\"$guile_store/lib/guile/3.0/ccache:$guile_store/lib/guile/3.0/site-ccache\"\n" " guile_load_compiled_path=\"$shepherd_store/lib/guile/3.0/site-ccache:$guile_extra_store/lib/guile/3.0/site-ccache\"\n" " guile_system_extensions_path=\"$guile_store/lib/guile/3.0/extensions\"\n" " guile_extensions_path=\"$guile_extra_store/lib/guile/3.0/extensions\"\n" + " if [ -n \"$guile_newt_store\" ] && [ -d \"$guile_newt_store/lib/guile/3.0/extensions\" ]; then\n" + " guile_extensions_path=\"$guile_extensions_path:$guile_newt_store/lib/guile/3.0/extensions\"\n" + " fi\n" " ld_library_path=\"$guile_extra_store/lib:$guile_store/lib:/usr/local/lib\"\n" + " ltdl_library_path=\"$ld_library_path\"\n" + " if [ -n \"$guile_newt_store\" ] && [ -d \"$guile_newt_store/lib\" ]; then\n" + " ld_library_path=\"$guile_newt_store/lib:$ld_library_path\"\n" + " ltdl_library_path=\"$guile_newt_store/lib:$ltdl_library_path\"\n" + " fi\n" " env \\\n" " GUILE_AUTO_COMPILE=0 \\\n" " GUILE_SYSTEM_PATH=\"$guile_system_path\" \\\n" @@ -636,11 +669,14 @@ " GUILE_SYSTEM_EXTENSIONS_PATH=\"$guile_system_extensions_path\" \\\n" " GUILE_EXTENSIONS_PATH=\"$guile_extensions_path\" \\\n" " LD_LIBRARY_PATH=\"$ld_library_path\" \\\n" + " LTDL_LIBRARY_PATH=\"$ltdl_library_path\" \\\n" " GUILE_PREFIX=\"$guile_store\" \\\n" " GUILE_EXTRA_PREFIX=\"$guile_extra_store\" \\\n" + " GUILE_NEWT_PREFIX=\"$guile_newt_store\" \\\n" " SHEPHERD_PREFIX=\"$shepherd_store\" \\\n" " FRUIX_GUILE_STORE=\"$guile_store\" \\\n" " FRUIX_GUILE_EXTRA_STORE=\"$guile_extra_store\" \\\n" + " FRUIX_GUILE_NEWT_STORE=\"$guile_newt_store\" \\\n" " FRUIX_SHEPHERD_STORE=\"$shepherd_store\" \\\n" " GUIX_SOURCE_DIR=\"$node_guix_root\" \\\n" " FRUIX_PROJECT_ROOT=\"$node_root\" \\\n" @@ -740,6 +776,23 @@ " printf 'build_base=ok\\n'\n" " cleanup_build_base\n" "}\n\n" + "installer_tui()\n" + "{\n" + " if [ $# -eq 0 ]; then\n" + " ensure_default_declaration\n" + " run_node_cli system installer-tui \"$declaration_file\" --system \"$current_system_name\" --store \"$default_store_dir\"\n" + " else\n" + " case \"$1\" in\n" + " --*)\n" + " ensure_default_declaration\n" + " run_node_cli system installer-tui \"$declaration_file\" --system \"$current_system_name\" --store \"$default_store_dir\" \"$@\"\n" + " ;;\n" + " *)\n" + " run_node_cli system installer-tui \"$@\"\n" + " ;;\n" + " esac\n" + " fi\n" + "}\n\n" "reconfigure_system()\n" "{\n" " build_output=$(mktemp /tmp/fruix-system-reconfigure.XXXXXX)\n" @@ -966,6 +1019,10 @@ " shift 2\n" " deploy_system \"$@\"\n" " ;;\n" + " installer-tui)\n" + " shift 2\n" + " installer_tui \"$@\"\n" + " ;;\n" " reconfigure)\n" " shift 2\n" " reconfigure_system \"$@\"\n" @@ -1285,7 +1342,7 @@ "cat \"$metadata_file\"\n"))) -(define* (operating-system-generated-files os #:key guile-store guile-extra-store shepherd-store) +(define* (operating-system-generated-files os #:key guile-store guile-extra-store shepherd-store guile-newt-store) (append `(("boot/loader.conf" . ,(render-loader-conf os)) ("etc/rc.conf" . ,(render-rc.conf os)) @@ -1304,7 +1361,7 @@ #:shepherd-store shepherd-store)) ("shepherd/init.scm" . ,(render-shepherd-config os)) ("usr/local/bin/fruix" - . ,(render-installed-system-fruix os guile-store guile-extra-store shepherd-store))) + . ,(render-installed-system-fruix os guile-store guile-extra-store shepherd-store guile-newt-store))) (bundled-fruix-node-files) (if (null? (operating-system-development-packages os)) '() diff --git a/scripts/fruix.scm b/scripts/fruix.scm index 54b2913..366b7e8 100644 --- a/scripts/fruix.scm +++ b/scripts/fruix.scm @@ -39,6 +39,7 @@ System options:\n\ --target PATH Install target for 'install' (raw image file or /dev/... device).\n\ --install-target-device DEVICE\n\ Target block device used by the booted 'installer' environment.\n\ + --self-test Use the Newt self-test path for 'installer-tui'.\n\ --rootfs DIR Rootfs target for 'rootfs'.\n\ --host HOST Remote host for 'deploy' (or use TARGET as first positional argument).\n\ --user USER Remote SSH user for 'deploy' (default: root).\n\ @@ -157,7 +158,8 @@ Common options:\n\ (deploy-user "root") (deploy-port "22") (identity-file #f) - (reboot? #f)) + (reboot? #f) + (self-test? #f)) (match args (() (let ((positional (reverse positional))) @@ -175,65 +177,68 @@ Common options:\n\ (deploy-user . ,deploy-user) (deploy-port . ,deploy-port) (identity-file . ,identity-file) - (reboot? . ,reboot?)))) + (reboot? . ,reboot?) + (self-test? . ,self-test?)))) (("--help") (usage 0)) (((? (lambda (arg) (string-prefix? "--system=" arg)) arg) . tail) - (loop tail positional (option-value arg "--system=") store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional (option-value arg "--system=") store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--system" value . tail) - (loop tail positional value store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional value store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--store=" arg)) arg) . tail) - (loop tail positional system-name (option-value arg "--store=") disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name (option-value arg "--store=") disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--store" value . tail) - (loop tail positional system-name value disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name value disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--disk-capacity=" arg)) arg) . tail) - (loop tail positional system-name store-dir (option-value arg "--disk-capacity=") root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir (option-value arg "--disk-capacity=") root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--disk-capacity" value . tail) - (loop tail positional system-name store-dir value root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir value root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--root-size=" arg)) arg) . tail) - (loop tail positional system-name store-dir disk-capacity (option-value arg "--root-size=") target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity (option-value arg "--root-size=") target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--root-size" value . tail) - (loop tail positional system-name store-dir disk-capacity value target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity value target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--target=" arg)) arg) . tail) - (loop tail positional system-name store-dir disk-capacity root-size (option-value arg "--target=") install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size (option-value arg "--target=") install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--target" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size value install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size value install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--install-target-device=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target - (option-value arg "--install-target-device=") rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (option-value arg "--install-target-device=") rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--install-target-device" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target value rootfs deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target value rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--rootfs=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target install-target-device - (option-value arg "--rootfs=") deploy-host deploy-user deploy-port identity-file reboot?)) + (option-value arg "--rootfs=") deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (("--rootfs" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device value deploy-host deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device value deploy-host deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--host=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs - (option-value arg "--host=") deploy-user deploy-port identity-file reboot?)) + (option-value arg "--host=") deploy-user deploy-port identity-file reboot? self-test?)) (("--host" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs value deploy-user deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs value deploy-user deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--user=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs - deploy-host (option-value arg "--user=") deploy-port identity-file reboot?)) + deploy-host (option-value arg "--user=") deploy-port identity-file reboot? self-test?)) (("--user" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host value deploy-port identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host value deploy-port identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--port=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs - deploy-host deploy-user (option-value arg "--port=") identity-file reboot?)) + deploy-host deploy-user (option-value arg "--port=") identity-file reboot? self-test?)) (("--port" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user value identity-file reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user value identity-file reboot? self-test?)) (((? (lambda (arg) (string-prefix? "--identity=" arg)) arg) . tail) (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs - deploy-host deploy-user deploy-port (option-value arg "--identity=") reboot?)) + deploy-host deploy-user deploy-port (option-value arg "--identity=") reboot? self-test?)) (("--identity" value . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port value reboot?)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port value reboot? self-test?)) (("--reboot" . tail) - (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file #t)) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file #t self-test?)) + (("--self-test" . tail) + (loop tail positional system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? #t)) (((? (lambda (arg) (string-prefix? "--" arg)) arg) . _) (error "unknown option" arg)) ((arg . tail) - (loop tail (cons arg positional) system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot?))))) + (loop tail (cons arg positional) system-name store-dir disk-capacity root-size target install-target-device rootfs deploy-host deploy-user deploy-port identity-file reboot? self-test?))))) (define (parse-source-arguments action rest) (let loop ((args rest) @@ -627,8 +632,10 @@ Common options:\n\ (os_file . ,os-file) (system_variable . ,resolved-symbol) (store_dir . ,store-dir) + (newt_mode . ,(assoc-ref result 'mode)) (newt_available . ,(assoc-ref result 'available?)) (newt_result . ,(assoc-ref result 'result)) + (newt_error . ,(or (assoc-ref result 'error) #f)) (missing_bindings . ,(assoc-ref result 'missing-bindings)) (step_count . ,(assoc-ref result 'step-count)) (step_ids . ,(assoc-ref result 'step-ids)) @@ -862,6 +869,7 @@ Common options:\n\ (deploy-port (assoc-ref parsed 'deploy-port)) (identity-file (assoc-ref parsed 'identity-file)) (reboot? (assoc-ref parsed 'reboot?)) + (self-test? (assoc-ref parsed 'self-test?)) (system-name (assoc-ref parsed 'system-name)) (requested-symbol (and system-name (string->symbol system-name)))) (unless (member action '("build" "deploy" "image" "installer" "installer-iso" "installer-tui" "install" "rootfs")) @@ -899,7 +907,8 @@ Common options:\n\ (shepherd-prefix (or (getenv "SHEPHERD_PREFIX") "/tmp/shepherd-freebsd-validate-install")) (guile-store-path (getenv "FRUIX_GUILE_STORE")) (guile-extra-store-path (getenv "FRUIX_GUILE_EXTRA_STORE")) - (shepherd-store-path (getenv "FRUIX_SHEPHERD_STORE"))) + (shepherd-store-path (getenv "FRUIX_SHEPHERD_STORE")) + (guile-newt-store-path (getenv "FRUIX_GUILE_NEWT_STORE"))) (unless deploy-source (error "deploy action requires a declaration file or system closure path")) (if (system-closure-path? deploy-source) @@ -925,6 +934,7 @@ Common options:\n\ #:guile-store-path guile-store-path #:guile-extra-store-path guile-extra-store-path #:shepherd-store-path shepherd-store-path + #:guile-newt-store-path guile-newt-store-path #:declaration-source declaration-source #:declaration-origin deploy-source #:declaration-system-symbol resolved-symbol))) @@ -947,6 +957,7 @@ Common options:\n\ (guile-store-path (getenv "FRUIX_GUILE_STORE")) (guile-extra-store-path (getenv "FRUIX_GUILE_EXTRA_STORE")) (shepherd-store-path (getenv "FRUIX_SHEPHERD_STORE")) + (guile-newt-store-path (getenv "FRUIX_GUILE_NEWT_STORE")) (declaration-source (read-file-string os-file))) (cond ((string=? action "build") @@ -960,6 +971,7 @@ Common options:\n\ #:guile-store-path guile-store-path #:guile-extra-store-path guile-extra-store-path #:shepherd-store-path shepherd-store-path + #:guile-newt-store-path guile-newt-store-path #:declaration-source declaration-source #:declaration-origin os-file #:declaration-system-symbol resolved-symbol))) @@ -1032,7 +1044,9 @@ Common options:\n\ #:target-device seed-target-device #:root-size root-size #:disk-capacity disk-capacity)) - (result (run-newt-installer state))) + (result (if self-test? + (run-newt-self-test) + (run-newt-installer state)))) (emit-installer-tui-metadata os-file resolved-symbol store-dir state result))) ((string=? action "install")