#!/bin/bash # ============================================================================= # machine-setup — command-line tools that do not come from the distribution # ============================================================================= # # Definitions only, like the other lib/ files. # # These four were buried inside "System Update & Essentials", after the package # install and with no announcement, so a run appeared to be installing system # packages and then started downloading tarballs and printing a shell tutorial. # They are their own concern: upstream binaries, fetched from upstream, on their # own release cadence. # # Each one is checked before it is fetched. The original re-ran every installer # on every run — which is how a machine that already had starship got it # reinstalled, along with its "add this to your ~/.zshrc" instructions, which we # do not want because this script writes the shell config itself. [[ -n "${MACHINE_SETUP_TOOLS_LOADED:-}" ]] && return 0 MACHINE_SETUP_TOOLS_LOADED=1 # The set installed on every machine, in the order they are fetched. tools_default() { echo lazydocker lazygit starship fastfetch; } # The command that proves a tool is already here. Same as the tool name for all # four today, but kept as a mapping because that is not a rule — a package and # the binary it provides disagree often enough (fd-find/fdfind) to be worth the # indirection. tool_command() { case "$1" in lazydocker) echo lazydocker ;; lazygit) echo lazygit ;; starship) echo starship ;; fastfetch) echo fastfetch ;; *) echo "$1" ;; esac } tool_is_installed() { command -v "$(tool_command "$1")" &>/dev/null; } # ----------------------------------------------------------------------------- # The installers # ----------------------------------------------------------------------------- tool_install_lazydocker() { curl -fsSL https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | DIR=/usr/local/bin bash } # The one that was actually broken on arm64: the asset name was hardcoded to # x86_64, so an arm machine downloaded a 404 and tar failed halfway through the # run. lazygit spells the architectures x86_64 and arm64, which is neither of the # two spellings ARCH uses, hence the mapping. tool_install_lazygit() { local version asset url case "$ARCH" in amd64) asset="x86_64" ;; arm64) asset="arm64" ;; esac version="$(curl -fsSL https://api.github.com/repos/jesseduffield/lazygit/releases/latest | jq -r '.tag_name')" # Strip only the leading v. The original used `tr -d 'v'`, which deletes every # v in the string and would mangle any tag that had one anywhere else. version="${version#v}" [[ -n "$version" ]] || { warn "could not read the latest lazygit version — skipping" return 0 } url="https://github.com/jesseduffield/lazygit/releases/download/v${version}/lazygit_${version}_Linux_${asset}.tar.gz" curl -fsSLo /tmp/lazygit.tar.gz "$url" tar -C /usr/local/bin -xzf /tmp/lazygit.tar.gz lazygit rm -f /tmp/lazygit.tar.gz } # Quiet on purpose. The installer ends by printing how to add starship to bash, # zsh, ion, tcsh and xonsh — five shells' worth of instructions for a step that # already writes the zsh config itself. Errors still come through. tool_install_starship() { curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin >/dev/null } # A distribution package everywhere, but not always one the distribution ships: # Ubuntu only picked fastfetch up in 24.10, so on noble and older the PPA is the # only source. Checked rather than assumed, so the PPA stops being added the # moment the archive has it. tool_install_fastfetch() { if [[ "$PM" == "apt" ]] && ! apt-cache policy fastfetch 2>/dev/null | grep -q 'Candidate: [0-9]'; then info " fastfetch is not in this release's archive — adding the upstream PPA" add-apt-repository -y ppa:zhangsongcui3371/fastfetch >/dev/null 2>&1 || { warn "could not add the fastfetch PPA — skipping" return 0 } pkg_refresh >/dev/null 2>&1 fi pkg_install_now fastfetch } # ----------------------------------------------------------------------------- # Acting # ----------------------------------------------------------------------------- # Announce the section, then fetch only what is absent — same contract and same # output shape as pkg_install, so the two read alike in a transcript. tools_install() { local label="$1" shift local tool local -a missing=() present=() for tool in "$@"; do if tool_is_installed "$tool"; then present+=("$tool"); else missing+=("$tool"); fi done info "$label — installs what is missing, keeps what you already have" ((${#present[@]})) && echo " already here: ${present[*]}" if ((${#missing[@]} == 0)); then echo " to install: nothing, all present" return 0 fi echo " to install: ${missing[*]}" for tool in "${missing[@]}"; do info " installing ${tool}..." "tool_install_${tool}" done }