#!/bin/sh # Install the portable ICT login zipapp for the current user. set -eu usage() { cat <<'EOF' Usage: install.sh [options] Options: -s, --source PATH|URL install this .pyz file -p, --prefix DIR install directory (default: $HOME/.local/bin) --sha256 HEX expected SHA-256 of the .pyz -h, --help show this help Environment overrides: ICTLOGIN_PYZ local .pyz path or URL ICTLOGIN_PYZ_URL download URL when no local artifact is present ICTLOGIN_PYZ_SHA256_URL checksum URL for a downloaded .pyz ICTLOGIN_PYZ_SHA256 expected SHA-256 ICTLOGIN_RELEASE_TAG public Gitea release tag (default: v0.2.0) ICTLOGIN_PREFIX install directory ICTLOGIN_PYTHON Python 3 executable EOF } SOURCE="${ICTLOGIN_PYZ:-}" URL="${ICTLOGIN_PYZ_URL:-}" CHECKSUM_URL="${ICTLOGIN_PYZ_SHA256_URL:-}" EXPECTED_SHA256="${ICTLOGIN_PYZ_SHA256:-}" PREFIX="${ICTLOGIN_PREFIX:-${HOME}/.local/bin}" RELEASE_TAG="${ICTLOGIN_RELEASE_TAG:-v0.2.0}" RELEASE_BASE_URL="https://gitx.roy1994.top/mancitrus/ictlogin/releases/download/${RELEASE_TAG}" while [ "$#" -gt 0 ]; do case "$1" in -s|--source) [ "$#" -ge 2 ] || { echo "--source requires a value" >&2; exit 2; } SOURCE=$2 shift 2 ;; -p|--prefix) [ "$#" -ge 2 ] || { echo "--prefix requires a value" >&2; exit 2; } PREFIX=$2 shift 2 ;; --sha256) [ "$#" -ge 2 ] || { echo "--sha256 requires a value" >&2; exit 2; } EXPECTED_SHA256=$2 shift 2 ;; -h|--help) usage exit 0 ;; *) echo "unknown option: $1" >&2 usage >&2 exit 2 ;; esac done PYTHON="${ICTLOGIN_PYTHON:-}" if [ -z "$PYTHON" ]; then PYTHON=$(command -v python3 2>/dev/null || true) fi if [ -z "$PYTHON" ]; then PYTHON=$(command -v python 2>/dev/null || true) fi if [ -z "$PYTHON" ]; then echo "Python 3 is required" >&2 exit 1 fi if ! "$PYTHON" -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 8) else 1)' 2>/dev/null; then echo "Python 3.8 or newer is required: $PYTHON" >&2 exit 1 fi SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) if [ -z "$SOURCE" ] && [ -z "$URL" ]; then if [ -f "$SCRIPT_DIR/dist/ictlogin.pyz" ]; then SOURCE=$SCRIPT_DIR/dist/ictlogin.pyz elif [ -f "$SCRIPT_DIR/ictlogin.pyz" ]; then SOURCE=$SCRIPT_DIR/ictlogin.pyz else URL="${RELEASE_BASE_URL}/ictlogin.pyz" CHECKSUM_URL="${CHECKSUM_URL:-${RELEASE_BASE_URL}/ictlogin.pyz.sha256}" fi fi SOURCE_PATH="" case "$SOURCE" in http://*|https://*) URL=$SOURCE; SOURCE="" ;; "") ;; *) SOURCE_PATH=$SOURCE [ -f "$SOURCE_PATH" ] || { echo "file not found: $SOURCE_PATH" >&2; exit 1; } ;; esac TMP_FILE=$(mktemp "${TMPDIR:-/tmp}/ictlogin.pyz.XXXXXX") TMP_CHECKSUM="" cleanup() { rm -f "$TMP_FILE" [ -z "$TMP_CHECKSUM" ] || rm -f "$TMP_CHECKSUM" } trap cleanup EXIT HUP INT TERM download() { TARGET_FILE=$1 SOURCE_URL=$2 if command -v curl >/dev/null 2>&1; then curl --fail --location --silent --show-error -o "$TARGET_FILE" "$SOURCE_URL" elif command -v wget >/dev/null 2>&1; then wget --quiet --output-document="$TARGET_FILE" "$SOURCE_URL" else echo "curl or wget is required to download $SOURCE_URL" >&2 exit 1 fi } if [ -n "$URL" ]; then download "$TMP_FILE" "$URL" else cp "$SOURCE_PATH" "$TMP_FILE" fi if [ -z "$EXPECTED_SHA256" ] && [ -n "$SOURCE_PATH" ] && [ -f "${SOURCE_PATH}.sha256" ]; then EXPECTED_SHA256=$(awk 'NF { print $1; exit }' "${SOURCE_PATH}.sha256") fi if [ -z "$EXPECTED_SHA256" ] && [ -n "$CHECKSUM_URL" ]; then TMP_CHECKSUM=$(mktemp "${TMPDIR:-/tmp}/ictlogin.pyz.sha256.XXXXXX") download "$TMP_CHECKSUM" "$CHECKSUM_URL" EXPECTED_SHA256=$(awk 'NF { print $1; exit }' "$TMP_CHECKSUM") if [ -z "$EXPECTED_SHA256" ]; then echo "could not read SHA-256 from $CHECKSUM_URL" >&2 exit 1 fi fi sha256_file() { if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}' else "$PYTHON" - "$1" <<'PY' import hashlib import sys digest = hashlib.sha256() with open(sys.argv[1], "rb") as handle: for chunk in iter(lambda: handle.read(1024 * 1024), b""): digest.update(chunk) print(digest.hexdigest()) PY fi } if [ -n "$EXPECTED_SHA256" ]; then ACTUAL_SHA256=$(sha256_file "$TMP_FILE") if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then echo "SHA-256 verification failed" >&2 echo "expected: $EXPECTED_SHA256" >&2 echo "actual: $ACTUAL_SHA256" >&2 exit 1 fi fi "$PYTHON" "$TMP_FILE" --version >/dev/null mkdir -p "$PREFIX" TARGET="$PREFIX/ictlogin" if command -v install >/dev/null 2>&1; then install -m 0755 "$TMP_FILE" "$TARGET" else cp "$TMP_FILE" "$TARGET" chmod 0755 "$TARGET" fi echo "installed $TARGET" case ":${PATH:-}:" in *":$PREFIX:"*) ;; *) echo "add to PATH: export PATH=\"$PREFIX:\$PATH\"" ;; esac "$TARGET" --version