diff --git a/site/public/install.sh b/site/public/install.sh new file mode 100755 index 0000000..042daad --- /dev/null +++ b/site/public/install.sh @@ -0,0 +1,483 @@ +#!/usr/bin/env sh + +# Options +# +# -V, --verbose +# Enable verbose output for the installer +# +# -f, -y, --force, --yes +# Skip the confirmation prompt during installation + +TERMSCP_VERSION="1.0.0" +GITHUB_URL="https://github.com/veeso/termscp/releases/download/v${TERMSCP_VERSION}" +DEB_URL_AMD64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}-1_amd64.deb" +DEB_URL_AARCH64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}-1_arm64.deb" + +PATH="$PATH:/usr/sbin" + +set -eu +printf "\n" + +BOLD="$(tput bold 2>/dev/null || printf '')" +GREY="$(tput setaf 0 2>/dev/null || printf '')" +UNDERLINE="$(tput smul 2>/dev/null || printf '')" +RED="$(tput setaf 1 2>/dev/null || printf '')" +GREEN="$(tput setaf 2 2>/dev/null || printf '')" +YELLOW="$(tput setaf 3 2>/dev/null || printf '')" +BLUE="$(tput setaf 4 2>/dev/null || printf '')" +MAGENTA="$(tput setaf 5 2>/dev/null || printf '')" +NO_COLOR="$(tput sgr0 2>/dev/null || printf '')" + +# Functions + +set_termscp_version() { + TERMSCP_VERSION="$1" + GITHUB_URL="https://github.com/veeso/termscp/releases/download/v${TERMSCP_VERSION}" + DEB_URL_AMD64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}-1_amd64.deb" + DEB_URL_AARCH64="${GITHUB_URL}/termscp_${TERMSCP_VERSION}-1_arm64.deb" +} + +info() { + printf '%s\n' "${BOLD}${GREY}>${NO_COLOR} $*" +} + +warn() { + printf '%s\n' "${YELLOW}! $*${NO_COLOR}" +} + +error() { + printf '%s\n' "${RED}x $*${NO_COLOR}" >&2 +} + +completed() { + printf '%s\n' "${GREEN}✓${NO_COLOR} $*" +} + +has() { + command -v "$1" 1>/dev/null 2>&1 +} + +get_tmpfile() { + local suffix + suffix="$1" + if has mktemp; then + printf "%s.%s" "$(mktemp)" "${suffix}" + else + # No really good options here--let's pick a default + hope + printf "/tmp/termscp.%s" "${suffix}" + fi +} + +download() { + output="$1" + url="$2" + + if has curl; then + cmd="curl --fail --silent --location --output $output $url" + elif has wget; then + cmd="wget --quiet --output-document=$output $url" + elif has fetch; then + cmd="fetch --quiet --output=$output $url" + else + error "No HTTP download program (curl, wget, fetch) found, exiting…" + return 1 + fi + $cmd && return 0 || rc=$? + + error "Command failed (exit code $rc): ${BLUE}${cmd}${NO_COLOR}" + warn "If you believe this is a bug, please report immediately an issue to " + return $rc +} + +test_writeable() { + local path + path="${1:-}/test.txt" + if touch "${path}" 2>/dev/null; then + rm "${path}" + return 0 + else + return 1 + fi +} + +elevate_priv() { + if has sudo; then + if ! sudo -v; then + error "Superuser not granted, aborting installation" + exit 1 + fi + sudo="sudo" + elif has doas; then + sudo="doas" + else + error 'Could not find the commands "sudo" or "doas", needed to install termscp on your system.' + info "If you are on Windows, please run your shell as an administrator, then" + info "rerun this script. Otherwise, please run this script as root, or install" + info "sudo or doas." + exit 1 + fi +} + +elevate_priv_ex() { + check_dir="$1" + if test_writeable "$check_dir"; then + sudo="" + else + elevate_priv + fi + echo $sudo +} + +# Currently supporting: +# - macos +# - linux +# - freebsd +detect_platform() { + local platform + platform="$(uname -s | tr '[:upper:]' '[:lower:]')" + + case "${platform}" in + linux) platform="linux" ;; + darwin) platform="macos" ;; + freebsd) platform="freebsd" ;; + esac + + printf '%s' "${platform}" +} + +# Currently supporting: +# - x86_64 +detect_arch() { + local arch + arch="$(uname -m | tr '[:upper:]' '[:lower:]')" + + case "${arch}" in + amd64) arch="x86_64" ;; + armv*) arch="arm" ;; + arm64) arch="aarch64" ;; + esac + + # `uname -m` in some cases mis-reports 32-bit OS as 64-bit, so double check + if [ "${arch}" = "x86_64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then + arch="i686" + elif [ "${arch}" = "aarch64" ] && [ "$(getconf LONG_BIT)" -eq 32 ]; then + arch="arm" + fi + + printf '%s' "${arch}" +} + +confirm() { + if [ -z "${FORCE-}" ]; then + printf "%s " "${MAGENTA}?${NO_COLOR} $* ${BOLD}[y/N]${NO_COLOR}" + set +e + read -r yn " "macos" + fi +} + +# -- cargo installation + +install_bsd_cargo_deps() { + set -e + confirm "${YELLOW}gcc${NO_COLOR} is required to install ${GREEN}termscp${NO_COLOR}; would you like to proceed?" + sudo="$(elevate_priv_ex /usr/local/bin)" + $sudo pkg install -y curl wget gcc dbus pkgconf libsmbclient + info "Dependencies installed successfully" +} + +install_linux_cargo_deps() { + local debian_deps="gcc pkg-config libdbus-1-dev libsmbclient-dev" + local rpm_deps="gcc openssl pkgconfig dbus-devel openssl-devel libsmbclient-devel" + local arch_deps="gcc openssl pkg-config dbus smbclient" + local deps_cmd="" + # Get pkg manager + if has apt; then + deps_cmd="apt install -y $debian_deps" + elif has apt-get; then + deps_cmd="apt-get install -y $debian_deps" + elif has yum; then + deps_cmd="yum -y install $rpm_deps" + elif has dnf; then + deps_cmd="dnf -y install $rpm_deps" + elif has pacman; then + deps_cmd="pacman -S --noconfirm $arch_deps" + else + error "Could not find any suitable package manager for your linux distro 🙄" + error "Supported package manager are: 'apt', 'apt-get', 'yum', 'dnf', 'pacman'" + exit 1 + fi + set -e + confirm "${YELLOW}gcc, openssl, pkg-config, libdbus${NO_COLOR} are required to install ${GREEN}termscp${NO_COLOR}. The following command will be used to install the dependencies: '${BOLD}${YELLOW}${deps_cmd}${NO_COLOR}'. Would you like to proceed?" + sudo="$(elevate_priv_ex /usr/local/bin)" + $sudo $deps_cmd + info "Dependencies installed successfully" +} + +install_cargo() { + if has cargo; then + return 0 + fi + cargo_env="$HOME/.cargo/env" + # Check if cargo is already installed (actually), but not loaded + if [ -f $cargo_env ]; then + . $cargo_env + fi + # Check again cargo + if has cargo; then + return 0 + else + confirm "${YELLOW}rust${NO_COLOR} is required to build termscp with cargo; would you like to install it now?" + set -e + rustup=$(get_tmpfile "sh") + info "Downloading rustup.sh…" + download "${rustup}" "https://sh.rustup.rs" + chmod +x $rustup + $rustup -y + rm -f ${archive} + info "Rust installed with success" + . $cargo_env + fi + +} + +try_with_cargo() { + err="$1" + platform="$2" + # Install cargo + install_cargo + if has cargo; then + info "Installing ${GREEN}termscp${NO_COLOR} via Cargo…" + case $platform in + "freebsd") + install_bsd_cargo_deps + cargo install --locked --no-default-features termscp + ;; + + "linux") + install_linux_cargo_deps + cargo install --locked termscp + ;; + + *) + cargo install --locked termscp + ;; + + esac + else + error "$err" + error "Alternatively you can opt for installing Cargo " + return 1 + fi +} + +# defaults +if [ -z "${PLATFORM-}" ]; then + PLATFORM="$(detect_platform)" +fi + +if [ -z "${BIN_DIR-}" ]; then + BIN_DIR=/usr/local/bin +fi + +if [ -z "${ARCH-}" ]; then + ARCH="$(detect_arch)" +fi + +if [ -z "${BASE_URL-}" ]; then + BASE_URL="https://github.com/starship/starship/releases" +fi + +# parse argv variables +while [ "$#" -gt 0 ]; do + echo $1 + case "$1" in + + -V | --verbose) + VERBOSE=1 + shift 1 + ;; + -f | -y | --force | --yes) + FORCE=1 + shift 1 + ;; + -V=* | --verbose=*) + VERBOSE="${1#*=}" + shift 1 + ;; + -f=* | -y=* | --force=* | --yes=*) + FORCE="${1#*=}" + shift 1 + ;; + -v=* | --version=*) + set_termscp_version "${1#*=}" + shift 1 + ;; + *) + error "Unknown option: $1" + exit 1 + ;; + esac +done + +printf " %s\n" "${UNDERLINE}Termscp configuration${NO_COLOR}" +info "${BOLD}Platform${NO_COLOR}: ${GREEN}${PLATFORM}${NO_COLOR}" +info "${BOLD}Arch${NO_COLOR}: ${GREEN}${ARCH}${NO_COLOR}" + +# non-empty VERBOSE enables verbose untarring +if [ -n "${VERBOSE-}" ]; then + VERBOSE=v + info "${BOLD}Verbose${NO_COLOR}: yes" +else + VERBOSE= +fi + +printf "\n" + +confirm "Install ${GREEN}termscp ${TERMSCP_VERSION}${NO_COLOR}?" + +# Installation based on arch +case $PLATFORM in + "freebsd") + install_on_bsd + ;; + "linux") + install_on_linux + ;; + "macos") + install_on_macos + ;; + *) + error "${PLATFORM} is not supported by this installer" + exit 1 + ;; +esac + +completed "Congratulations! Termscp has successfully been installed on your system!" +info "If you're a new user, you might be interested in reading the user manual " +info "While if you've just updated your termscp version, you can find the changelog at this link " +info "Remember that if you encounter any issue, you can report them on Github " +info "Feel free to open an issue also if you have an idea which could improve the project" +info "If you want to support the project, please, consider a little donation " +info "I hope you'll enjoy using termscp :D" + +exit 0 diff --git a/site/src/components/InstallTabs.astro b/site/src/components/InstallTabs.astro new file mode 100644 index 0000000..865941d --- /dev/null +++ b/site/src/components/InstallTabs.astro @@ -0,0 +1,34 @@ +--- +interface Method { id: string; label: string; cmd: string; } +interface Props { methods: Method[]; } +const { methods } = Astro.props; +--- +
+
+ {methods.map((m, i) => ( + + ))} +
+ {methods.map((m, i) => ( + + ))} +
+ diff --git a/site/src/pages/install.astro b/site/src/pages/install.astro new file mode 100644 index 0000000..6bc321e --- /dev/null +++ b/site/src/pages/install.astro @@ -0,0 +1,54 @@ +--- +import Base from "../layouts/Base.astro"; +import Nav from "../components/Nav.astro"; +import Footer from "../components/Footer.astro"; +import InstallTabs from "../components/InstallTabs.astro"; +import { useTranslations, DOCS_URL } from "../i18n/ui"; + +const locale = "en" as const; +const t = useTranslations(locale); + +const script = "curl --proto '=https' --tlsv1.2 -sSLf https://termscp.rs/install.sh | sh"; + +// Verified package managers (see repo README). Cargo is universal. +const methods = [ + { id: "cargo", label: "Cargo", cmd: "cargo install termscp --locked" }, + { id: "arch", label: "Arch Linux", cmd: "pacman -S termscp" }, + { id: "netbsd", label: "NetBSD", cmd: "pkgin install termscp" }, + { id: "choco", label: "Windows (Chocolatey)", cmd: "choco install termscp" }, +]; +--- + +