#!/bin/sh set -eu cd -- "$(dirname "$0")/../sub/lib" . ./log.sh . ./flag.sh . ./release.sh cd - >/dev/null help() { arg0="$0" if [ "$0" = sh ]; then arg0="curl -fsSL https://d2lang.com/install.sh | sh -s --" fi cat < but the release archive in ~/.cache/d2/release will remain. --uninstall: Uninstall the installed version of d2. The --method and --prefix flags must be the same as for installation. i.e if you used --method standalone you must again use --method standalone for uninstallation. With detect, the install script will try to use the OS package manager to uninstall instead. All downloaded archives are cached into ~/.cache/d2/release. use \$XDG_CACHE_HOME to change path of the cached assets. Release archives are unarchived into /usr/local/lib/d2/d2- note: Deleting the unarchived releases will cause --uninstall to stop working. You can rerun install.sh to update your version of D2. install.sh will avoid reinstalling if the installed version is the latest unless --force is passed. EOF } main() { if [ -n "${DEBUG-}" ]; then set -x fi METHOD=standalone while :; do flag_parse "$@" case "$FLAG" in h|help) help return 0 ;; dry-run) flag_noarg && shift "$FLAGSHIFT" DRY_RUN=1 ;; version) flag_nonemptyarg && shift "$FLAGSHIFT" VERSION=$FLAGARG ;; tala) shift "$FLAGSHIFT" TALA=${FLAGARG:-latest} ;; edge) flag_noarg && shift "$FLAGSHIFT" EDGE=1 echoerr "$FLAGRAW is currently unimplemented" return 1 ;; method) flag_nonemptyarg && shift "$FLAGSHIFT" METHOD=$FLAGARG echoerr "$FLAGRAW is currently unimplemented" return 1 ;; prefix) flag_nonemptyarg && shift "$FLAGSHIFT" export PREFIX=$FLAGARG ;; force) flag_noarg && shift "$FLAGSHIFT" FORCE=1 ;; uninstall) flag_noarg && shift "$FLAGSHIFT" UNINSTALL=1 ;; '') shift "$FLAGSHIFT" break ;; *) flag_errusage "unrecognized flag $FLAGRAW" ;; esac done if [ $# -gt 0 ]; then flag_errusage "no arguments are accepted" fi REPO=${REPO:-terrastruct/d2} PREFIX=${PREFIX:-/usr/local} OS=$(os) ARCH=$(arch) CACHE_DIR=$(cache_dir) mkdir -p "$CACHE_DIR" INSTALL_DIR=$PREFIX/lib/d2 if [ -n "${UNINSTALL-}" ]; then uninstall return 0 fi VERSION=${VERSION:-latest} if [ "$VERSION" = latest ]; then header "fetching latest release info" fetch_release_info fi install } install() { install_d2 if [ "${TALA-}" ]; then # Run in subshell to avoid overwriting VERSION. ( install_tala ) fi COLOR=2 header success log "d2-$VERSION-$OS-$ARCH has been successfully installed into $PREFIX" if ! echo "$PATH" | grep -qF "$PREFIX/bin"; then logcat >&2 </dev/null; then INSTALLED_VERSION="$(d2 version)" if [ ! "${FORCE-}" -a "$VERSION" = "$INSTALLED_VERSION" ]; then log "skipping installation as version $VERSION is already installed." return 0 fi log "uninstalling $INSTALLED_VERSION to install $VERSION" if ! uninstall_d2; then warn "failed to uninstall $INSTALLED_VERSION" fi fi header "installing d2-$VERSION" install_standalone_d2 } install_standalone_d2() { ARCHIVE="d2-$VERSION-$OS-$ARCH.tar.gz" log "installing standalone release $ARCHIVE from github" fetch_release_info asset_line=$(cat "$RELEASE_INFO" | grep -n "$ARCHIVE" | cut -d: -f1 | head -n1) asset_url=$(sed -n $((asset_line-3))p "$RELEASE_INFO" | sed 's/^.*: "\(.*\)",$/\1/g') fetch_gh "$asset_url" "$CACHE_DIR/$ARCHIVE" 'application/octet-stream' sh_c="sh_c" if ! is_prefix_writable; then sh_c="sudo_sh_c" fi "$sh_c" tar -C "$INSTALL_DIR" -xzf "$CACHE_DIR/$ARCHIVE" "$sh_c" sh -c "'cd \"$INSTALL_DIR/d2-$VERSION\" && make install PREFIX=\"$PREFIX\"'" } install_tala() { install_standalone_tala } install_standalone_tala() { REPO="${REPO_TALA:-terrastruct/TALA}" VERSION=$TALA RELEASE_INFO= fetch_release_info ARCHIVE="tala-$VERSION-$OS-$ARCH.tar.gz" log "installing standalone release $ARCHIVE from github" asset_line=$(cat "$RELEASE_INFO" | grep -n "$ARCHIVE" | cut -d: -f1 | head -n1) asset_url=$(sed -n $((asset_line-3))p "$RELEASE_INFO" | sed 's/^.*: "\(.*\)",$/\1/g') fetch_gh "$asset_url" "$CACHE_DIR/$ARCHIVE" 'application/octet-stream' sh_c="sh_c" if ! is_prefix_writable; then sh_c="sudo_sh_c" fi "$sh_c" tar -C "$INSTALL_DIR" -xzf "$CACHE_DIR/$ARCHIVE" "$sh_c" sh -c "'cd \"$INSTALL_DIR/tala-$VERSION\" && make install PREFIX=\"$PREFIX\"'" } uninstall() { if ! command -v d2 >/dev/null; then echoerr "no version of d2 installed" return 1 fi INSTALLED_VERSION="$(d2 --version)" if ! uninstall_d2; then echoerr "failed to uninstall $INSTALLED_VERSION" return 1 fi if [ "${TALA-}" ]; then if ! command -v d2plugin-tala >/dev/null; then echoerr "no version of tala installed" return 1 fi INSTALLED_VERSION="$(d2plugin-tala --version)" if ! uninstall_tala; then echoerr "failed to uninstall tala $INSTALLED_VERSION" return 1 fi fi return 0 } uninstall_d2() { header "uninstalling d2-$INSTALLED_VERSION" uninstall_standalone_d2 } uninstall_standalone_d2() { log "uninstalling standalone release of d2-$INSTALLED_VERSION" if [ ! -e "$INSTALL_DIR/d2-$INSTALLED_VERSION" ]; then echoerr "missing standalone install release directory $INSTALL_DIR/d2-$INSTALLED_VERSION" return 1 fi sh_c="sh_c" if ! is_prefix_writable; then sh_c="sudo_sh_c" fi "$sh_c" sh -c "'cd \"$INSTALL_DIR/d2-$INSTALLED_VERSION\" && make uninstall PREFIX=\"$PREFIX\"'" "$sh_c" rm -rf "$INSTALL_DIR/d2-$INSTALLED_VERSION" } uninstall_tala() { uninstall_standalone_tala } uninstall_standalone_tala() { log "uninstalling standalone release tala-$INSTALLED_VERSION" if [ ! -e "$INSTALL_DIR/tala-$INSTALLED_VERSION" ]; then echoerr "missing standalone install release directory $INSTALL_DIR/tala-$INSTALLED_VERSION" return 1 fi sh_c="sh_c" if ! is_prefix_writable; then sh_c="sudo_sh_c" fi "$sh_c" sh -c "'cd \"$INSTALL_DIR/tala-$INSTALLED_VERSION\" && make uninstall PREFIX=\"$PREFIX\"'" "$sh_c" rm -rf "$INSTALL_DIR/tala-$INSTALLED_VERSION" } is_prefix_writable() { sh_c "mkdir -p '$INSTALL_DIR' 2>/dev/null" || true # The reason for checking whether bin is writable specifically is that on macOS you have # /usr/local owned by root but you don't need root to write to its subdirectories which # is all we want to do. if [ ! -w "$PREFIX/bin" ]; then return 0 fi } cache_dir() { if [ -n "${XDG_CACHE_HOME-}" ]; then echo "$XDG_CACHE_HOME/d2/release" elif [ -n "${HOME-}" ]; then echo "$HOME/.cache/d2/release" else echo "/tmp/d2-cache/release" fi } fetch_release_info() { if [ -n "${RELEASE_INFO-}" ]; then return 0 fi log "fetching info on $VERSION version of $REPO" RELEASE_INFO=$(mktemp -d)/release-info.json if [ "$VERSION" = latest ]; then release_info_url="https://api.github.com/repos/$REPO/releases/$VERSION" else release_info_url="https://api.github.com/repos/$REPO/releases/tags/$VERSION" fi fetch_gh "$release_info_url" "$RELEASE_INFO" \ 'application/json' VERSION=$(cat "$RELEASE_INFO" | grep -m1 tag_name | sed 's/^.*: "\(.*\)",$/\1/g') } curl_gh() { sh_c curl -fL ${GITHUB_TOKEN+"-H \"Authorization: Bearer \$GITHUB_TOKEN\""} "$@" } fetch_gh() { url=$1 file=$2 accept=$3 if [ -e "$file" ]; then log "reusing $file" return fi curl_gh -#o "$file.inprogress" -C- -H "'Accept: $accept'" "$url" sh_c mv "$file.inprogress" "$file" } main "$@"