#!/usr/bin/env bash set -euo pipefail install_sometimes() { fail() { printf 'sometimes: %s\n' "$*" >&2; exit 1; } [[ $(uname -s) == Linux && $(uname -m) == x86_64 ]] || fail 'This installer requires x86_64 Linux. See https://sometimeschat.com/downloads' [[ $EUID -ne 0 ]] || fail 'Run this command as your normal user, without sudo.' if [[ -f /run/ostree-booted ]] || command -v transactional-update >/dev/null; then fail 'This system uses transactional updates. See https://sometimeschat.com/downloads' fi local ID='' ID_LIKE='' family='' manager='' prerequisites='' distro [[ -r /etc/os-release ]] || fail 'Cannot identify this Linux distribution.' # shellcheck source=/dev/null . /etc/os-release for distro in "$ID" $ID_LIKE; do case "$distro" in arch|archlinux|cachyos|endeavouros|manjaro) family=arch; break ;; debian|ubuntu|linuxmint|pop) family=deb; break ;; fedora|rhel|centos|rocky|almalinux) family=rpm; manager=dnf; break ;; opensuse*|suse|sles) family=rpm; manager=zypper; break ;; esac done case "$family" in arch) prerequisites='sudo pacman -S --needed base-devel curl sudo'; set -- makepkg pacman ;; deb) prerequisites='sudo apt-get install curl sudo coreutils util-linux'; set -- apt-get apt-cache sha256sum ;; rpm) prerequisites="sudo $manager install curl sudo rpm-build binutils tar xz coreutils util-linux gawk" [[ $manager != zypper ]] || prerequisites="$prerequisites util-linux-systemd" set -- "$manager" rpmbuild rpm ar tar xz sha256sum ;; *) fail 'This distribution is not supported by the installer. See https://sometimeschat.com/downloads' ;; esac for tool in curl sudo findmnt df mktemp awk "$@"; do command -v "$tool" >/dev/null || fail "Missing $tool. First install the prerequisites: $prerequisites" done if [[ $family == arch ]]; then pacman -Q base-devel >/dev/null 2>&1 || fail "First install the prerequisites: $prerequisites" fi { : < /dev/tty; } 2>/dev/null || fail 'Run this installer in an interactive terminal.' local ram='' candidate work cleanup for candidate in /tmp /dev/shm; do if [[ $(findmnt -n -o FSTYPE -T "$candidate") == tmpfs && -w $candidate ]] && [[ $(df -Pk "$candidate" | awk 'NR==2 {print $4}') -ge 1572864 ]]; then ram=$candidate break fi done [[ -n $ram ]] || fail 'At least 1.5 GiB of free space in /tmp or /dev/shm is required.' umask 077 work=$(mktemp -d "$ram/sometimes-install.XXXXXXXX") printf -v cleanup 'rm -rf -- %q' "$work" # shellcheck disable=SC2064 trap "$cleanup" EXIT trap 'exit 130' INT trap 'exit 143' TERM printf '\nsometimes ยท installing for %s (%s)\nBuild directory: %s\n\n' "$ID" "$family" "$work" fetch() { curl --fail --show-error --silent --location --proto '=https' --proto-redir '=https' \ "https://sometimeschat.com/$1" -o "$2" } privileged_install() { # Read the original user's terminal; sudo handles only the package manager. # shellcheck disable=SC2024 sudo "$@" < /dev/tty } cd "$work" if [[ $family == arch ]]; then fetch packages/arch/PKGBUILD "$work/PKGBUILD" export BUILDDIR="$work" PKGDEST="$work" SRCDEST="$work" SRCPKGDEST="$work" LOGDEST="$work" makepkg --syncdeps --install --rmdeps --clean < /dev/tty else local checksum file extra version payload fetch packages/linux/SHA256SUMS "$work/SHA256SUMS" read -r checksum file extra < "$work/SHA256SUMS" [[ $checksum =~ ^[a-f0-9]{64}$ && -z $extra && $file =~ ^([0-9]+\.[0-9]+\.[0-9]+)/(b[0-9]{6,}/)?Sometimes-([0-9]+\.[0-9]+\.[0-9]+)-linux-amd64\.deb$ ]] || fail 'Invalid package checksum record.' version=${BASH_REMATCH[1]} [[ $version == "${BASH_REMATCH[3]}" ]] || fail 'Package version mismatch.' payload=${file##*/} fetch "api/desktop-downloads/$file" "$work/$payload" printf '%s %s\n' "$checksum" "$payload" | sha256sum --check --status || fail 'Package checksum verification failed.' if [[ $family == deb ]]; then # Allow apt's unprivileged download helper to read this public package. chmod 755 "$work" chmod 644 "$work/$payload" # Older published DEBs omit ALSA; handle the t64 rename on newer systems. local alsa=libasound2 if apt-cache show libasound2t64 >/dev/null 2>&1; then alsa=libasound2t64; fi privileged_install apt-get install --reinstall "$work/$payload" "$alsa" libgbm1 else fetch packages/rpm/sometimes.spec "$work/sometimes.spec" mkdir -p "$work"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} mv "$work/$payload" "$work/SOURCES/" rpmbuild -bb --define "_topdir $work" "$work/sometimes.spec" local package="$work/RPMS/x86_64/sometimes-desktop-$version-1.x86_64.rpm" [[ -f $package ]] || fail 'RPM build did not produce the expected package.' if [[ $manager == zypper ]]; then # Only this locally built RPM is unsigned; repository checks stay enabled. privileged_install zypper install --force --allow-unsigned-rpm "$package" else if rpm -q sometimes-desktop >/dev/null 2>&1; then privileged_install dnf reinstall "$package" else privileged_install dnf install "$package" fi fi fi fi printf '\nsometimes is installed. Open it from your applications menu.\n' rm -rf -- "$work" trap - EXIT INT TERM } install_sometimes "$@"