@@ -238,7 +238,8 @@ bash packaging/uninstall.sh --yes --purge-data
|
|||||||
|
|
||||||
Re-running the installer upgrades in place: it stops the old daemon, removes
|
Re-running the installer upgrades in place: it stops the old daemon, removes
|
||||||
the previous application and extension files, then copies the new tree.
|
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
|
[Migration notes](docs/MIGRATIONS.md) before upgrading or moving an
|
||||||
installation.
|
installation.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -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
|
directories next to the install prefix are removed first. Existing config and
|
||||||
data under `~/.config/jarvis`, `~/.local/share/jarvis`, and the model cache are
|
data under `~/.config/jarvis`, `~/.local/share/jarvis`, and the model cache are
|
||||||
preserved. If the service was running, the installer restarts it after the
|
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
|
`systemctl --user daemon-reload` only when you install the service file by
|
||||||
hand.
|
hand.
|
||||||
|
|
||||||
|
|||||||
+92
-14
@@ -7,11 +7,28 @@ EXT_DIR="${XDG_DATA_HOME:-${HOME}/.local/share}/gnome-shell/extensions/jarvis@qv
|
|||||||
CONFIG_DIR="${HOME}/.config/jarvis"
|
CONFIG_DIR="${HOME}/.config/jarvis"
|
||||||
CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/jarvis/models"
|
CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/jarvis/models"
|
||||||
APP_PARENT="$(dirname "${APP_DIR}")"
|
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=""
|
STAGING=""
|
||||||
EXT_TMP_DIR=""
|
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
|
trap cleanup_install EXIT
|
||||||
|
|
||||||
has_bundled_bare() {
|
has_bundled_bare() {
|
||||||
@@ -22,41 +39,82 @@ extract_tree() {
|
|||||||
local dest="$1"
|
local dest="$1"
|
||||||
mkdir -p "${dest}"
|
mkdir -p "${dest}"
|
||||||
if has_bundled_bare; then
|
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}"
|
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
|
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}"
|
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
|
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
|
PREVIOUSLY_ACTIVE=false
|
||||||
if command -v systemctl >/dev/null; then
|
if command -v systemctl >/dev/null; then
|
||||||
if systemctl --user is-active --quiet jarvisd.service 2>/dev/null; then
|
if systemctl --user is-active --quiet jarvisd.service 2>/dev/null; then
|
||||||
PREVIOUSLY_ACTIVE=true
|
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
|
fi
|
||||||
|
else
|
||||||
|
log "jarvisd.service was not running"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "systemctl not found; skipped service stop"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -e "${APP_DIR}" || -e "${EXT_DIR}" ]]; then
|
if [[ -e "${APP_DIR}" ]]; then
|
||||||
echo "Cleaning the previous JARVIS-QVAC install so this upgrade is a clean replacement."
|
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
|
fi
|
||||||
|
|
||||||
if command -v gnome-extensions >/dev/null; then
|
if command -v gnome-extensions >/dev/null; then
|
||||||
gnome-extensions disable [email protected] >/dev/null 2>&1 || true
|
if gnome-extensions disable [email protected] >/dev/null 2>&1; then
|
||||||
gnome-extensions uninstall [email protected] >/dev/null 2>&1 || true
|
log "disabled GNOME extension [email protected]"
|
||||||
|
else
|
||||||
|
log "GNOME extension [email protected] was not enabled or could not be disabled"
|
||||||
|
fi
|
||||||
|
if gnome-extensions uninstall [email protected] >/dev/null 2>&1; then
|
||||||
|
log "uninstalled GNOME extension [email protected]"
|
||||||
|
else
|
||||||
|
log "GNOME extension [email protected] 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
|
fi
|
||||||
rm -rf "${EXT_DIR}"
|
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for leftover in "${APP_PARENT}"/jarvis-qvac.staging.*; do
|
for leftover in "${APP_PARENT}"/jarvis-qvac.staging.*; do
|
||||||
|
log "removing leftover staging directory ${leftover}"
|
||||||
rm -rf "${leftover}"
|
rm -rf "${leftover}"
|
||||||
done
|
done
|
||||||
shopt -u nullglob
|
shopt -u nullglob
|
||||||
|
|
||||||
STAGING="$(mktemp -d "${APP_PARENT}/jarvis-qvac.staging.XXXXXX")"
|
STAGING="$(mktemp -d "${APP_PARENT}/jarvis-qvac.staging.XXXXXX")"
|
||||||
extract_tree "${STAGING}"
|
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}"
|
mv "${STAGING}" "${APP_DIR}"
|
||||||
STAGING=""
|
STAGING=""
|
||||||
|
log "application tree replaced at ${APP_DIR}"
|
||||||
|
|
||||||
case "$(uname -m)" in
|
case "$(uname -m)" in
|
||||||
x86_64|amd64) BARE_BIN="${APP_DIR}/node_modules/bare-runtime-linux-x64/bin/bare" ;;
|
x86_64|amd64) BARE_BIN="${APP_DIR}/node_modules/bare-runtime-linux-x64/bin/bare" ;;
|
||||||
@@ -65,40 +123,58 @@ case "$(uname -m)" in
|
|||||||
esac
|
esac
|
||||||
if [[ ! -x "${BARE_BIN}" ]]; then BARE_BIN="$(command -v bare || true)"; fi
|
if [[ ! -x "${BARE_BIN}" ]]; then BARE_BIN="$(command -v bare || true)"; fi
|
||||||
if [[ -z "${BARE_BIN}" || ! -x "${BARE_BIN}" ]]; then
|
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
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
chmod 755 "${BARE_BIN}"
|
chmod 755 "${BARE_BIN}"
|
||||||
|
log "using Bare runtime ${BARE_BIN}"
|
||||||
EXT_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/jarvis-extension.XXXXXX")"
|
EXT_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/jarvis-extension.XXXXXX")"
|
||||||
EXT_ZIP="${EXT_TMP_DIR}/jarvis-extension.zip"
|
EXT_ZIP="${EXT_TMP_DIR}/jarvis-extension.zip"
|
||||||
mkdir -p "${EXT_DIR}"
|
mkdir -p "${EXT_DIR}"
|
||||||
( cd "${ROOT_DIR}/apps/gnome-extension/[email protected]" && zip -q -r "${EXT_ZIP}" . )
|
( cd "${ROOT_DIR}/apps/gnome-extension/[email protected]" && zip -q -r "${EXT_ZIP}" . )
|
||||||
if command -v gnome-extensions >/dev/null; then
|
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
|
echo "GNOME extension registration failed; installing the files directly." >&2
|
||||||
cp -a "${ROOT_DIR}/apps/gnome-extension/[email protected]/." "${EXT_DIR}/"
|
cp -a "${ROOT_DIR}/apps/gnome-extension/[email protected]/." "${EXT_DIR}/"
|
||||||
|
log "copied GNOME extension files to ${EXT_DIR}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
cp -a "${ROOT_DIR}/apps/gnome-extension/[email protected]/." "${EXT_DIR}/"
|
cp -a "${ROOT_DIR}/apps/gnome-extension/[email protected]/." "${EXT_DIR}/"
|
||||||
|
log "copied GNOME extension files to ${EXT_DIR}"
|
||||||
fi
|
fi
|
||||||
if command -v glib-compile-schemas >/dev/null && [[ -d "${EXT_DIR}/schemas" ]]; then
|
if command -v glib-compile-schemas >/dev/null && [[ -d "${EXT_DIR}/schemas" ]]; then
|
||||||
glib-compile-schemas "${EXT_DIR}/schemas" >/dev/null
|
glib-compile-schemas "${EXT_DIR}/schemas" >/dev/null
|
||||||
|
log "compiled GSettings schemas in ${EXT_DIR}/schemas"
|
||||||
fi
|
fi
|
||||||
sed "s#__JARVIS_BARE__#${BARE_BIN}#" "${ROOT_DIR}/packaging/jarvisd.service" > "${HOME}/.config/systemd/user/jarvisd.service"
|
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
|
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"
|
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
|
fi
|
||||||
restart_user_service() {
|
restart_user_service() {
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
|
log "reloaded user systemd units"
|
||||||
if [[ "${1:-}" == "enable" ]]; then
|
if [[ "${1:-}" == "enable" ]]; then
|
||||||
systemctl --user enable jarvisd.service
|
systemctl --user enable jarvisd.service
|
||||||
|
log "enabled jarvisd.service"
|
||||||
fi
|
fi
|
||||||
systemctl --user restart jarvisd.service
|
systemctl --user restart jarvisd.service
|
||||||
|
log "restarted jarvisd.service"
|
||||||
}
|
}
|
||||||
if [[ "${1:-}" == "--enable" ]]; then
|
if [[ "${1:-}" == "--enable" ]]; then
|
||||||
restart_user_service enable
|
restart_user_service enable
|
||||||
if command -v gnome-extensions >/dev/null && gnome-extensions enable [email protected] >/dev/null 2>&1; then
|
if command -v gnome-extensions >/dev/null && gnome-extensions enable [email protected] >/dev/null 2>&1; then
|
||||||
echo "GNOME extension enabled."
|
log "enabled GNOME extension [email protected]"
|
||||||
elif command -v gsettings >/dev/null && gsettings writable org.gnome.shell enabled-extensions >/dev/null 2>&1; then
|
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
|
# A running GNOME Shell keeps its extension catalogue until the next
|
||||||
# session. Persist the enabled state so the extension starts on login.
|
# session. Persist the enabled state so the extension starts on login.
|
||||||
@@ -110,14 +186,16 @@ if [[ "${1:-}" == "--enable" ]]; then
|
|||||||
ENABLED_EXTENSIONS="${ENABLED_EXTENSIONS%]}, '[email protected]']"
|
ENABLED_EXTENSIONS="${ENABLED_EXTENSIONS%]}, '[email protected]']"
|
||||||
fi
|
fi
|
||||||
gsettings set org.gnome.shell enabled-extensions "${ENABLED_EXTENSIONS}"
|
gsettings set org.gnome.shell enabled-extensions "${ENABLED_EXTENSIONS}"
|
||||||
|
log "persisted [email protected] in org.gnome.shell enabled-extensions"
|
||||||
fi
|
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
|
else
|
||||||
echo "GNOME Shell has not rescanned extensions; log out and back in, then run: gnome-extensions enable [email protected]"
|
log "GNOME Shell has not rescanned extensions; log out and back in, then run: gnome-extensions enable [email protected]"
|
||||||
fi
|
fi
|
||||||
elif [[ "${PREVIOUSLY_ACTIVE}" == true ]]; then
|
elif [[ "${PREVIOUSLY_ACTIVE}" == true ]]; then
|
||||||
restart_user_service
|
restart_user_service
|
||||||
echo "Restarted jarvisd.service with the upgraded files."
|
log "restarted jarvisd.service with the upgraded files"
|
||||||
fi
|
fi
|
||||||
|
log "install complete; log file ${LOG_FILE}"
|
||||||
echo "Installed JARVIS-QVAC to ${APP_DIR}"
|
echo "Installed JARVIS-QVAC to ${APP_DIR}"
|
||||||
echo "Run: ${APP_DIR}/packaging/first-run.sh"
|
echo "Run: ${APP_DIR}/packaging/first-run.sh"
|
||||||
|
|||||||
+14
-1
@@ -66,16 +66,22 @@ exit 0
|
|||||||
echo "gnome-extensions $*" >> '${log}'
|
echo "gnome-extensions $*" >> '${log}'
|
||||||
if [ "$1" = install ]; then exit 1; fi
|
if [ "$1" = install ]; then exit 1; fi
|
||||||
exit 0
|
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, 'systemctl'), 0o755);
|
||||||
await chmod(path.join(bin, 'gnome-extensions'), 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,
|
...process.env,
|
||||||
HOME: home,
|
HOME: home,
|
||||||
PATH: `${bin}:${process.env.PATH}`,
|
PATH: `${bin}:${process.env.PATH}`,
|
||||||
XDG_DATA_HOME: path.join(home, '.local/share'),
|
XDG_DATA_HOME: path.join(home, '.local/share'),
|
||||||
XDG_CACHE_HOME: path.join(home, '.cache'),
|
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);
|
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, /systemctl --user stop jarvisd\.service/);
|
||||||
assert.match(commands, /gnome-extensions uninstall jarvis@qvac\.local/);
|
assert.match(commands, /gnome-extensions uninstall jarvis@qvac\.local/);
|
||||||
assert.match(commands, /systemctl --user restart jarvisd\.service/);
|
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 {
|
} finally {
|
||||||
await rm(work, { recursive: true, force: true });
|
await rm(work, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user