From 324f0d5e3a668ec833d9c83bd1e6519e1431d8b6 Mon Sep 17 00:00:00 2001 From: Raven Scott Date: Fri, 11 Sep 2026 21:34:34 -0400 Subject: [PATCH] Update Installer --- README.md | 3 +- docs/MIGRATIONS.md | 4 +- packaging/install.sh | 106 +++++++++++++++++++++++++++++++++++++------ test/install.test.js | 15 +++++- 4 files changed, 111 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1be942e..d878bed 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,8 @@ bash packaging/uninstall.sh --yes --purge-data Re-running the installer upgrades in place: it stops the old daemon, removes the previous application and extension files, then copies the new tree. -Config, memory, and model cache are kept. Read +Config, memory, and model cache are kept. Those steps are written to +`~/.local/state/jarvis/install.log`. Read [Migration notes](docs/MIGRATIONS.md) before upgrading or moving an installation. diff --git a/docs/MIGRATIONS.md b/docs/MIGRATIONS.md index 72f0031..7c78347 100644 --- a/docs/MIGRATIONS.md +++ b/docs/MIGRATIONS.md @@ -12,7 +12,9 @@ leftover files from older versions cannot mix with the new tree. Failed staging directories next to the install prefix are removed first. Existing config and data under `~/.config/jarvis`, `~/.local/share/jarvis`, and the model cache are preserved. If the service was running, the installer restarts it after the -replacement; `--enable` also enables the unit. Run +replacement; `--enable` also enables the unit. Each of those steps is appended +to `~/.local/state/jarvis/install.log` (or `$XDG_STATE_HOME/jarvis/install.log`) +and to the system log as tag `jarvis-install`. Run `systemctl --user daemon-reload` only when you install the service file by hand. diff --git a/packaging/install.sh b/packaging/install.sh index 36d97ce..1c5240e 100755 --- a/packaging/install.sh +++ b/packaging/install.sh @@ -7,11 +7,28 @@ EXT_DIR="${XDG_DATA_HOME:-${HOME}/.local/share}/gnome-shell/extensions/jarvis@qv CONFIG_DIR="${HOME}/.config/jarvis" CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/jarvis/models" APP_PARENT="$(dirname "${APP_DIR}")" -mkdir -p "${APP_PARENT}" "${CONFIG_DIR}" "${HOME}/.config/systemd/user" "${CACHE_DIR}" +LOG_DIR="${XDG_STATE_HOME:-${HOME}/.local/state}/jarvis" +LOG_FILE="${LOG_DIR}/install.log" +mkdir -p "${APP_PARENT}" "${CONFIG_DIR}" "${HOME}/.config/systemd/user" "${CACHE_DIR}" "${LOG_DIR}" + +log() { + local line + line="$(date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S%z') jarvis-install: $*" + printf '%s\n' "${line}" | tee -a "${LOG_FILE}" + if command -v logger >/dev/null; then + logger --tag jarvis-install -- "$*" 2>/dev/null || logger -t jarvis-install -- "$*" 2>/dev/null || true + fi +} STAGING="" EXT_TMP_DIR="" -cleanup_install() { rm -rf "${STAGING}" "${EXT_TMP_DIR}"; } +cleanup_install() { + if [[ -n "${STAGING}" && -e "${STAGING}" ]]; then + log "removing unfinished staging directory ${STAGING}" + rm -rf "${STAGING}" + fi + rm -rf "${EXT_TMP_DIR}" +} trap cleanup_install EXIT has_bundled_bare() { @@ -22,41 +39,82 @@ extract_tree() { local dest="$1" mkdir -p "${dest}" if has_bundled_bare; then + log "staging bundled Bare tree from ${ROOT_DIR} into ${dest}" tar --exclude='.git' --exclude='./.agents' --exclude='./.codex' --exclude='./dist' --exclude='./vendor/agent-harness/node_modules' --exclude='*/__pycache__' --exclude='*.pyc' -cf - -C "${ROOT_DIR}" . | tar -xf - -C "${dest}" else + log "staging source tree from ${ROOT_DIR} into ${dest} (excluding node_modules)" tar --exclude='.git' --exclude='./.agents' --exclude='./.codex' --exclude='./dist' --exclude='./node_modules' --exclude='*/node_modules' --exclude='*/__pycache__' --exclude='*.pyc' -cf - -C "${ROOT_DIR}" . | tar -xf - -C "${dest}" fi } +log "starting install from ${ROOT_DIR}" +log "application directory ${APP_DIR}; extension ${EXT_DIR}" +log "preserving config ${CONFIG_DIR}, cache ${CACHE_DIR}, and user data under ${HOME}/.local/share/jarvis" + PREVIOUSLY_ACTIVE=false if command -v systemctl >/dev/null; then if systemctl --user is-active --quiet jarvisd.service 2>/dev/null; then PREVIOUSLY_ACTIVE=true - systemctl --user stop jarvisd.service || true + log "stopping running jarvisd.service before replacing files" + if systemctl --user stop jarvisd.service; then + log "stopped jarvisd.service" + else + log "warning: could not stop jarvisd.service; continuing with replacement" + fi + else + log "jarvisd.service was not running" fi +else + log "systemctl not found; skipped service stop" fi -if [[ -e "${APP_DIR}" || -e "${EXT_DIR}" ]]; then - echo "Cleaning the previous JARVIS-QVAC install so this upgrade is a clean replacement." +if [[ -e "${APP_DIR}" ]]; then + log "previous application tree found at ${APP_DIR}" +else + log "no previous application tree at ${APP_DIR}" +fi +if [[ -e "${EXT_DIR}" ]]; then + log "previous GNOME extension found at ${EXT_DIR}" +else + log "no previous GNOME extension at ${EXT_DIR}" fi if command -v gnome-extensions >/dev/null; then - gnome-extensions disable jarvis@qvac.local >/dev/null 2>&1 || true - gnome-extensions uninstall jarvis@qvac.local >/dev/null 2>&1 || true + if gnome-extensions disable jarvis@qvac.local >/dev/null 2>&1; then + log "disabled GNOME extension jarvis@qvac.local" + else + log "GNOME extension jarvis@qvac.local was not enabled or could not be disabled" + fi + if gnome-extensions uninstall jarvis@qvac.local >/dev/null 2>&1; then + log "uninstalled GNOME extension jarvis@qvac.local" + else + log "GNOME extension jarvis@qvac.local was not registered or could not be uninstalled" + fi +else + log "gnome-extensions not found; removing extension files directly" +fi +if [[ -e "${EXT_DIR}" ]]; then + log "removing leftover extension files at ${EXT_DIR}" + rm -rf "${EXT_DIR}" fi -rm -rf "${EXT_DIR}" shopt -s nullglob for leftover in "${APP_PARENT}"/jarvis-qvac.staging.*; do + log "removing leftover staging directory ${leftover}" rm -rf "${leftover}" done shopt -u nullglob STAGING="$(mktemp -d "${APP_PARENT}/jarvis-qvac.staging.XXXXXX")" extract_tree "${STAGING}" -rm -rf "${APP_DIR}" +if [[ -e "${APP_DIR}" ]]; then + log "removing previous application tree ${APP_DIR}" + rm -rf "${APP_DIR}" +fi +log "moving staged tree ${STAGING} into ${APP_DIR}" mv "${STAGING}" "${APP_DIR}" STAGING="" +log "application tree replaced at ${APP_DIR}" case "$(uname -m)" in x86_64|amd64) BARE_BIN="${APP_DIR}/node_modules/bare-runtime-linux-x64/bin/bare" ;; @@ -65,40 +123,58 @@ case "$(uname -m)" in esac if [[ ! -x "${BARE_BIN}" ]]; then BARE_BIN="$(command -v bare || true)"; fi if [[ -z "${BARE_BIN}" || ! -x "${BARE_BIN}" ]]; then + log "error: no Bare runtime for $(uname -m) in the installed bundle" echo "The installed bundle does not contain a Bare runtime for $(uname -m). Install the official rolling bundle or build it with npm run package:bare." >&2 exit 1 fi chmod 755 "${BARE_BIN}" +log "using Bare runtime ${BARE_BIN}" EXT_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/jarvis-extension.XXXXXX")" EXT_ZIP="${EXT_TMP_DIR}/jarvis-extension.zip" mkdir -p "${EXT_DIR}" ( cd "${ROOT_DIR}/apps/gnome-extension/jarvis@qvac.local" && zip -q -r "${EXT_ZIP}" . ) if command -v gnome-extensions >/dev/null; then - if ! gnome-extensions install --force "${EXT_ZIP}"; then + if gnome-extensions install --force "${EXT_ZIP}"; then + log "registered GNOME extension from ${EXT_ZIP}" + else + log "warning: GNOME extension registration failed; copying files to ${EXT_DIR}" echo "GNOME extension registration failed; installing the files directly." >&2 cp -a "${ROOT_DIR}/apps/gnome-extension/jarvis@qvac.local/." "${EXT_DIR}/" + log "copied GNOME extension files to ${EXT_DIR}" fi else cp -a "${ROOT_DIR}/apps/gnome-extension/jarvis@qvac.local/." "${EXT_DIR}/" + log "copied GNOME extension files to ${EXT_DIR}" fi if command -v glib-compile-schemas >/dev/null && [[ -d "${EXT_DIR}/schemas" ]]; then glib-compile-schemas "${EXT_DIR}/schemas" >/dev/null + log "compiled GSettings schemas in ${EXT_DIR}/schemas" fi sed "s#__JARVIS_BARE__#${BARE_BIN}#" "${ROOT_DIR}/packaging/jarvisd.service" > "${HOME}/.config/systemd/user/jarvisd.service" +log "wrote ${HOME}/.config/systemd/user/jarvisd.service" +if [[ -f "${CONFIG_DIR}/config.json" ]]; then + log "kept existing ${CONFIG_DIR}/config.json" +fi if [[ ! -f "${CONFIG_DIR}/qvac.config.json" ]]; then sed "s#__JARVIS_CACHE__#${CACHE_DIR}#g" "${ROOT_DIR}/packaging/qvac.config.template.json" > "${CONFIG_DIR}/qvac.config.json" + log "created ${CONFIG_DIR}/qvac.config.json" +else + log "kept existing ${CONFIG_DIR}/qvac.config.json" fi restart_user_service() { systemctl --user daemon-reload + log "reloaded user systemd units" if [[ "${1:-}" == "enable" ]]; then systemctl --user enable jarvisd.service + log "enabled jarvisd.service" fi systemctl --user restart jarvisd.service + log "restarted jarvisd.service" } if [[ "${1:-}" == "--enable" ]]; then restart_user_service enable if command -v gnome-extensions >/dev/null && gnome-extensions enable jarvis@qvac.local >/dev/null 2>&1; then - echo "GNOME extension enabled." + log "enabled GNOME extension jarvis@qvac.local" elif command -v gsettings >/dev/null && gsettings writable org.gnome.shell enabled-extensions >/dev/null 2>&1; then # A running GNOME Shell keeps its extension catalogue until the next # session. Persist the enabled state so the extension starts on login. @@ -110,14 +186,16 @@ if [[ "${1:-}" == "--enable" ]]; then ENABLED_EXTENSIONS="${ENABLED_EXTENSIONS%]}, 'jarvis@qvac.local']" fi gsettings set org.gnome.shell enabled-extensions "${ENABLED_EXTENSIONS}" + log "persisted jarvis@qvac.local in org.gnome.shell enabled-extensions" fi - echo "GNOME Shell will enable Jarvis after the next login (the current Shell session has not rescanned extensions)." + log "GNOME Shell will enable Jarvis after the next login (the current Shell session has not rescanned extensions)" else - echo "GNOME Shell has not rescanned extensions; log out and back in, then run: gnome-extensions enable jarvis@qvac.local" + log "GNOME Shell has not rescanned extensions; log out and back in, then run: gnome-extensions enable jarvis@qvac.local" fi elif [[ "${PREVIOUSLY_ACTIVE}" == true ]]; then restart_user_service - echo "Restarted jarvisd.service with the upgraded files." + log "restarted jarvisd.service with the upgraded files" fi +log "install complete; log file ${LOG_FILE}" echo "Installed JARVIS-QVAC to ${APP_DIR}" echo "Run: ${APP_DIR}/packaging/first-run.sh" diff --git a/test/install.test.js b/test/install.test.js index 0df258a..f3410df 100644 --- a/test/install.test.js +++ b/test/install.test.js @@ -66,16 +66,22 @@ exit 0 echo "gnome-extensions $*" >> '${log}' if [ "$1" = install ]; then exit 1; fi exit 0 +`); + await writeFile(path.join(bin, 'logger'), `#!/bin/sh +echo "logger $*" >> '${log}' +exit 0 `); await chmod(path.join(bin, 'systemctl'), 0o755); await chmod(path.join(bin, 'gnome-extensions'), 0o755); + await chmod(path.join(bin, 'logger'), 0o755); - await run('bash', [path.join(root, 'packaging/install.sh'), '--enable'], { + const result = await run('bash', [path.join(root, 'packaging/install.sh'), '--enable'], { ...process.env, HOME: home, PATH: `${bin}:${process.env.PATH}`, XDG_DATA_HOME: path.join(home, '.local/share'), XDG_CACHE_HOME: path.join(home, '.cache'), + XDG_STATE_HOME: path.join(home, '.local/state'), }); assert.equal(existsSync(path.join(appDir, 'stale-old-version.js')), false); @@ -92,6 +98,13 @@ exit 0 assert.match(commands, /systemctl --user stop jarvisd\.service/); assert.match(commands, /gnome-extensions uninstall jarvis@qvac\.local/); assert.match(commands, /systemctl --user restart jarvisd\.service/); + const installLog = await readFile(path.join(home, '.local/state/jarvis/install.log'), 'utf8'); + assert.match(installLog, /stopping running jarvisd\.service/); + assert.match(installLog, /removing leftover staging directory/); + assert.match(installLog, /removing previous application tree/); + assert.match(installLog, /kept existing .*config\.json/); + assert.match(installLog, /install complete; log file/); + assert.match(result.stdout, /jarvis-install: stopping running jarvisd\.service/); } finally { await rm(work, { recursive: true, force: true }); }