mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
149 lines
4.1 KiB
Bash
Executable File
149 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
do_install() {
|
|
REPO="safedep/pmg"
|
|
BINARY="pmg"
|
|
|
|
# Prefer $HOME/.local/bin if it exists and is in PATH.
|
|
INSTALL_DIR="/usr/local/bin"
|
|
if [ -n "${HOME:-}" ]; then
|
|
local_bin="$HOME/.local/bin"
|
|
case ":${PATH}:" in
|
|
*":${local_bin}:"*)
|
|
INSTALL_DIR="$local_bin"
|
|
mkdir -p "$INSTALL_DIR"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Detect OS and architecture.
|
|
OS="$(uname -s)"
|
|
ARCH="$(uname -m)"
|
|
|
|
case "$OS" in
|
|
Linux) os="Linux" ;;
|
|
Darwin) os="Darwin" ;;
|
|
MINGW* | MSYS* | CYGWIN*) os="Windows" ;;
|
|
*)
|
|
echo "Error: unsupported operating system: $OS" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "$ARCH" in
|
|
x86_64 | amd64) arch="x86_64" ;;
|
|
aarch64 | arm64) arch="arm64" ;;
|
|
i386 | i686) arch="i386" ;;
|
|
*)
|
|
echo "Error: unsupported architecture: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# macOS ships a universal binary.
|
|
if [ "$os" = "Darwin" ]; then
|
|
arch="all"
|
|
fi
|
|
|
|
if [ "$os" = "Windows" ]; then
|
|
BINARY="pmg.exe"
|
|
fi
|
|
|
|
# Verify install directory exists.
|
|
if [ ! -d "$INSTALL_DIR" ]; then
|
|
echo "Error: install directory ${INSTALL_DIR} does not exist" >&2
|
|
echo "Create it with: sudo mkdir -p ${INSTALL_DIR}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Fetch latest release tag via redirect (avoids JSON parsing).
|
|
echo "Fetching latest release..."
|
|
tag=$(curl -fsSI -o /dev/null -w '%{redirect_url}' "https://github.com/${REPO}/releases/latest" | sed 's|.*/||')
|
|
if [ -z "$tag" ]; then
|
|
echo "Error: could not determine latest release" >&2
|
|
exit 1
|
|
fi
|
|
echo "Latest release: $tag"
|
|
|
|
# Build download URL.
|
|
# Assets follow the pattern: pmg_{OS}_{arch}.{tar.gz|zip}
|
|
if [ "$os" = "Windows" ]; then
|
|
asset="pmg_${os}_${arch}.zip"
|
|
else
|
|
asset="pmg_${os}_${arch}.tar.gz"
|
|
fi
|
|
url="https://github.com/${REPO}/releases/download/${tag}/${asset}"
|
|
|
|
# Download archive and checksums.
|
|
echo "Downloading ${asset}..."
|
|
tmpdir=$(mktemp -d)
|
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
checksums_url="https://github.com/${REPO}/releases/download/${tag}/checksums.txt"
|
|
if ! curl -fsSL -o "${tmpdir}/${asset}" "$url"; then
|
|
echo "Error: archive not available for ${os}/${arch}" >&2
|
|
echo "Check available assets at https://github.com/${REPO}/releases/tag/${tag}" >&2
|
|
exit 1
|
|
fi
|
|
if ! curl -fsSL -o "${tmpdir}/checksums.txt" "$checksums_url"; then
|
|
echo "Error: could not download checksums.txt from ${checksums_url}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Verify SHA-256 checksum.
|
|
expected=$(grep " ${asset}$" "${tmpdir}/checksums.txt" | cut -d' ' -f1)
|
|
if [ -z "$expected" ]; then
|
|
echo "Error: no checksum entry found for ${asset} in checksums.txt" >&2
|
|
exit 1
|
|
fi
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
actual=$(sha256sum "${tmpdir}/${asset}" | cut -d' ' -f1)
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
actual=$(shasum -a 256 "${tmpdir}/${asset}" | cut -d' ' -f1)
|
|
else
|
|
echo "Error: neither sha256sum nor shasum found; cannot verify download" >&2
|
|
echo " Install one of them and re-run, or download manually from:" >&2
|
|
echo " https://github.com/${REPO}/releases/tag/${tag}" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$actual" != "$expected" ]; then
|
|
echo "Error: checksum mismatch for ${asset}" >&2
|
|
echo " expected: $expected" >&2
|
|
echo " actual: $actual" >&2
|
|
exit 1
|
|
fi
|
|
echo "Checksum verified."
|
|
|
|
if [ "$os" = "Windows" ]; then
|
|
unzip -q -o "${tmpdir}/${asset}" "${BINARY}" -d "${tmpdir}"
|
|
else
|
|
tar -xzf "${tmpdir}/${asset}" -C "${tmpdir}" "${BINARY}"
|
|
fi
|
|
|
|
if [ ! -f "${tmpdir}/${BINARY}" ]; then
|
|
echo "Error: ${BINARY} not found in archive" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Install.
|
|
if [ -w "$INSTALL_DIR" ]; then
|
|
install -m 755 "${tmpdir}/${BINARY}" "${INSTALL_DIR}/${BINARY}"
|
|
else
|
|
echo "Installing to ${INSTALL_DIR} (requires sudo)..."
|
|
sudo install -m 755 "${tmpdir}/${BINARY}" "${INSTALL_DIR}/${BINARY}"
|
|
fi
|
|
|
|
echo "Installed pmg ${tag} to ${INSTALL_DIR}/${BINARY}"
|
|
|
|
# Verify the install directory is in PATH.
|
|
case ":${PATH}:" in
|
|
*":${INSTALL_DIR}:"*) ;;
|
|
*)
|
|
echo "Warning: ${INSTALL_DIR} is not in your PATH. Add it with:" >&2
|
|
echo " export PATH=\"${INSTALL_DIR}:\$PATH\"" >&2
|
|
;;
|
|
esac
|
|
}
|
|
|
|
do_install
|