Current section
Files
Jump to
Current section
Files
priv/templates/install.sh.eex
#!/usr/bin/env sh
# <%= @app %> installer — generated by tinfoil <%= @tinfoil_version %>
#
# Usage:
# curl -fsSL <%= @raw_url %> | sh
# curl -fsSL <%= @raw_url %> | sh -s -- --version v1.2.3
# curl -fsSL <%= @raw_url %> | sh -s -- --install-dir /usr/local/bin
set -eu
APP="<%= @app %>"
REPO="<%= @repo %>"
DEFAULT_INSTALL_DIR="<%= @install_dir %>"
VERSION=""
INSTALL_DIR="$DEFAULT_INSTALL_DIR"
while [ $# -gt 0 ]; do
case "$1" in
--version)
VERSION="$2"; shift 2 ;;
--version=*)
VERSION="${1#*=}"; shift ;;
--install-dir)
INSTALL_DIR="$2"; shift 2 ;;
--install-dir=*)
INSTALL_DIR="${1#*=}"; shift ;;
-h|--help)
sed -n '2,9p' "$0" 2>/dev/null || true
exit 0 ;;
*)
echo "unknown option: $1" >&2
exit 1 ;;
esac
done
die() { echo "error: $*" >&2; exit 1; }
need() { command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"; }
need uname
need tar
need mkdir
if command -v curl >/dev/null 2>&1; then
fetch() { curl -fsSL -o "$2" "$1"; }
fetch_stdout() { curl -fsSL "$1"; }
elif command -v wget >/dev/null 2>&1; then
fetch() { wget -qO "$2" "$1"; }
fetch_stdout() { wget -qO- "$1"; }
else
die "curl or wget is required"
fi
OS_RAW="$(uname -s)"
ARCH_RAW="$(uname -m)"
case "$OS_RAW" in
Darwin) OS="apple-darwin" ;;
Linux) OS="unknown-linux-musl" ;;
*) die "unsupported OS: $OS_RAW" ;;
esac
case "$ARCH_RAW" in
x86_64|amd64) ARCH="x86_64" ;;
arm64|aarch64) ARCH="aarch64" ;;
*) die "unsupported architecture: $ARCH_RAW" ;;
esac
TRIPLE="${ARCH}-${OS}"
# Resolve version
if [ -z "$VERSION" ]; then
echo "Resolving latest release..."
API_URL="https://api.github.com/repos/${REPO}/releases/latest"
VERSION="$(fetch_stdout "$API_URL" \
| tr -d '\r' \
| awk -F'"' '/"tag_name":/ {print $4; exit}')"
[ -n "$VERSION" ] || die "failed to determine latest release tag"
fi
# Normalize (strip leading v for the filename)
VERSION_NO_V="${VERSION#v}"
TAG="$VERSION"
case "$TAG" in v*) ;; *) TAG="v$TAG" ;; esac
ARCHIVE="${APP}-${VERSION_NO_V}-${TRIPLE}.tar.gz"
BASE="https://github.com/${REPO}/releases/download/${TAG}"
URL="${BASE}/${ARCHIVE}"
SUMS_URL="${BASE}/checksums-sha256.txt"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
echo "Downloading ${ARCHIVE}..."
fetch "$URL" "$TMP/$ARCHIVE" || die "download failed: $URL"
# Verify against the combined checksums-sha256.txt that tinfoil
# uploads alongside the archives. Per-archive .sha256 sidecars are
# not published as release assets to keep the release page tidy.
echo "Verifying checksum..."
if fetch "$SUMS_URL" "$TMP/checksums-sha256.txt" 2>/dev/null; then
EXPECTED="$(awk -v a="$ARCHIVE" '$2 == a || $2 == "*" a {print $1; exit}' "$TMP/checksums-sha256.txt")"
if [ -z "$EXPECTED" ]; then
die "no checksum entry for ${ARCHIVE} in checksums-sha256.txt"
fi
if command -v shasum >/dev/null 2>&1; then
ACTUAL="$(shasum -a 256 "$TMP/$ARCHIVE" | awk '{print $1}')"
elif command -v sha256sum >/dev/null 2>&1; then
ACTUAL="$(sha256sum "$TMP/$ARCHIVE" | awk '{print $1}')"
else
die "neither shasum nor sha256sum found"
fi
[ "$EXPECTED" = "$ACTUAL" ] || die "checksum mismatch (expected $EXPECTED, got $ACTUAL)"
echo "Checksum OK."
else
echo "warning: checksums-sha256.txt not found; skipping verification" >&2
fi
echo "Extracting..."
tar -xzf "$TMP/$ARCHIVE" -C "$TMP"
# Expand ~ in install dir
case "$INSTALL_DIR" in
"~"|"~/"*) INSTALL_DIR="${HOME}${INSTALL_DIR#~}" ;;
esac
mkdir -p "$INSTALL_DIR"
mv "$TMP/$APP" "$INSTALL_DIR/$APP"
chmod +x "$INSTALL_DIR/$APP"
echo ""
echo "Installed ${APP} ${VERSION} to ${INSTALL_DIR}/${APP}"
case ":$PATH:" in
*":${INSTALL_DIR}:"*) ;;
*)
echo ""
echo "note: ${INSTALL_DIR} is not on your PATH."
echo " add this to your shell profile:"
echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
;;
esac