#!/bin/sh # SPDX-License-Identifier: GPL-3.0-only # # This file is part of the distrobox project: https://github.com/89luca89/distrobox # # Copyright (C) 2021 distrobox contributors # # distrobox is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3 # as published by the Free Software Foundation. # # distrobox is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with distrobox; if not, see . # POSIX # install.sh — fetch distrobox from GitHub. v1 (the legacy POSIX # shell-script release) is the default and recommended for production; # pass --v2 to install the v2 Go release candidate instead. To undo, # run ./uninstall. # # v1 (default): pulls the source tarball at $VERSION and installs every # distrobox* shell script plus man pages, completions, and icons. No # architecture detection is needed (pure POSIX shell). # # v2 (--v2 or any 2.* tag): fetches the bundled release artefact # (distrobox-linux-{amd64,arm64}.tar.gz) for the detected architecture # plus the source tarball for the in-container helpers # (init/export/host-exec), man pages, completions, and icons. # # Intended as a one-liner curl install for users who don't want to # build from source. If you have Go and a checkout, prefer # `make install`. REPO="89luca89/distrobox" # Bump on every release. Override with --version to install a different tag. LEGACY_VERSION="1.8.2.5" V2_VERSION="2.0.0-rc.3" VERSION="${LEGACY_VERSION}" prefix="" no_color=0 verbose=0 force_v2=0 explicit_version=0 show_help() { cat << EOF install --prefix /usr/local Options: --prefix/-P: base path where files will be deployed (default: /usr/local if root, ~/.local otherwise) --version/-V: release tag to install (default: ${LEGACY_VERSION} for v1, ${V2_VERSION} for v2). The install path is chosen from the tag prefix: 1.x → v1, anything else → v2. --v2: install the v2 Go release instead of the legacy v1 shell scripts. Forces the v2 install path even if --version points at a 1.x tag. --no-color: disable color formatting --help/-h: show this message -v/--verbose: show more verbosity Requires: tar plus either curl or wget. The v2 path additionally needs linux-amd64 or linux-arm64 (matching the published release artefacts). To uninstall, use the companion ./uninstall script. EOF } while [ $# -gt 0 ]; do case $1 in -h | --help) show_help exit 0 ;; -v | --verbose) verbose=1 shift ;; --no-color) no_color=1 shift ;; --v2) force_v2=1 shift ;; -P | --prefix) if [ -n "${2:-}" ]; then prefix="$2" shift 2 else show_help exit 1 fi ;; -V | --version) if [ -n "${2:-}" ]; then VERSION="$2" explicit_version=1 shift 2 else show_help exit 1 fi ;; *) printf >&2 "Error: unknown argument %s\n" "$1" show_help exit 1 ;; esac done # If --v2 was passed without an explicit --version, swap to the v2 # default so the banner and any error messages name the right release. if [ "${force_v2}" -eq 1 ] && [ "${explicit_version}" -ne 1 ]; then VERSION="${V2_VERSION}" fi # Dispatch: v1 by default, v2 if the tag is 2.x or --v2 was passed. install_v1=1 case "${VERSION}" in 1.*) ;; *) install_v1=0 ;; esac if [ "${force_v2}" -eq 1 ]; then install_v1=0 fi set -o errexit set -o nounset BOLD_GREEN="" BOLD_RED="" CLEAR="" if [ -t 0 ] && [ -t 1 ] && [ "${no_color}" -ne 1 ]; then BOLD_GREEN='\033[1;32m' BOLD_RED='\033[1;31m' CLEAR='\033[0m' fi if [ "${verbose}" -ne 0 ]; then set -o xtrace fi if [ -z "${prefix}" ]; then prefix="/usr/local" if [ "$(id -u)" -ne 0 ]; then prefix="${HOME}/.local" fi fi bindir="${prefix}/bin" mandir="${prefix}/share/man/man1" bashdir="${prefix}/share/bash-completion/completions" zshdir="${prefix}/share/zsh/site-functions" icondir="${prefix}/share/icons/hicolor" icon_sizes="16 22 24 32 36 48 64 72 96 128 256" if command -v curl > /dev/null 2>&1; then download="curl -sLfo" elif command -v wget > /dev/null 2>&1; then download="wget -qO" else printf >&2 "Error: need either curl or wget on PATH\n" exit 1 fi if ! command -v tar > /dev/null 2>&1; then printf >&2 "Error: need tar on PATH\n" exit 1 fi # Arch detection is only needed for the v2 pre-built binary path. arch="posix" if [ "${install_v1}" -ne 1 ]; then case "$(uname -m)" in x86_64 | amd64) arch="amd64" ;; aarch64 | arm64) arch="arm64" ;; *) printf >&2 "Error: unsupported architecture %s (release artefacts are linux-amd64 and linux-arm64)\n" "$(uname -m)" exit 1 ;; esac fi if [ "${install_v1}" -eq 1 ]; then printf >&2 "%b Installing distrobox v1 %s (legacy) into %s%b\n" \ "${BOLD_GREEN}" "${VERSION}" "${prefix}" "${CLEAR}" else printf >&2 "%b Installing distrobox v2 %s for linux-%s into %s%b\n" \ "${BOLD_GREEN}" "${VERSION}" "${arch}" "${prefix}" "${CLEAR}" fi tmp="$(mktemp -d)" # shellcheck disable=SC2064 trap "rm -rf '${tmp}'" EXIT cd "${tmp}" # Both paths need the source tarball: v1 ships everything from it # (the split scripts, the helpers, the completions, the man pages, # the icons); v2 needs it for the helpers, completions, man pages, # and icons. The v2 Go binary itself comes from the bundled release # artefact in the v2 branch below. printf >&2 "%b Downloading source tarball...%b\n" "${BOLD_RED}" "${CLEAR}" # shellcheck disable=SC2086 ${download} src.tar.gz "https://github.com/${REPO}/archive/refs/tags/${VERSION}.tar.gz" mkdir -p src tar -xzf src.tar.gz -C src --strip-components=1 if ! install -d "${bindir}" "${mandir}" "${bashdir}" "${zshdir}"; then printf >&2 "Do you have permission to write to %s?\n" "${prefix}" exit 1 fi if [ "${install_v1}" -eq 1 ]; then # v1 ships as split POSIX shell scripts at the tarball root: # the main `distrobox` plus per-subcommand wrappers # (distrobox-create, distrobox-enter, …) and the in-container # helpers (distrobox-init/export/host-exec). Install every # `distrobox*` script in one pass — that's exactly the v1 # release artefact set. for file in src/distrobox*; do install -m 0755 "${file}" "${bindir}/" done # v1 ships per-subcommand bash and zsh completions. Install all # of them. if [ -d src/completions/bash ]; then for file in src/completions/bash/*; do install -m 0644 "${file}" "${bashdir}/" done fi if [ -d src/completions/zsh ]; then for file in src/completions/zsh/*; do install -m 0644 "${file}" "${zshdir}/" done fi else # v2 path. The release artefact is a tarball (per #2141); extract # it to get the pre-built Go binary. printf >&2 "%b Downloading bundled binary...%b\n" "${BOLD_RED}" "${CLEAR}" # shellcheck disable=SC2086 ${download} bundle.tar.gz "https://github.com/${REPO}/releases/download/${VERSION}/distrobox-linux-${arch}.tar.gz" mkdir -p bundle tar -xzf bundle.tar.gz -C bundle # Main binary from the bundled release artefact. install -m 0755 bundle/distrobox "${bindir}/distrobox" # In-container helper scripts. The Go binary embeds these and # would extract them at first use, but shipping them here puts # them on PATH next to the binary so the runtime detection # short-circuits and skips extraction entirely. Same paths v1 # used, which also means containers created by v1 keep finding # a working bind-mount source. install -m 0755 src/internal/inside-distrobox/assets/distrobox-init "${bindir}/distrobox-init" install -m 0755 src/internal/inside-distrobox/assets/distrobox-export "${bindir}/distrobox-export" install -m 0755 src/internal/inside-distrobox/assets/distrobox-host-exec "${bindir}/distrobox-host-exec" # v1 subcommand compatibility: argv[0] dispatch via symlinks. # Users (and desktop entries written by v1 distrobox-export) still # invoke `distrobox-enter foo`; the binary routes by basename. for sub in assemble create enter ephemeral generate-entry ls list rm stop upgrade; do ln -sf distrobox "${bindir}/distrobox-${sub}" done # v2 ships a single combined completion per shell. install -m 0644 src/completions/bash/distrobox "${bashdir}/distrobox" install -m 0644 src/completions/zsh/_distrobox "${zshdir}/_distrobox" fi # Man pages and icons are common to both versions. if [ -d src/man ]; then for file in src/man/man1/*; do install -m 0644 "${file}" "${mandir}/" done fi if [ -e src/icons/terminal-distrobox-icon.svg ]; then install -d "${icondir}/scalable/apps" install -m 0644 src/icons/terminal-distrobox-icon.svg "${icondir}/scalable/apps/" for sz in ${icon_sizes}; do install -d "${icondir}/${sz}x${sz}/apps" install -m 0644 "src/icons/hicolor/${sz}x${sz}/apps/terminal-distrobox-icon.png" \ "${icondir}/${sz}x${sz}/apps/" done fi printf >&2 "%b Installation successful!%b\n" "${BOLD_GREEN}" "${CLEAR}" printf >&2 "%b distrobox is at %s%b\n" "${CLEAR}" "${bindir}/distrobox" "${CLEAR}" if ! echo "${PATH}" | grep -q "${bindir}"; then printf >&2 "%b Note:%b add %s to your \$PATH\n" "${BOLD_RED}" "${CLEAR}" "${bindir}" fi