install.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/sh
#
# Installs the Wispers Access CLI tools, waserver and waclient, from the newest
# GitHub release of each. Re-running it upgrades the tools.
#
# curl -fsSL https://raw.githubusercontent.com/s-te-ch/wispers-access/main/install.sh | sh
#
# Currently supported platforms are Linux (amd64, arm64) and macOS (Apple
# silicon). The binaries go to /usr/local/bin, or to the directory given with
# --prefix. If that directory is not writable, sudo is used for that one step.
#
# This script doesn't support Windows. Instead, download the zip from
# https://github.com/s-te-ch/wispers-access/releases
set -eu
REPO="s-te-ch/wispers-access"
COMPONENTS="waserver waclient"
prefix="/usr/local/bin"
main() {
parse_args "$@"
target="$(detect_target)"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
fetch "https://api.github.com/repos/$REPO/releases?per_page=100" "$tmp/releases.json"
installed=""
upgraded=""
for component in $COMPONENTS; do
install_component "$component"
done
check_path
case " $upgraded " in
*" waserver "*)
say "A running waserver keeps the old version until it is restarted" \
"(systemctl restart 'waserver@*', or waserver stop and start)." ;;
esac
case " $installed " in
*" waserver "*)
say ""
say "Next: share an app with 'waserver init <share> \"<Name>\"', then 'waserver edit <share>';"
say "see https://github.com/$REPO#quick-start. For a systemd service, see"
say "https://github.com/$REPO/tree/main/integrations/systemd." ;;
esac
}
parse_args() {
while [ $# -gt 0 ]; do
case "$1" in
--prefix) shift; prefix="${1:?--prefix needs a directory}" ;;
--prefix=*) prefix="${1#--prefix=}" ;;
-h|--help) usage; exit 0 ;;
*) die "unknown argument '$1' (try --help)" ;;
esac
shift
done
}
usage() {
cat <<USAGE
Installs the newest release of waserver and waclient.
curl -fsSL https://raw.githubusercontent.com/$REPO/main/install.sh | sh
curl -fsSL https://raw.githubusercontent.com/$REPO/main/install.sh | sh -s -- --prefix ~/.local/bin
--prefix DIR install into DIR instead of $prefix
USAGE
}
# Detects the release target name for this machine.
detect_target() {
os="$(uname -s)"
arch="$(uname -m)"
case "$os/$arch" in
Linux/x86_64) echo linux-amd64 ;;
Linux/aarch64 | Linux/arm64) echo linux-arm64 ;;
Darwin/arm64) echo macos-arm64 ;;
Darwin/x86_64) die "there is no build for Intel Macs" ;;
*) die "unsupported platform $os/$arch; see https://github.com/$REPO/releases" ;;
esac
}
# Installs one component at its newest release, unless that is installed
# already. Each component has its own release tags, <component>-vX.Y.Z.
install_component() {
component="$1"
version="$(newest_version "$component")"
current="$(installed_version "$component")"
if [ "$current" = "$version" ]; then
say "$component $version is already in $prefix"
return
elif [ -n "$current" ]; then
say "Upgrading $component $current to $version"
upgraded="$upgraded $component"
else
say "Installing $component $version"
installed="$installed $component"
fi
archive="$component-$version-$target.tar.gz"
base="https://github.com/$REPO/releases/download/$component-v$version"
fetch "$base/$archive" "$tmp/$archive"
fetch "$base/SHA256SUMS" "$tmp/$component.SHA256SUMS"
verify "$tmp/$archive" "$tmp/$component.SHA256SUMS"
tar -xzf "$tmp/$archive" -C "$tmp"
install_binary "$tmp/${archive%.tar.gz}/$component"
}
# Detects the component's newest release.
newest_version() {
# The API lists releases newest first, so just take the first match.
version="$(sed -n 's/.*"tag_name": *"'"$1"'-v\([^"]*\)".*/\1/p' "$tmp/releases.json" | head -n 1)"
[ -n "$version" ] || die "found no $1 release at https://github.com/$REPO/releases"
echo "$version"
}
# Detects the already installed version of the component, or nothing.
installed_version() {
[ -x "$prefix/$1" ] || return 0
"$prefix/$1" --version 2>/dev/null | awk '{print $2}' || true
}
# Checks the archive against its line in the release's SHA256SUMS.
verify() {
name="$(basename "$1")"
expected="$(awk -v name="$name" '$2 == name {print $1}' "$2")"
[ -n "$expected" ] || die "$name is not in the release's SHA256SUMS"
if command -v sha256sum >/dev/null 2>&1; then
actual="$(sha256sum "$1" | awk '{print $1}')"
else
actual="$(shasum -a 256 "$1" | awk '{print $1}')"
fi
[ "$actual" = "$expected" ] || die "checksum mismatch for $name"
}
# Puts the binary into $prefix, with sudo if the directory is not ours.
install_binary() {
if [ -w "$prefix" ] || { [ ! -e "$prefix" ] && mkdir -p "$prefix" 2>/dev/null; }; then
install -m 755 "$1" "$prefix/"
elif command -v sudo >/dev/null 2>&1; then
say " $prefix is not writable, using sudo"
sudo install -d "$prefix"
sudo install -m 755 "$1" "$prefix/"
else
die "$prefix is not writable and there is no sudo; run as root or use --prefix"
fi
}
# Warn when the tools in $prefix are not the ones a shell will run. That is, if
# $prefix is not on the PATH, or ifanother copy (a cargo install, say) comes
# first.
check_path() {
case ":$PATH:" in
*":$prefix:"*) ;;
*) say "Note: $prefix is not on your PATH."; return ;;
esac
for component in $COMPONENTS; do
found="$(command -v "$component" 2>/dev/null || true)"
if [ -n "$found" ] && ! [ "$found" -ef "$prefix/$component" ]; then
say "Note: '$component' on your PATH is $found, which shadows $prefix/$component."
fi
done
}
fetch() {
if command -v curl >/dev/null 2>&1; then
curl -fsSL --retry 3 -o "$2" "$1" || die "download failed: $1"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$2" "$1" || die "download failed: $1"
else
die "need curl or wget"
fi
}
say() { printf '%s\n' "$*"; }
die() { printf 'install.sh: %s\n' "$*" >&2; exit 1; }
main "$@"