Radish alpha
r
rad:z371PVmDHdjJucejRoRYJcDEvD5pp
Radicle website including documentation and guides
Radicle
Git
radicle.xyz › install
#!/bin/sh
#
# Radicle installation script.
#
set -e

# SSH signing key for the release archives. This is currently cloudhead and fintan's keys.
# FIXME: Technically, there should be a release signing key, with a shamir threshold of > 1, with the secret encrypted by something like SOPS.
CLOUDHEAD="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL460KIEccS4881p7PPpiiQBsxF+H5tgC6De6crw9rbU"
FINTAN="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFsaRqAJ1r6bBFwlcWzJKN7DdjItQDumCNc0wqw6Dvk"
LORENZ="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFhK7CqgIIbSthoNn8ea32krOnMzC807Z+PpBkR2YOVj"

url() {
  echo "https://files.radicle.dev/releases/$1/radicle-$2.tar.xz"
}

info() {
  printf "\033[36m$*\033[0m\n"
}

warn() {
  printf "\033[33m$*\033[0m\n"
}

rad_home() {
  if command -v rad >/dev/null 2>&1; then
    rad path || true
  fi
}

is_authed() {
  RAD_HOME=$(rad_home)

  if [ -n "$RAD_HOME" ] && [ -f "$RAD_HOME/keys/radicle.pub" ]; then
    return 0
  else
    return 1
  fi
}

success() {
  version="$1"

  printf "\033[32m✓\033[0m Radicle \033[2m$1\033[0m was installed successfully.\n"

  RAD_HOME=$(rad_home)

  if [ -n "$RAD_HOME" ] && [ -S "$RAD_HOME/node/control.sock" ];  then
    printf "\n"
    printf "Please restart your node to complete the upgrade.\n"
  fi
}

error() {
  printf "\033[31merror\033[0m: $*\n" >&2
}

fatal() {
  error "$@"
  exit 1
}

usage() {
  echo "Usage"
  echo
  echo "  $0 [<options>]"
  echo
  echo "  This script will install the Radicle binaries under '$RAD_PATH'".
  echo "  To change the location, set \$RAD_PATH to a different directory."
  echo
  echo "  Your Radicle home is set to '$RAD_HOME'."
  echo "  To change it, set \$RAD_HOME to a different directory."
  echo
  echo "Options"
  echo
  echo "  --no-modify-path    Do not modify the PATH environment variable"
  echo "  --version=VERSION   Install the given version of Radicle (default: latest)"
  echo "  --prefix=PATH       Radicle install prefix (default: ~/.radicle)"
  echo "  --help, -h          Show this help message and exit"
  echo
  echo "Environment"
  echo
  echo "  RAD_HOME            Radicle home directory"
}

target() {
  TARGET=""

  case "$(uname)/$(uname -m)" in
  Darwin/arm64)
    TARGET="aarch64-apple-darwin" ;;
  Darwin/x86_64)
    TARGET="x86_64-apple-darwin" ;;
  Linux/arm64|Linux/aarch64)
    TARGET="aarch64-unknown-linux-musl" ;;
  Linux/x86_64)
    TARGET="x86_64-unknown-linux-musl" ;;
  *)
    fatal "Your operating system is currently unsupported. Sorry!" ;;
  esac
  echo $TARGET
}

in_path() {
  IFS=":"

  for dir in $PATH; do
    if [ "$dir" = "$1" ]; then
      return 0 # The path is in $PATH
    fi
  done

  return 1 # The path is not in $PATH
}

get_started() {
  printf "\n"
  success "$@"

  if ! is_authed; then
    printf "\n"
    printf "Get started by creating your Radicle key pair with \033[35m\`rad auth\`\033[0m.\n"
  fi
}

verify() {
  archive="$1"
  signers="$(dirname $archive)/signers"
  # Add the signer key to the allowed signers file we pass to ssh-keygen.
  printf "radicle $CLOUDHEAD\n" > $signers
  printf "radicle $FINTAN\n" >> $signers
  printf "radicle $LORENZ\n" >> $signers

  # Verify that `$archive` was signed by a key in `$signers`, identified by the
  # pattern "*@radicle.dev", using the signature in `$archive.sig`.
  ssh-keygen -Y verify -f $signers -I "radicle" -n file -s "$archive.sig" < "$archive" || fatal "Invalid signature for $archive"
}

main() {
  PREFIX=${RAD_HOME:-"$HOME/.radicle"}
  SHELL_PATH=${SHELL:-"/bin/sh"}
  NO_MODIFY_PATH=false
  VERSION=latest

  if [ -n "$RAD_PATH" ]; then
    fatal "RAD_PATH is no longer supported; Use '--prefix' instead"
  fi

  if ! command -v tar >/dev/null 2>&1; then
    fatal "The 'tar' tool is required to extract the archive; please install 'tar' and try again"
  fi

  if ! command -v xz >/dev/null 2>&1; then
    fatal "The 'xz' tool is required to extract the archive; please install 'xz' or 'xz-utils' and try again"
  fi

  if ! command -v curl >/dev/null 2>&1; then
    fatal "The 'curl' tool is required to download the archive; please install 'curl' and try again"
  fi

  if ! command -v ssh-keygen >/dev/null 2>&1; then
    fatal "The 'ssh-keygen' tool is required to verify the archive; please install the 'openssh' and try again"
  fi

  while :; do
    case "$1" in
      --no-modify-path)
        NO_MODIFY_PATH=true
        ;;
      --prefix=*)
        PREFIX=${1#*=}
        ;;
      --version=*)
        VERSION=${1#*=}
        ;;
      -h|--help)
        usage
        exit 0 ;;
      -*)
        error "Unrecognized argument '$1'"
        echo ; usage ; exit 1 ;;
      *)
        break ;;
    esac
    shift
  done

  if [ -z "$VERSION" ]; then
    fatal "Empty version string; use --version=VERSION"
  fi

  if [ -z "$PREFIX" ]; then
    fatal "Empty installation prefix; use --prefix=PATH or set RAD_HOME"
  fi
  mkdir -p $PREFIX

  echo
  echo "👾 Welcome to Radicle"
  echo

  # Where to install binaries.
  RAD_PATH=$PREFIX/bin

  info "Detecting operating system..."
  TARGET=$(target)
  ARCHIVE="$(mktemp -d)/radicle-$TARGET.tar.xz" # Nb. `-d` must be used on BSDs.
  URL="$(url "$VERSION" "$TARGET")"

  info "Downloading $URL..."
  curl --proto '=https' --fail --tlsv1.2 -# -L "$URL"     -o "$ARCHIVE"     || fatal "Failed to fetch $URL" # Nb. `--tlsv1.3` is not supported on macOS
  info "Downloading $URL.sig..."
  curl --proto '=https' --fail --tlsv1.2 -# -L "$URL.sig" -o "$ARCHIVE.sig" || fatal "Failed to fetch $URL.sig"

  info "Verifying $(basename $ARCHIVE)..."
  verify "$ARCHIVE"

  info "Installing Radicle into $PREFIX..."
  tar -xJf "$ARCHIVE" --strip-components=1 -C "$PREFIX"

  chmod +x \
    $RAD_PATH/radicle-node \
    $RAD_PATH/rad \
    $RAD_PATH/git-remote-rad

  if ! command -v git >/dev/null 2>&1; then
    warn
    warn "Warning: a Git installation was not detected on your system."
    warn "Warning: please install Git for Radicle to work correctly."
  fi
  version="$($RAD_PATH/rad --version | cut -f2 -d' ' -)"

  # If radicle is not in $PATH, add it here.
  if $NO_MODIFY_PATH; then
    info "Not modifying shell path variable, as requested."
    get_started $version
  elif in_path $RAD_PATH; then
    info "Radicle is configured in shell already, not modifying."
    get_started $version
  else
    PROFILE=""

    case $SHELL_PATH in
      */zsh)
        PROFILE=$HOME/.zshenv ;;
      */bash)
        PROFILE=$HOME/.bashrc ;;
      */fish)
        PROFILE=$HOME/.config/fish/config.fish ;;
      */ash)
        PROFILE=$HOME/.profile ;;
      */csh)
        PROFILE=$HOME/.cshrc ;;
    esac

    if [ -z "$PROFILE" ]; then
      warn "Warning: unable to update your PATH variable."
      warn "Warning: please manually add $RAD_PATH to your PATH."
      get_started $version
    else
      info "Configuring path variable in ~${PROFILE#$HOME}..."
      echo                                    >> "$PROFILE"
      echo "# Added by Radicle."              >> "$PROFILE"
      echo "export PATH=\"\$PATH:$RAD_PATH\"" >> "$PROFILE"
      echo

      success $version

      if command -v rad >/dev/null 2>&1; then
        EXISTING=$(command -v rad)
        printf "\n"
        warn "Warning: Pre-existing binaries found at $(dirname "$EXISTING")."
        warn "Warning: Installed new binaries in $RAD_PATH."
      fi

      printf "\n"
      printf "Before running Radicle for the first time,\n"
      printf "run \033[34m\`source ~${PROFILE#$HOME}\`\033[0m or open a new terminal.\n"

      if ! is_authed; then
        printf "\n"
        printf "Then, create your Radicle key pair with \033[35m\`rad auth\`\033[0m.\n"
      fi
    fi
  fi
}

main "$@"