Add curl-pipe installer, uninstaller, and contributor bootstrap
End-user installation collapses to a single command: curl -fsSL https://gitea.cahlen.com/nokeo08/Move/raw/branch/master/install.sh | sh Changes: - install.sh rewritten as a POSIX sh, curl-pipeable end-user installer. Honors XDG_DATA_HOME and XDG_BIN_HOME (de facto). Idempotent via a version-marker file at $INSTALL_DIR/.installed-version; MOVE_FORCE=1 overrides. Hard-fails if Bun is missing (no auto-install). Includes a safety guard refusing rm -rf on too-broad install dirs. - uninstall.sh added; same curl-pipe pattern, shared XDG path resolution, leaves Bun alone. - dev-setup.sh added (= the previous install.sh content, retitled for contributors and pointing at bun run start / bun link / install.sh). - README updated: curl one-liner Install section, XDG behavior tables, new Uninstall section, new 'For contributors' section, Files table rows for all three scripts.
This commit is contained in:
+164
-28
@@ -1,41 +1,177 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
# install.sh - bootstrap the Teams Status Keeper project.
|
||||
# install.sh - End-user installer for the `move` CLI.
|
||||
#
|
||||
# Verifies Bun is installed, then runs `bun install` to fetch dependencies
|
||||
# (notably `@nut-tree-fork/nut-js`, which ships prebuilt native binaries
|
||||
# for darwin-arm64/x64, linux, and windows).
|
||||
# Curl-pipe ready:
|
||||
#
|
||||
# This script is idempotent: re-running it just re-resolves the dependency
|
||||
# tree against the existing `bun.lock`.
|
||||
# curl -fsSL https://gitea.cahlen.com/nokeo08/Move/raw/branch/master/install.sh | sh
|
||||
#
|
||||
# What it does:
|
||||
# 1. Detect platform; bail on anything @nut-tree-fork/nut-js doesn't ship.
|
||||
# 2. Require Bun; fail with a clear hint if missing (no auto-install).
|
||||
# 3. Resolve XDG-compliant install paths.
|
||||
# 4. Idempotence check via a version marker file.
|
||||
# 5. Download the source tarball from Gitea, extract under the install dir.
|
||||
# 6. `bun install --production` (skips devDependencies).
|
||||
# 7. Drop a small wrapper script as `move` on the user's bin dir.
|
||||
# 8. Verify PATH, surface macOS Accessibility hint, print final status.
|
||||
#
|
||||
# Env vars (all optional):
|
||||
# MOVE_VERSION Branch or tag to install. Default: master.
|
||||
# MOVE_FORCE Set to 1 to reinstall even if the version marker matches.
|
||||
# XDG_DATA_HOME Source install root (default $HOME/.local/share).
|
||||
# Final source location is $XDG_DATA_HOME/move.
|
||||
# XDG_BIN_HOME Wrapper install root (default $HOME/.local/bin).
|
||||
# Final binary location is $XDG_BIN_HOME/move.
|
||||
#
|
||||
# POSIX sh; no bashisms.
|
||||
|
||||
# Fail fast on any error, unset variable, or failed pipe stage.
|
||||
set -euo pipefail
|
||||
set -eu
|
||||
|
||||
# Always operate relative to the script's own directory so the install works
|
||||
# regardless of the caller's CWD.
|
||||
cd "$(dirname "$0")"
|
||||
REPO_OWNER="nokeo08"
|
||||
REPO_NAME="Move"
|
||||
GITEA_HOST="gitea.cahlen.com"
|
||||
|
||||
MOVE_VERSION="${MOVE_VERSION:-master}"
|
||||
MOVE_FORCE="${MOVE_FORCE:-0}"
|
||||
|
||||
INSTALL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/move"
|
||||
BIN_DIR="${XDG_BIN_HOME:-$HOME/.local/bin}"
|
||||
|
||||
die() {
|
||||
printf 'Error: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Refuse to operate on a directory that points somewhere catastrophic.
|
||||
# `INSTALL_DIR` derives from XDG_DATA_HOME, a broadly-scoped env var the
|
||||
# user could conceivably set to anything; the install path always
|
||||
# culminates in `.../move`, but a malformed XDG_DATA_HOME could still
|
||||
# resolve to something like '/move' which we don't want to `rm -rf`.
|
||||
assert_safe_install_dir() {
|
||||
case "$INSTALL_DIR" in
|
||||
'' | '/' | "$HOME" | "$HOME/" | '/move')
|
||||
die "refusing to operate on INSTALL_DIR='$INSTALL_DIR' (too broad)"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# --- Prerequisite tools ------------------------------------------------------
|
||||
|
||||
for tool in curl tar mktemp; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
die "$tool is required (not found in PATH)"
|
||||
fi
|
||||
done
|
||||
|
||||
# --- Platform detection ------------------------------------------------------
|
||||
|
||||
OS=$(uname -s)
|
||||
ARCH=$(uname -m)
|
||||
|
||||
case "$OS" in
|
||||
Darwin|Linux) ;;
|
||||
*) die "unsupported OS '$OS' (move supports macOS and Linux)" ;;
|
||||
esac
|
||||
|
||||
case "$ARCH" in
|
||||
arm64|aarch64|x86_64|amd64) ;;
|
||||
*) die "unsupported architecture '$ARCH'" ;;
|
||||
esac
|
||||
|
||||
# --- Bun check (hard fail; no auto-install) ----------------------------------
|
||||
|
||||
echo "==> Checking for Bun..."
|
||||
if ! command -v bun >/dev/null 2>&1; then
|
||||
# Hard error rather than auto-install: keep the script's behavior
|
||||
# predictable and let the user pick their own install method.
|
||||
echo "Error: bun is not installed." >&2
|
||||
echo " Install it from https://bun.sh (e.g. 'brew install oven-sh/bun/bun') and re-run." >&2
|
||||
cat >&2 <<EOF
|
||||
Error: bun is not installed.
|
||||
Install it from https://bun.sh
|
||||
(e.g. 'curl -fsSL https://bun.sh/install | bash')
|
||||
then re-run this installer.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
echo " bun $(bun --version)"
|
||||
|
||||
echo "==> Installing dependencies..."
|
||||
bun install
|
||||
BUN_VERSION=$(bun --version)
|
||||
printf '==> Using bun %s\n' "$BUN_VERSION"
|
||||
|
||||
echo
|
||||
echo "Done. Run with: bun run start"
|
||||
# --- Idempotence check -------------------------------------------------------
|
||||
|
||||
# macOS gates synthetic mouse events behind the Accessibility permission.
|
||||
# Without this hint, the first run silently fails to move the cursor and
|
||||
# the user has no obvious next step.
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
echo "Note: macOS will prompt for Accessibility permission on first mouse move."
|
||||
echo " Grant it under System Settings > Privacy & Security > Accessibility."
|
||||
assert_safe_install_dir
|
||||
|
||||
if [ "$MOVE_FORCE" != "1" ] && [ -f "$INSTALL_DIR/.installed-version" ]; then
|
||||
CURRENT=$(cat "$INSTALL_DIR/.installed-version" 2>/dev/null || printf '')
|
||||
if [ "$CURRENT" = "$MOVE_VERSION" ]; then
|
||||
printf 'move %s is already installed at %s/move.\n' "$MOVE_VERSION" "$BIN_DIR"
|
||||
printf 'Set MOVE_FORCE=1 to reinstall, or set MOVE_VERSION to a different ref.\n'
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Clean install dir -------------------------------------------------------
|
||||
|
||||
mkdir -p "$BIN_DIR"
|
||||
rm -rf "$INSTALL_DIR"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# --- Download source ---------------------------------------------------------
|
||||
|
||||
TARBALL_URL="https://$GITEA_HOST/$REPO_OWNER/$REPO_NAME/archive/$MOVE_VERSION.tar.gz"
|
||||
TARBALL_TMP=$(mktemp) || die "could not create temp file"
|
||||
|
||||
cleanup() {
|
||||
rm -f "$TARBALL_TMP"
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
printf '==> Downloading %s\n' "$TARBALL_URL"
|
||||
if ! curl -fsSL "$TARBALL_URL" -o "$TARBALL_TMP"; then
|
||||
die "could not download $TARBALL_URL (check MOVE_VERSION='$MOVE_VERSION' and network)"
|
||||
fi
|
||||
|
||||
printf '==> Extracting source to %s\n' "$INSTALL_DIR"
|
||||
if ! tar -xzf "$TARBALL_TMP" -C "$INSTALL_DIR" --strip-components=1; then
|
||||
die "could not extract tarball from $TARBALL_URL"
|
||||
fi
|
||||
|
||||
# --- Install runtime deps ----------------------------------------------------
|
||||
|
||||
printf '==> Installing runtime dependencies (bun install --production)\n'
|
||||
(cd "$INSTALL_DIR" && bun install --production)
|
||||
|
||||
# --- Drop the wrapper --------------------------------------------------------
|
||||
|
||||
WRAPPER="$BIN_DIR/move"
|
||||
printf '==> Writing wrapper to %s\n' "$WRAPPER"
|
||||
cat > "$WRAPPER" <<EOF
|
||||
#!/usr/bin/env sh
|
||||
exec bun "$INSTALL_DIR/src/move.ts" "\$@"
|
||||
EOF
|
||||
chmod +x "$WRAPPER"
|
||||
|
||||
# --- Write version marker ----------------------------------------------------
|
||||
|
||||
printf '%s\n' "$MOVE_VERSION" > "$INSTALL_DIR/.installed-version"
|
||||
|
||||
# --- PATH sanity check -------------------------------------------------------
|
||||
|
||||
case ":$PATH:" in
|
||||
*":$BIN_DIR:"*) BIN_ON_PATH=1 ;;
|
||||
*) BIN_ON_PATH=0 ;;
|
||||
esac
|
||||
|
||||
if [ "$BIN_ON_PATH" = "0" ]; then
|
||||
printf '\nNote: %s is not on your PATH. Add this to your shell rc:\n' "$BIN_DIR"
|
||||
printf ' export PATH="%s:$PATH"\n' "$BIN_DIR"
|
||||
fi
|
||||
|
||||
# --- macOS Accessibility hint ------------------------------------------------
|
||||
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
printf '\nNote: macOS will prompt for Accessibility permission on first mouse move.\n'
|
||||
printf ' Grant it under System Settings > Privacy & Security > Accessibility.\n'
|
||||
fi
|
||||
|
||||
# --- Final message -----------------------------------------------------------
|
||||
|
||||
printf '\nInstalled move %s at %s.\n' "$MOVE_VERSION" "$WRAPPER"
|
||||
printf "Run 'move --help' to get started.\n"
|
||||
|
||||
Reference in New Issue
Block a user