install-cli.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/sh
# Install only the cross-platform firecrab client into a user-writable directory.
set -eu
RELEASE_BASE=${FIRECRAB_RELEASE_BASE:-https://github.com/SteelCrab/firecrab/releases}
VERSION=${FIRECRAB_VERSION:-latest}
INSTALL_DIR=${FIRECRAB_INSTALL_DIR:-}
CHECK=0
PRINT_ASSET=0
PRINT_URL=0
UNINSTALL=0
PURGE=0
usage() {
cat <<'EOF'
Usage: install-cli.sh [options]
Install the firecrab client without root, Cargo, or the Linux host services.
Options:
--version VER Release tag such as v0.4.1 (default: latest)
--install-dir DIR Destination directory (default: ~/.local/bin)
--uninstall Remove the standalone firecrab client
--purge With --uninstall, also remove saved host configuration
--check Print the selected asset and destination without changes
--print-asset Print the selected release asset name
--print-url Print the selected release asset URL
-h, --help Show this help
Environment:
FIRECRAB_RELEASE_BASE Alternate release root for mirrors or tests
FIRECRAB_TEST_ALLOW_FILE_URL=1
Permit file:// release roots in tests only
FIRECRAB_VERSION Default release tag
FIRECRAB_INSTALL_DIR Default destination directory
FIRECRAB_CONFIG_DIR Configuration directory (default: ~/.firecrab)
FIRECRAB_CLI_LIBC Linux libc override: gnu, glibc, or musl
EOF
}
while [ "$#" -gt 0 ]; do
case "$1" in
--version)
[ "$#" -ge 2 ] || { printf '%s\n' '--version needs a value' >&2; exit 2; }
VERSION=$2
shift 2
;;
--install-dir)
[ "$#" -ge 2 ] || { printf '%s\n' '--install-dir needs a value' >&2; exit 2; }
INSTALL_DIR=$2
shift 2
;;
--uninstall) UNINSTALL=1; shift ;;
--purge) PURGE=1; shift ;;
--check) CHECK=1; shift ;;
--print-asset) PRINT_ASSET=1; shift ;;
--print-url) PRINT_URL=1; shift ;;
-h|--help) usage; exit 0 ;;
*) printf 'unknown option: %s\n' "$1" >&2; usage >&2; exit 2 ;;
esac
done
[ "$PURGE" -eq 0 ] || [ "$UNINSTALL" -eq 1 ] \
|| { printf '%s\n' '--purge requires --uninstall' >&2; exit 2; }
if [ -z "$INSTALL_DIR" ]; then
[ -n "${HOME:-}" ] || { printf '%s\n' 'HOME is not set; pass --install-dir or FIRECRAB_INSTALL_DIR' >&2; exit 1; }
INSTALL_DIR="$HOME/.local/bin"
fi
if [ "$UNINSTALL" -eq 1 ]; then
for name in firecrab firecrab-micromanager-macos; do
binary="$INSTALL_DIR/$name"
if [ -d "$binary" ]; then
printf 'cannot uninstall: %s is a directory\n' "$binary" >&2
exit 1
fi
if [ -e "$binary" ] || [ -L "$binary" ]; then
rm -f "$binary"
printf 'removed %s from %s\n' "$name" "$binary"
elif [ "$name" = firecrab ]; then
printf 'firecrab CLI is not installed at %s\n' "$binary"
fi
done
if [ "$PURGE" -eq 1 ]; then
if [ -n "${FIRECRAB_CONFIG_DIR:-}" ]; then
config_dir=$FIRECRAB_CONFIG_DIR
else
[ -n "${HOME:-}" ] || { printf '%s\n' 'HOME is not set; set FIRECRAB_CONFIG_DIR to purge configuration' >&2; exit 1; }
config_dir="$HOME/.firecrab"
fi
config="$config_dir/config.toml"
if [ -e "$config" ] || [ -L "$config" ]; then
rm -f "$config"
printf 'removed saved hosts from %s\n' "$config"
fi
rmdir "$config_dir" 2>/dev/null || true
fi
exit 0
fi
RELEASE_BASE=${RELEASE_BASE%/}
case "$RELEASE_BASE" in
https://?*) ;;
file://?*)
[ "${FIRECRAB_TEST_ALLOW_FILE_URL:-}" = 1 ] \
|| { printf '%s\n' 'file:// release roots require FIRECRAB_TEST_ALLOW_FILE_URL=1' >&2; exit 1; }
;;
*)
printf '%s\n' 'FIRECRAB_RELEASE_BASE must use HTTPS' >&2
exit 1
;;
esac
raw_os=${FIRECRAB_CLI_OS:-$(uname -s 2>/dev/null || printf unknown)}
case "$raw_os" in
Linux|linux) platform=linux ;;
Darwin|darwin|macOS|macos) platform=macos ;;
*) printf 'unsupported client OS: %s\n' "$raw_os" >&2; exit 1 ;;
esac
raw_arch=${FIRECRAB_CLI_ARCH:-$(uname -m 2>/dev/null || printf unknown)}
case "$raw_arch" in
x86_64|amd64|X64) architecture=x86_64 ;;
aarch64|arm64|Arm64) architecture=aarch64 ;;
*) printf 'unsupported client architecture: %s\n' "$raw_arch" >&2; exit 1 ;;
esac
case "$platform" in
linux)
raw_libc=${FIRECRAB_CLI_LIBC:-}
if [ -z "$raw_libc" ]; then
if [ -e /lib/ld-musl-x86_64.so.1 ] || [ -e /lib/ld-musl-aarch64.so.1 ] \
|| { command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; }; then
raw_libc=musl
else
raw_libc=gnu
fi
fi
case "$raw_libc" in
gnu|glibc) libc=gnu ;;
musl) libc=musl ;;
*) printf 'unsupported Linux libc: %s\n' "$raw_libc" >&2; exit 1 ;;
esac
asset="firecrab-cli-${architecture}-linux-${libc}.tar.gz"
;;
macos)
[ "$architecture" = aarch64 ] \
|| { printf '%s\n' 'unsupported macOS client architecture: x86_64' >&2; exit 1; }
asset="firecrab-cli-aarch64-macos.tar.gz"
;;
esac
case "$VERSION" in
''|latest) download_root="$RELEASE_BASE/latest/download" ;;
v*) download_root="$RELEASE_BASE/download/$VERSION" ;;
*) download_root="$RELEASE_BASE/download/v$VERSION" ;;
esac
asset_url="$download_root/$asset"
[ "$PRINT_ASSET" -eq 0 ] || { printf '%s\n' "$asset"; exit 0; }
[ "$PRINT_URL" -eq 0 ] || { printf '%s\n' "$asset_url"; exit 0; }
if [ "$CHECK" -eq 1 ]; then
printf 'would install %s to %s/firecrab\n' "$asset_url" "$INSTALL_DIR"
if [ "$platform" = macos ]; then
printf 'would install the signed microManager helper to %s/firecrab-micromanager-macos\n' "$INSTALL_DIR"
fi
exit 0
fi
command -v curl >/dev/null 2>&1 || { printf '%s\n' 'curl is required' >&2; exit 1; }
command -v tar >/dev/null 2>&1 || { printf '%s\n' 'tar is required' >&2; exit 1; }
temporary=$(mktemp -d 2>/dev/null || mktemp -d -t firecrab-cli)
temporary_binary=
temporary_helper=
cleanup() {
rm -rf "$temporary"
[ -z "$temporary_binary" ] || rm -f "$temporary_binary"
[ -z "$temporary_helper" ] || rm -f "$temporary_helper"
}
trap cleanup EXIT HUP INT TERM
curl -fsSL "$asset_url" -o "$temporary/$asset"
curl -fsSL "$download_root/SHA256SUMS" -o "$temporary/SHA256SUMS"
expected=$(awk -v name="$asset" '
$2 == name || $2 == "*" name || $2 ~ "/" name "$" { print $1; exit }
' "$temporary/SHA256SUMS")
[ -n "$expected" ] || { printf 'checksum missing for %s\n' "$asset" >&2; exit 1; }
if command -v sha256sum >/dev/null 2>&1; then
actual=$(sha256sum "$temporary/$asset" | awk '{ print $1 }')
elif command -v shasum >/dev/null 2>&1; then
actual=$(shasum -a 256 "$temporary/$asset" | awk '{ print $1 }')
else
printf '%s\n' 'sha256sum or shasum is required' >&2
exit 1
fi
[ "$actual" = "$expected" ] || { printf 'checksum mismatch for %s\n' "$asset" >&2; exit 1; }
mkdir -p "$temporary/unpacked" "$INSTALL_DIR"
INSTALL_DIR=$(cd "$INSTALL_DIR" && pwd -P)
tar -xzf "$temporary/$asset" -C "$temporary/unpacked"
[ -f "$temporary/unpacked/firecrab" ] \
|| { printf '%s\n' 'release archive does not contain firecrab' >&2; exit 1; }
if [ "$platform" = macos ]; then
[ -f "$temporary/unpacked/firecrab-micromanager-macos" ] \
|| { printf '%s\n' 'macOS release archive does not contain firecrab-micromanager-macos' >&2; exit 1; }
fi
[ ! -d "$INSTALL_DIR/firecrab" ] \
|| { printf '%s\n' 'install destination firecrab is a directory' >&2; exit 1; }
[ "$platform" != macos ] || [ ! -d "$INSTALL_DIR/firecrab-micromanager-macos" ] \
|| { printf '%s\n' 'install destination firecrab-micromanager-macos is a directory' >&2; exit 1; }
temporary_binary=$(mktemp "$INSTALL_DIR/.firecrab-install.XXXXXX") \
|| { printf '%s\n' 'could not create a private temporary install file' >&2; exit 1; }
cp "$temporary/unpacked/firecrab" "$temporary_binary"
chmod 0755 "$temporary_binary"
if [ "$platform" = macos ]; then
temporary_helper=$(mktemp "$INSTALL_DIR/.firecrab-micromanager-install.XXXXXX") \
|| { printf '%s\n' 'could not create a private temporary helper install file' >&2; exit 1; }
cp "$temporary/unpacked/firecrab-micromanager-macos" "$temporary_helper"
chmod 0755 "$temporary_helper"
mv -f "$temporary_helper" "$INSTALL_DIR/firecrab-micromanager-macos"
temporary_helper=
fi
mv -f "$temporary_binary" "$INSTALL_DIR/firecrab"
temporary_binary=
printf 'installed firecrab to %s/firecrab\n' "$INSTALL_DIR"
if [ "$platform" = macos ]; then
printf 'installed microManager helper to %s/firecrab-micromanager-macos\n' "$INSTALL_DIR"
fi
case ":${PATH:-}:" in
*:"$INSTALL_DIR":*) ;;
*)
printf '%s\n' "$INSTALL_DIR is not on PATH. Add this line to your shell profile:"
printf ' export PATH="%s:%s"\n' "$INSTALL_DIR" "\$PATH"
;;
esac