/ install.sh
install.sh
  1  #!/usr/bin/env bash
  2  set -e
  3  
  4  # Install Codex on Linux, macOS, and Windows (msys2)
  5  
  6  # Variables
  7  VERSION=${VERSION:-latest}
  8  CIRDL=${CIRDL:-false}
  9  INSTALL_DIR=${INSTALL_DIR:-/usr/local/bin}
 10  CODEX_ARCHIVE_PREFIX="codex"
 11  CIRDL_ARCHIVE_PREFIX="cirdl"
 12  CODEX_BINARY_PREFIX="codex"
 13  CIRDL_BINARY_PREFIX="cirdl"
 14  WINDOWS_LIBS=${WINDOWS_LIBS:-false}
 15  WINDOWS_LIBS_LIST="libstdc++-6.dll libgomp-1.dll libgcc_s_seh-1.dll libwinpthread-1.dll"
 16  BASE_URL=${BASE_URL:-https://github.com/codex-storage/nim-codex}
 17  API_BASE_URL="https://api.github.com/repos/codex-storage/nim-codex"
 18  BRANCH="${BRANCH:-master}"
 19  TEMP_DIR="${TEMP_DIR:-.}"
 20  PROGRESS_MARK="\033[0;36m\u2022\033[0m"
 21  PASS_MARK="\033[0;32m\u2714\033[0m"
 22  FAIL_MARK="\033[0;31m\u2718\033[0m"
 23  SCRIPT_URL="${SCRIPT_URL:-https://get.codex.storage/install.sh}"
 24  
 25  # Debug
 26  if [[ "${DEBUG:-false}" == "true" ]]; then
 27    echo -e "\n \e[33mVariables:\e[0m"
 28    echo "  VERSION: ${VERSION}"
 29    echo "  CIRDL: ${CIRDL}"
 30    echo "  INSTALL_DIR: ${INSTALL_DIR}"
 31    echo "  BRANCH: ${BRANCH}"
 32    echo "  TEMP_DIR: ${TEMP_DIR}"
 33    echo "  BASE_URL: ${BASE_URL}"
 34    echo "  SCRIPT_URL: ${SCRIPT_URL}"
 35  fi
 36  
 37  # Help
 38  if [[ $1 == *"help"* ]] ; then
 39    COMMAND="curl -s ${SCRIPT_URL}"
 40    echo -e "
 41    \e[33mInstall Codex\e[0m\n
 42    \e[33mUsage:\e[0m
 43      ${COMMAND} | bash
 44      ${COMMAND} | VERSION=0.1.7 bash
 45      ${COMMAND} | VERSION=0.1.7 CIRDL=true bash
 46      ${COMMAND} | bash -s help
 47  
 48    \e[33mVariables:\e[0m
 49      - VERSION=0.1.7                         - codex and cird version to install
 50      - CIRDL=true                            - install cirdl
 51      - INSTALL_DIR=/usr/local/bin            - directory to install binaries
 52      - WINDOWS_LIBS=true                     - download and install archive with libs for windows
 53      - BASE_URL=https://builds.codex.storage - custom base URL for binaries downloading
 54      - BRANCH=fix/custom-branch              - custom branch builds
 55    "
 56    exit 0
 57  fi
 58  
 59  # Show
 60  show_start() {
 61    echo -e "\n \e[33m${1}\e[0m\n"
 62  }
 63  
 64  show_progress() {
 65    echo -e " ${PROGRESS_MARK} ${1}"
 66  }
 67  
 68  show_pass() {
 69    echo -e "\r\e[${TRIM:-1}A\e[0K ${PASS_MARK} ${1}"
 70    unset TRIM
 71  }
 72  
 73  show_fail() {
 74    echo -e "\r\e[1A\e[0K ${FAIL_MARK} ${1}"
 75    [[ -n "${2}" ]] && echo -e "\e[31m \n Error: ${2}\e[0m\n"
 76    exit 1
 77  }
 78  
 79  show_end() {
 80    echo -e "\n\e[32m ${1}\e[0m\n"
 81  }
 82  
 83  # Start
 84  show_start "Installing Codex..."
 85  
 86  # Version
 87  message="Compute version"
 88  show_progress "${message}"
 89  if [[ "${BASE_URL}" == *"https://github.com/"* ]]; then
 90    if [[ "${VERSION}" == "latest" ]]; then
 91      VERSION=$(curl -s "${API_BASE_URL}/releases/latest" | grep tag_name | cut -d '"' -f 4)
 92    else
 93      VERSION="v${VERSION}"
 94    fi
 95  else
 96    if [[ "${BRANCH}" == "releases" ]]; then
 97      if [[ "${VERSION}" == "latest" ]]; then
 98        VERSION=$(curl -s "${BASE_URL}/${BRANCH}/latest")
 99      else
100        VERSION="v${VERSION}"
101      fi
102    else
103      VERSION="${BRANCH/\//-}"
104    fi
105  fi
106  [[ $? -eq 0 ]] && show_pass "${message}" || show_fail "${message}"
107  
108  # Archives and binaries
109  message="Compute archives and binaries names"
110  show_progress "${message}"
111  [[ "${CIRDL}" == "true" ]] && ARCHIVES=("${CODEX_ARCHIVE_PREFIX}" "${CIRDL_ARCHIVE_PREFIX}") || ARCHIVES=("${CODEX_ARCHIVE_PREFIX}")
112  [[ "${CIRDL}" == "true" ]] && BINARIES=("${CODEX_BINARY_PREFIX}" "${CIRDL_BINARY_PREFIX}") || BINARIES=("${CODEX_BINARY_PREFIX}")
113  show_pass "${message}"
114  
115  # Get the current OS
116  message="Checking the current OS"
117  show_progress "${message}"
118  case "$(uname -s)" in
119    Linux*)               OS="linux"                                          ;;
120    Darwin*)              OS="darwin"                                         ;;
121    CYGWIN*|MINGW*|MSYS*) OS="windows"                                        ;;
122    *)                    show_fail "${message}" "Unsupported OS $(uname -s)" ;;
123  esac
124  [[ $? -eq 0 ]] && show_pass "${message}" || show_fail "${message}"
125  
126  # Get the current architecture
127  message="Checking the current architecture"
128  show_progress "${message}"
129  case "$(uname -m)" in
130    x86_64|amd64)  ARCHITECTURE="amd64"                                           ;;
131    arm64|aarch64) ARCHITECTURE="arm64"                                           ;;
132    *)             show_fail "${message}" "Unsupported architecture: $(uname -m)" ;;
133  esac
134  [[ $? -eq 0 ]] && show_pass "${message}" || show_fail "${message}"
135  
136  # Not supported
137  if [[ "${OS}" == "windows" && "${ARCHITECTURE}" == "arm64" ]]; then
138    show_fail "${message}" "Windows ${ARCHITECTURE} is not supported at the moment"
139  fi
140  
141  # Prerequisites
142  message="Checking prerequisites"
143  show_progress "${message}"
144  if [[ ("${OS}" != "windows") ]]; then
145    $(command -v tar &> /dev/null) || show_fail "${message}" "Please install tar to continue installation"
146  fi
147  show_pass "${message}"
148  
149  # Archive and binaries names
150  if [[ "$OS" == "windows" ]]; then
151    [[ "${WINDOWS_LIBS}" == "true" ]] && ARCHIVE_SUFFIX="${VERSION}-${OS}-${ARCHITECTURE}-libs.zip" || ARCHIVE_SUFFIX="${VERSION}-${OS}-${ARCHITECTURE}.zip"
152    BINARY_SUFFIX="${VERSION}-${OS}-${ARCHITECTURE}"
153  else
154    ARCHIVE_SUFFIX="${VERSION}-${OS}-${ARCHITECTURE}.tar.gz"
155    BINARY_SUFFIX="${VERSION}-${OS}-${ARCHITECTURE}"
156  fi
157  
158  # Download
159  for ARCHIVE in "${ARCHIVES[@]}"; do
160    ARCHIVE_NAME="${ARCHIVE}-${ARCHIVE_SUFFIX}"
161  
162    for FILE in "${ARCHIVE_NAME}" "${ARCHIVE_NAME}.sha256"; do
163      if [[ "${BASE_URL}" == *"https://github.com/"* ]]; then
164        DOWNLOAD_URL="${BASE_URL}/releases/download/${VERSION}/${FILE}"
165      else
166        if [[ "${BRANCH}" == "releases" ]]; then
167          DOWNLOAD_URL="${BASE_URL}/${BRANCH}/${VERSION}/${FILE}"
168        elif [[ "${BRANCH}" == "master" ]]; then
169          DOWNLOAD_URL="${BASE_URL}/${BRANCH}/${FILE}"
170        else
171          DOWNLOAD_URL="${BASE_URL}/branches/${VERSION}/${FILE}"
172        fi
173      fi
174  
175      message="Downloading ${FILE}"
176      show_progress "${message}"
177      http_code=$(curl --write-out "%{http_code}" --connect-timeout 5 --retry 5 -sL "${DOWNLOAD_URL}" -o "${TEMP_DIR}/${FILE}")
178      [[ "${http_code}" -eq 200 ]] && show_pass "${message}" || show_fail "${message}" "Failed to download ${DOWNLOAD_URL}"
179    done
180  done
181  
182  # Checksum
183  for ARCHIVE in "${ARCHIVES[@]}"; do
184    ARCHIVE_NAME="${ARCHIVE}-${ARCHIVE_SUFFIX}"
185    message="Verifying checksum for ${ARCHIVE_NAME}"
186    show_progress "${message}"
187  
188    EXPECTED_SHA256=$(cat "${TEMP_DIR}/${ARCHIVE_NAME}.sha256" | cut -d' ' -f1)
189    if [[ "${OS}" == "darwin" ]]; then
190      ACTUAL_SHA256=$(shasum -a 256 "${TEMP_DIR}/${ARCHIVE_NAME}" | cut -d ' ' -f 1)
191    else
192      ACTUAL_SHA256=$(sha256sum "${TEMP_DIR}/${ARCHIVE_NAME}" | cut -d ' ' -f 1)
193    fi
194  
195    if [[ "$ACTUAL_SHA256" == "$EXPECTED_SHA256" ]]; then
196      show_pass "${message}"
197    else
198      show_fail "${message}" "Checksum verification failed for ${ARCHIVE_NAME}. Expected: $EXPECTED_SHA256, Got: $ACTUAL_SHA256"
199    fi
200  done
201  
202  # Extract
203  for ARCHIVE in "${ARCHIVES[@]}"; do
204    ARCHIVE_NAME="${ARCHIVE}-${ARCHIVE_SUFFIX}"
205  
206    message="Extracting ${ARCHIVE_NAME}"
207    show_progress "${message}"
208  
209    if [[ "${OS}" == "windows" ]]; then
210      if unzip -v &> /dev/null; then
211        unzip -q -o "${TEMP_DIR}/${ARCHIVE_NAME}" -d "${TEMP_DIR}"
212        [[ $? -ne 0 ]] && show_fail "${message}"
213      else
214        C:/Windows/system32/tar.exe -xzf "${TEMP_DIR}/${ARCHIVE_NAME}" -C "${TEMP_DIR}"
215        [[ $? -ne 0 ]] && show_fail "${message}"
216      fi
217    else
218      tar -xzf "${TEMP_DIR}/${ARCHIVE_NAME}" -C "${TEMP_DIR}"
219      [[ $? -ne 0 ]] && show_fail "${message}"
220    fi
221    show_pass "${message}"
222  done
223  
224  # Install
225  for BINARY in "${BINARIES[@]}"; do
226    BINARY_NAME="${BINARY}-${BINARY_SUFFIX}"
227    INSTALL_PATH="${INSTALL_DIR}/${BINARY}"
228  
229    # Install
230    message="Installing ${BINARY_NAME} to ${INSTALL_PATH}"
231    show_progress "${message}"
232    [[ -d "${INSTALL_PATH}" ]] && show_fail "${message}" "Installation path ${INSTALL_PATH} is a directory"
233    if ! (mkdir -p "${INSTALL_DIR}" && install -m 755 "${TEMP_DIR}/${BINARY_NAME}" "${INSTALL_PATH}") 2> /dev/null; then
234      $(sudo -n true 2>/dev/null) || TRIM=2
235      sudo mkdir -p "${INSTALL_DIR}" && sudo install -m 755 "${TEMP_DIR}/${BINARY_NAME}" "${INSTALL_PATH}"
236      [[ $? -ne 0 ]] && show_fail "${message}"
237    fi
238    show_pass "${message}"
239  done
240  
241  # Windows libs
242  if [[ "${OS}" == "windows" && "${WINDOWS_LIBS}" == "true" ]]; then
243    message="Copy libs to ${MINGW_PREFIX}/bin"
244    show_progress "${message}"
245    for LIB in ${WINDOWS_LIBS_LIST}; do
246      mv "${TEMP_DIR}/${LIB}" "${MINGW_PREFIX}/bin"
247    done
248    [[ $? -eq 0 ]] && show_pass "${message}" || show_fail "${message}"
249  fi
250  
251  # Cleanup
252  message="Cleanup"
253  show_progress "${message}"
254  for BINARY in "${BINARIES[@]}"; do
255    ARCHIVE_NAME="${BINARY}-${BINARY_SUFFIX}"
256    rm -f "${TEMP_DIR}/${ARCHIVE_NAME}"*
257    [[ $? -ne 0 ]] && show_fail "${message}"
258  done
259  show_pass "${message}"
260  
261  # End
262  show_end "Setup completed successfully!"
263  
264  # Dependencies
265  dependencies=()
266  for BINARY in "${BINARIES[@]}"; do
267    LOCATION="${INSTALL_DIR}/${BINARY}"
268    case "${OS}" in
269      linux)  dependencies+=($(ldd "${LOCATION}" | awk '/not found/ {print $1}'))      ;;
270      darwin) dependencies+=($(otool -L "${LOCATION}" | awk '/not found/ {print $1}')) ;;
271    esac
272  done
273  
274  if [[ ${#dependencies[@]} -ne 0 ]]; then
275    echo -e " Please inatall the following dpependencies:
276    ${dependencies[@]}\n"
277  fi
278  
279  # Path
280  if [[ "${INSTALL_DIR}" != "." && "${PATH}" != *"${INSTALL_DIR}"* ]]; then
281    echo -e " Note: Please add install directory '"${INSTALL_DIR}"' to your PATH\n"
282  fi