/ install
install
  1  #!/bin/sh
  2  #
  3  # Radicle installation script.
  4  #
  5  set -e
  6  
  7  # SSH signing key for the release archives. This is currently cloudhead's key.
  8  SIGNER="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL460KIEccS4881p7PPpiiQBsxF+H5tgC6De6crw9rbU"
  9  
 10  url() {
 11    echo "https://files.radicle.xyz/releases/$1/radicle-$2.tar.xz"
 12  }
 13  
 14  info() {
 15    printf "\033[36m$*\033[0m\n"
 16  }
 17  
 18  warn() {
 19    printf "\033[33m$*\033[0m\n"
 20  }
 21  
 22  rad_home() {
 23    if command -v rad >/dev/null 2>&1; then
 24      rad path || true
 25    fi
 26  }
 27  
 28  is_authed() {
 29    RAD_HOME=$(rad_home)
 30  
 31    if [ -n "$RAD_HOME" ] && [ -f "$RAD_HOME/keys/radicle.pub" ]; then
 32      return 0
 33    else
 34      return 1
 35    fi
 36  }
 37  
 38  success() {
 39    version="$1"
 40  
 41    printf "\033[32m✓\033[0m Radicle \033[2m$1\033[0m was installed successfully.\n"
 42  
 43    RAD_HOME=$(rad_home)
 44  
 45    if [ -n "$RAD_HOME" ] && [ -S "$RAD_HOME/node/control.sock" ];  then
 46      printf "\n"
 47      printf "Please restart your node to complete the upgrade.\n"
 48    fi
 49  }
 50  
 51  error() {
 52    printf "\033[31merror\033[0m: $*\n" >&2
 53  }
 54  
 55  fatal() {
 56    error "$@"
 57    exit 1
 58  }
 59  
 60  usage() {
 61    echo "Usage"
 62    echo
 63    echo "  $0 [<options>]"
 64    echo
 65    echo "  This script will install the Radicle binaries under '$RAD_PATH'".
 66    echo "  To change the location, set \$RAD_PATH to a different directory."
 67    echo
 68    echo "  Your Radicle home is set to '$RAD_HOME'."
 69    echo "  To change it, set \$RAD_HOME to a different directory."
 70    echo
 71    echo "Options"
 72    echo
 73    echo "  --no-modify-path    Do not modify the PATH environment variable"
 74    echo "  --version=VERSION   Install the given version of Radicle (default: latest)"
 75    echo "  --prefix=PATH       Radicle install prefix (default: ~/.radicle)"
 76    echo "  --help, -h          Show this help message and exit"
 77    echo
 78    echo "Environment"
 79    echo
 80    echo "  RAD_HOME            Radicle home directory"
 81  }
 82  
 83  target() {
 84    TARGET=""
 85  
 86    case "$(uname)/$(uname -m)" in
 87    Darwin/arm64)
 88      TARGET="aarch64-apple-darwin" ;;
 89    Darwin/x86_64)
 90      TARGET="x86_64-apple-darwin" ;;
 91    Linux/arm64|Linux/aarch64)
 92      TARGET="aarch64-unknown-linux-musl" ;;
 93    Linux/x86_64)
 94      TARGET="x86_64-unknown-linux-musl" ;;
 95    *)
 96      fatal "Your operating system is currently unsupported. Sorry!" ;;
 97    esac
 98    echo $TARGET
 99  }
100  
101  in_path() {
102    IFS=":"
103  
104    for dir in $PATH; do
105      if [ "$dir" = "$1" ]; then
106        return 0 # The path is in $PATH
107      fi
108    done
109  
110    return 1 # The path is not in $PATH
111  }
112  
113  get_started() {
114    printf "\n"
115    success "$@"
116  
117    if ! is_authed; then
118      printf "\n"
119      printf "Get started by creating your Radicle key pair with \033[35m\`rad auth\`\033[0m.\n"
120    fi
121  }
122  
123  verify() {
124    archive="$1"
125    signers="$(dirname $archive)/signers"
126    # Add the signer key to the allowed signers file we pass to ssh-keygen.
127    printf "cloudhead $SIGNER\n" > $signers
128  
129    # Verify that `$archive` was signed by a key in `$signers`, identified by the
130    # name "cloudhead", using the signature in `$archive.sig`.
131    ssh-keygen -Y verify -f $signers -I cloudhead -n file -s "$archive.sig" < "$archive" || fatal "Invalid signature for $archive"
132  }
133  
134  main() {
135    PREFIX=${RAD_HOME:-"$HOME/.radicle"}
136    SHELL_PATH=${SHELL:-"/bin/sh"}
137    NO_MODIFY_PATH=false
138    VERSION=latest
139  
140    if [ -n "$RAD_PATH" ]; then
141      fatal "RAD_PATH is no longer supported; Use '--prefix' instead"
142    fi
143  
144    if ! command -v tar >/dev/null 2>&1; then
145      fatal "The 'tar' tool is required to extract the archive; please install 'tar' and try again"
146    fi
147  
148    if ! command -v xz >/dev/null 2>&1; then
149      fatal "The 'xz' tool is required to extract the archive; please install 'xz' or 'xz-utils' and try again"
150    fi
151  
152    if ! command -v curl >/dev/null 2>&1; then
153      fatal "The 'curl' tool is required to download the archive; please install 'curl' and try again"
154    fi
155  
156    if ! command -v ssh-keygen >/dev/null 2>&1; then
157      fatal "The 'ssh-keygen' tool is required to verify the archive; please install the 'openssh' and try again"
158    fi
159  
160    while :; do
161      case "$1" in
162        --no-modify-path)
163          NO_MODIFY_PATH=true
164          ;;
165        --prefix=*)
166          PREFIX=${1#*=}
167          ;;
168        --version=*)
169          VERSION=${1#*=}
170          ;;
171        -h|--help)
172          usage
173          exit 0 ;;
174        -*)
175          error "Unrecognized argument '$1'"
176          echo ; usage ; exit 1 ;;
177        *)
178          break ;;
179      esac
180      shift
181    done
182  
183    if [ -z "$VERSION" ]; then
184      fatal "Empty version string; use --version=VERSION"
185    fi
186  
187    if [ -z "$PREFIX" ]; then
188      fatal "Empty installation prefix; use --prefix=PATH or set RAD_HOME"
189    fi
190    mkdir -p $PREFIX
191  
192    echo
193    echo "👾 Welcome to Radicle"
194    echo
195  
196    # Where to install binaries.
197    RAD_PATH=$PREFIX/bin
198  
199    info "Detecting operating system..."
200    TARGET=$(target)
201    ARCHIVE="$(mktemp -d)/radicle-$TARGET.tar.xz" # Nb. `-d` must be used on BSDs.
202    URL="$(url "$VERSION" "$TARGET")"
203  
204    info "Downloading $URL..."
205    curl --proto '=https' --fail --tlsv1.2 -# -L "$URL"     -o "$ARCHIVE"     || fatal "Failed to fetch $URL" # Nb. `--tlsv1.3` is not supported on macOS
206    info "Downloading $URL.sig..."
207    curl --proto '=https' --fail --tlsv1.2 -# -L "$URL.sig" -o "$ARCHIVE.sig" || fatal "Failed to fetch $URL.sig"
208  
209    info "Verifying $(basename $ARCHIVE)..."
210    verify "$ARCHIVE"
211  
212    info "Installing Radicle into $PREFIX..."
213    tar -xJf "$ARCHIVE" --strip-components=1 -C "$PREFIX"
214  
215    chmod +x \
216      $RAD_PATH/radicle-node \
217      $RAD_PATH/rad \
218      $RAD_PATH/git-remote-rad
219  
220    if ! command -v git >/dev/null 2>&1; then
221      warn
222      warn "Warning: a Git installation was not detected on your system."
223      warn "Warning: please install Git for Radicle to work correctly."
224    fi
225    version="$($RAD_PATH/rad --version | cut -f2 -d' ' -)"
226  
227    # If radicle is not in $PATH, add it here.
228    if $NO_MODIFY_PATH; then
229      info "Not modifying shell path variable, as requested."
230      get_started $version
231    elif in_path $RAD_PATH; then
232      info "Radicle is configured in shell already, not modifying."
233      get_started $version
234    else
235      PROFILE=""
236  
237      case $SHELL_PATH in
238        */zsh)
239          PROFILE=$HOME/.zshenv ;;
240        */bash)
241          PROFILE=$HOME/.bashrc ;;
242        */fish)
243          PROFILE=$HOME/.config/fish/config.fish ;;
244        */ash)
245          PROFILE=$HOME/.profile ;;
246        */csh)
247          PROFILE=$HOME/.cshrc ;;
248      esac
249  
250      if [ -z "$PROFILE" ]; then
251        warn "Warning: unable to update your PATH variable."
252        warn "Warning: please manually add $RAD_PATH to your PATH."
253        get_started $version
254      else
255        info "Configuring path variable in ~${PROFILE#$HOME}..."
256        echo                                    >> "$PROFILE"
257        echo "# Added by Radicle."              >> "$PROFILE"
258        echo "export PATH=\"\$PATH:$RAD_PATH\"" >> "$PROFILE"
259        echo
260  
261        success $version
262  
263        if command -v rad >/dev/null 2>&1; then
264          EXISTING=$(command -v rad)
265          printf "\n"
266          warn "Warning: Pre-existing binaries found at $(dirname "$EXISTING")."
267          warn "Warning: Installed new binaries in $RAD_PATH."
268        fi
269  
270        printf "\n"
271        printf "Before running Radicle for the first time,\n"
272        printf "run \033[34m\`source ~${PROFILE#$HOME}\`\033[0m or open a new terminal.\n"
273  
274        if ! is_authed; then
275          printf "\n"
276          printf "Then, create your Radicle key pair with \033[35m\`rad auth\`\033[0m.\n"
277        fi
278      fi
279    fi
280  }
281  
282  main "$@"