From 6bcfa25a1ca3df07fcf91a208deb66ca64f1ddf9 Mon Sep 17 00:00:00 2001 From: "Deavon M. McCaffery" Date: Tue, 24 Nov 2020 03:50:38 +0000 Subject: [PATCH] feat: add support for apple silicon * update prompt-install to detect and handle prompt installation for apple silicon (arm64e) architecture * install homebrew used to manage rosetta 2 installations (x86_64) in /usr/local * install homebrew used to manage native installations (arm64e) in /opt/homebrew * introduce `brew-intel` and `brew-arm` aliases to enable management of both installations regardless of the architecture of the current shell * update `use-shell` to detect arm64e native shells * fix an issue where the PATH variable is reordered by invalid path_helper invocations * normalise and fix areas where the PATH variable is modified * normalise eval invocations (such as completions) * remove completion check for gulp and grunt, which are largely obsolete * fix an issue where it was assumed that gpg was available * add end-to-end tests for Windows 2019 under WSL 1 * add end-to-end tests for all validated linux distributions - create a non-root user - add user to sudoers - install gosu - use gosu to invoke installs and tests under non-root user * update VERSION logic in prompt-install / update to support the `next` branch and any future branches - this should be improved in the future to correctly recommend updates based on semver tags (or the branch/channel used to install prompt) Closes: #66, #69 NOTE: Homebrew, which we rely heavily on, does not yet officially support apple silicon. In addition, very few formulae include bottles (pre-compiled) binaries for the SoC. As a result, most formulae must be compiled from source. Many formulae do not yet successfully compile for apple silicon and so we must gracefully fallback to their x86_64 counterparts. The following methodology is used to support prompt on apple silicon macs: 1. install homebrew instance for intel/rosetta (x86_64) under /usr/local 2. detect apple silicon (arm64e) and install homebrew instance in /opt/homebrew 3. attempt to install all tools included with prompt natively in /opt/homebrew 4. install all tools included with prompt under rosetta in /usr/local 5. ensure /opt/homebrew is prioritised in the PATH variable The above methodology will enable native tools if and when they are available and working with apple silicon. Tools that are not available and/or fail will fallback to the rosetta versions. This enables a seamless experience for apple silicon users. --- .gitattributes | 4 +- .github/workflows/end-to-end.yml | 106 ++++++++++----- .releaserc.yml | 8 +- README.md | 2 +- VERSION | 1 + hack/e2e.apt.sh | 21 +++ hack/e2e.darwin.sh | 7 + hack/e2e.yum.sh | 21 +++ hack/install.sh | 19 +++ hack/pre.apt.sh | 11 ++ hack/pre.yum.sh | 17 +++ hack/test.sh | 27 ++++ install.sh | 15 ++- src/bash/scripts/eval/set-completion | 8 -- src/bash/scripts/eval/set-gcloud-path | 2 +- src/sh/install/centos.sh | 8 +- src/sh/install/darwin.sh | 124 ++++++++++++++++-- src/sh/install/debian.sh | 9 +- src/sh/install/fedora.sh | 13 +- src/sh/install/linux.sh | 8 +- src/sh/install/linuxmint.sh | 20 +-- src/sh/profile | 9 +- src/sh/scripts/add-var | 4 +- .../centos/install-dotnet-prerequisites | 8 ++ src/sh/scripts/darwin/eval/pandoc-path | 5 - src/sh/scripts/darwin/eval/set-brew-path | 11 ++ src/sh/scripts/darwin/install-pandoc | 2 +- .../debian/install-dotnet-prerequisites | 37 ++++++ src/sh/scripts/eval/set-brew-path | 2 +- src/sh/scripts/eval/set-gpg-agent | 6 + .../fedora/install-dotnet-prerequisites | 8 ++ src/sh/scripts/install-dotnet | 6 + src/sh/scripts/open-url | 20 ++- src/sh/scripts/remove-var | 2 +- .../ubuntu/install-dotnet-prerequisites | 36 +++++ src/sh/scripts/use-shell | 9 +- src/zsh/install/darwin.sh | 23 ++-- src/zsh/scripts/eval/set-completion | 8 -- test.sh | 6 - test/sh/scripts/install-dotnet.test.sh | 1 - test/sh/scripts/set-gpg-agent.test.sh | 6 + 41 files changed, 517 insertions(+), 143 deletions(-) create mode 100644 VERSION create mode 100755 hack/e2e.apt.sh create mode 100755 hack/e2e.darwin.sh create mode 100755 hack/e2e.yum.sh create mode 100755 hack/install.sh create mode 100755 hack/pre.apt.sh create mode 100755 hack/pre.yum.sh create mode 100755 hack/test.sh create mode 100755 src/sh/scripts/centos/install-dotnet-prerequisites delete mode 100755 src/sh/scripts/darwin/eval/pandoc-path create mode 100755 src/sh/scripts/darwin/eval/set-brew-path create mode 100755 src/sh/scripts/debian/install-dotnet-prerequisites create mode 100755 src/sh/scripts/fedora/install-dotnet-prerequisites create mode 100755 src/sh/scripts/ubuntu/install-dotnet-prerequisites delete mode 100755 test.sh create mode 100755 test/sh/scripts/set-gpg-agent.test.sh diff --git a/.gitattributes b/.gitattributes index 304125b..6d01e54 100644 --- a/.gitattributes +++ b/.gitattributes @@ -98,4 +98,6 @@ AUTHORS text *.psd1 text eol=crlf # unix files -*.sh text eol=lf +*.sh text eol=lf +src/** text eol=lf +template/* text eol=lf diff --git a/.github/workflows/end-to-end.yml b/.github/workflows/end-to-end.yml index 1124d84..d391494 100644 --- a/.github/workflows/end-to-end.yml +++ b/.github/workflows/end-to-end.yml @@ -35,37 +35,81 @@ jobs: - name: checkout uses: actions/checkout@v2 - name: install-bash - run: ./install.sh bash | tee log.txt && bash -lc 'cat $AM_PROMPT/.sha' + run: ./hack/install.sh bash - name: install-zsh - run: ./install.sh zsh | tee log.txt && zsh -lc 'cat $AM_PROMPT/.sha' + run: ./hack/install.sh zsh - name: run-tests - run: ./test.sh + run: ./hack/test.sh - # TODO: add this after figuring out a consistent way to create a non-root user without having to create specialised - # dockerfiles for each container type (linuxbrew refuses to install with the root user) - # docker: - # name: "end-to-end-${{ matrix.container }}" - # runs-on: ubuntu-20.04 - # container: ${{ matrix.container }} - # needs: cancel - # strategy: - # matrix: - # container: - # - centos:7 - # - centos:8 - # - debian:9 - # - debian:10 - # - fedora:32 - # - fedora:33 - # - linuxmintd/mint18-amd64 - # - linuxmintd/mint19-amd64 - # - linuxmintd/mint20-amd64 - # steps: - # - name: checkout - # uses: actions/checkout@v2 - # - name: install-bash - # run: ./install.sh bash | tee log.txt && bash -lc 'cat $AM_PROMPT/.sha' - # - name: install-zsh - # run: ./install.sh zsh | tee log.txt && zsh -lc 'cat $AM_PROMPT/.sha' - # - name: run-tests - # run: ./test.sh + win: + name: "end-to-end-${{ matrix.os }}" + runs-on: ${{ matrix.os }} + needs: cancel + strategy: + matrix: + os: + - windows-2019 + defaults: + run: + shell: wsl-bash {0} + steps: + - name: setup-wsl + uses: vampire/setup-wsl@v1 + - name: checkout + uses: actions/checkout@v2 + - name: install-pre + run: ./hack/pre.apt.sh + - name: install-bash + run: gosu build ./hack/install.sh bash + - name: install-zsh + run: gosu build ./hack/install.sh zsh + - name: run-tests + run: gosu build ./hack/test.sh + + docker-apt: + name: "end-to-end-${{ matrix.container }}" + runs-on: ubuntu-20.04 + container: ${{ matrix.container }} + needs: cancel + strategy: + matrix: + container: + - debian:9 + - debian:10 + - linuxmintd/mint18-amd64 + - linuxmintd/mint19-amd64 + - linuxmintd/mint20-amd64 + steps: + - name: checkout + uses: actions/checkout@v2 + - name: install-pre + run: ./hack/pre.apt.sh + - name: install-bash + run: gosu build ./hack/install.sh bash + - name: install-zsh + run: gosu build ./hack/install.sh zsh + - name: run-tests + run: gosu build ./hack/test.sh + + docker-yum: + name: "end-to-end-${{ matrix.container }}" + runs-on: ubuntu-20.04 + container: ${{ matrix.container }} + needs: cancel + strategy: + matrix: + container: + - centos:8 + - fedora:32 + - fedora:33 + steps: + - name: checkout + uses: actions/checkout@v2 + - name: install-pre + run: ./hack/pre.yum.sh + - name: install-bash + run: gosu build ./hack/install.sh bash + - name: install-zsh + run: gosu build ./hack/install.sh zsh + - name: run-tests + run: gosu build ./hack/test.sh diff --git a/.releaserc.yml b/.releaserc.yml index 0b877d4..eb9fab8 100644 --- a/.releaserc.yml +++ b/.releaserc.yml @@ -1,7 +1,13 @@ plugins: - "@semantic-release/commit-analyzer" - "@semantic-release/release-notes-generator" - - "@semantic-release/github" + - "@semantic-release/changelog" + - path: "@semantic-release/exec" + prepareCmd: echo ${nextRelease.gitHead} > VERSION + - path: "@semantic-release/github" + assets: + - CHANGELOG.md + - VERSION branches: - master diff --git a/README.md b/README.md index 0a48b46..b176d6a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ only validate a few of the most popular. | ubuntu | 16.04 (Xenial Xerus), 18.04 (Bionic Beaver), and 20.04 (Focal Fossa) | | fedora | 32 and 33 | | debian | 9 (Stretch) and 10 (Buster) | -| centOS | 7 and 8 | +| centOS | 8 | | mint | 18 (Sarah), 19 (Tara), and 20 (Ulyana) | > NOTE: not all capabilities are tested. If you discover any bugs or wish to add your favourite distro to the validated diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..d532e0e --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +b420dd99ffaa647cd1d8e97ad4b1e6914b03a811 \ No newline at end of file diff --git a/hack/e2e.apt.sh b/hack/e2e.apt.sh new file mode 100755 index 0000000..33e5eb6 --- /dev/null +++ b/hack/e2e.apt.sh @@ -0,0 +1,21 @@ +#! /usr/bin/env sh + +set -e + +SCRIPT_DIR=$(mktemp -d) + +cat <<- 'EOT' > $SCRIPT_DIR.e2e.sh +#! /usr/bin/env sh +set -e +./hack/pre.apt.sh +./hack/install.sh bash +./hack/install.sh zsh +./hack/test.sh +EOT + +chmod +x $SCRIPT_DIR/e2e.sh + +docker run \ + --volume $PWD:/home/build + --volume $SCRIPT_DIR:/build \ + debian --tty 'sh -c /build/e2e.sh' diff --git a/hack/e2e.darwin.sh b/hack/e2e.darwin.sh new file mode 100755 index 0000000..5ff13be --- /dev/null +++ b/hack/e2e.darwin.sh @@ -0,0 +1,7 @@ +#! /usr/bin/env sh + +set -e + +./hack/install.sh bash +./hack/install.sh zsh +./hack/test.sh diff --git a/hack/e2e.yum.sh b/hack/e2e.yum.sh new file mode 100755 index 0000000..01918c0 --- /dev/null +++ b/hack/e2e.yum.sh @@ -0,0 +1,21 @@ +#! /usr/bin/env sh + +set -e + +SCRIPT_DIR=$(mktemp -d) + +cat <<- 'EOT' > $SCRIPT_DIR.e2e.sh +#! /usr/bin/env sh +set -e +./hack/pre.apt.sh +./hack/install.sh bash +./hack/install.sh zsh +./hack/test.sh +EOT + +chmod +x $SCRIPT_DIR/e2e.sh + +docker run \ + --volume $PWD:/home/build + --volume $SCRIPT_DIR:/build \ + centos --tty 'sh -c /build/e2e.sh' diff --git a/hack/install.sh b/hack/install.sh new file mode 100755 index 0000000..aa6a0b5 --- /dev/null +++ b/hack/install.sh @@ -0,0 +1,19 @@ +#! /usr/bin/env sh + +set -e + +SHELL_NAME=${1:-'bash'} + +./install.sh $SHELL_NAME + +SHELL=$SHELL_NAME + +if [ -f /opt/homebrew/bin/$SHELL_NAME ]; then + SHELL=/opt/homebrew/bin/$SHELL_NAME +elif [ -f /usr/local/bin/$SHELL_NAME ]; then + SHELL=/usr/local/bin/${SHELL_NAME} +elif [ -f /home/linuxbrew/.linuxbrew/bin/$SHELL_NAME ]; then + SHELL=/home/linuxbrew/.linuxbrew/bin/${SHELL_NAME} +fi + +$SHELL -lc 'cat $AM_PROMPT/.sha' diff --git a/hack/pre.apt.sh b/hack/pre.apt.sh new file mode 100755 index 0000000..1346ca8 --- /dev/null +++ b/hack/pre.apt.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env sh + +set -e + +apt-get update && apt-get install -y gosu sudo git +gosu nobody true + +useradd --uid 1000 --user-group --system --create-home --no-log-init --groups tty --shell /bin/bash build +echo 'build ALL=(ALL) NOPASSWD:ALL' >>/etc/sudoers +chown -R build:build /home/build +chmod u=rwx,g=rx,o= /home/build diff --git a/hack/pre.yum.sh b/hack/pre.yum.sh new file mode 100755 index 0000000..49cc44d --- /dev/null +++ b/hack/pre.yum.sh @@ -0,0 +1,17 @@ +#! /usr/bin/env sh + +set -e + +gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 +curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.11/gosu-amd64" +curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.11/gosu-amd64.asc" +gpg --verify /usr/local/bin/gosu.asc +chmod +x /usr/local/bin/gosu +gosu nobody true + +yum update -y && yum install -y sudo + +useradd --uid 1000 --user-group --system --create-home --no-log-init \--groups tty --shell /bin/bash build +echo 'build ALL=(ALL) NOPASSWD:ALL' >>/etc/sudoers +chown -R build:build /home/build +chmod u=rwx,g=rx,o= /home/build diff --git a/hack/test.sh b/hack/test.sh new file mode 100755 index 0000000..ab5c835 --- /dev/null +++ b/hack/test.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh + +final=0 + +SHELL_NAME=${1:-'bash'} +SHELL=$SHELL_NAME + +if [ -f /opt/homebrew/bin/$SHELL_NAME ]; then + SHELL=/opt/homebrew/bin/$SHELL_NAME +elif [ -f /usr/local/bin/$SHELL_NAME ]; then + SHELL=/usr/local/bin/${SHELL_NAME} +elif [ -f /home/linuxbrew/.linuxbrew/bin/$SHELL_NAME ]; then + SHELL=/home/linuxbrew/.linuxbrew/bin/${SHELL_NAME} +fi + +for test in ./test/sh/scripts/*.test.sh; do + TERM=dumb $SHELL -lc "$test" + exit_code=$? + + if [ $exit_code -ne 0 ]; then + name=$(basename $test) + echo "test ($name) failed: $exit_code" + final=1 + fi +done + +exit $final diff --git a/install.sh b/install.sh index 685ce4d..3a73be1 100755 --- a/install.sh +++ b/install.sh @@ -3,19 +3,21 @@ set -e CLR_SUCCESS="\033[1;32m" # BRIGHT GREEN +CLR_WARN="\033[1;33m" # BRIGHT YELLOW CLR_CLEAR="\033[0m" # DEFAULT COLOR ECHO='echo' -AM_HOME="$HOME/.am" -AM_PROMPT="$AM_HOME/prompt" - # when not outputing to a tty, add spacing instead of colors if [ ! -t 1 ]; then CLR_SUCCESS="\n------------------------------------------------------------------------------------------------------------------------\n" + CLR_WARN=$CLR_SUCCESS CLR_CLEAR=$CLR_SUCCESS ECHO='printf' fi +AM_HOME="$HOME/.am" +AM_PROMPT="$AM_HOME/prompt" + __am_prompt_success() { $ECHO "${CLR_SUCCESS}prompt-install: $1${CLR_CLEAR}" } @@ -116,10 +118,9 @@ __am_prompt_install() { local CURL_OPT="$CURL_OPT -H 'Authorization: token $GITHUB_TOKEN'" fi - local SHA_URI="https://api.github.com/repos/automotivemastermind/prompt/commits/master" - local PROMPT_SHA=$(curl $CURL_OPT $SHA_URI | grep sha | head -n 1 | sed 's#.*\:.*"\(.*\).*",#\1#') + local PROMPT_SHA=$(cat VERSION) local PROMPT_SHA_PATH=$HOME/.am/prompt/.sha - local PROMPT_CHANGELOG_URI="https://github.com/automotivemastermind/prompt/blob/$PROMPT_SHA/CHANGELOG.md" + local PROMPT_CHANGELOG_URL="https://github.com/automotivemastermind/prompt/blob/$PROMPT_SHA/CHANGELOG.md" echo $PROMPT_SHA > $PROMPT_SHA_PATH @@ -147,7 +148,7 @@ __am_prompt_install() { . $AM_PROMPT/sh/scripts/use-shell $PROMPT_SHELL # open the changelog url - . $AM_PROMPT/sh/scripts/open-url $PROMPT_CHANGELOG_URI 1>/dev/null + . $AM_PROMPT/sh/scripts/open-url $PROMPT_CHANGELOG_URL } __am_prompt_install $@ diff --git a/src/bash/scripts/eval/set-completion b/src/bash/scripts/eval/set-completion index af3deab..622b559 100755 --- a/src/bash/scripts/eval/set-completion +++ b/src/bash/scripts/eval/set-completion @@ -9,14 +9,6 @@ elif [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion fi -if type gulp 1>/dev/null 2>&1; then - . <(gulp --completion=bash) -fi - -if type grunt 1>/dev/null 2>&1; then - . <(grunt --completion=bash) -fi - if type kubectl 1>/dev/null 2>&1; then . <(kubectl completion bash) fi diff --git a/src/bash/scripts/eval/set-gcloud-path b/src/bash/scripts/eval/set-gcloud-path index 8df4a88..5aea02a 100755 --- a/src/bash/scripts/eval/set-gcloud-path +++ b/src/bash/scripts/eval/set-gcloud-path @@ -13,7 +13,7 @@ __am_prompt_set_gcloud_path() { fi # add gcloud to the path - export PATH="$HOME/.gcloud/bin":$PATH + export PATH="$HOME/.gcloud/bin:$PATH" fi local GCLOUD_CMD=$(command -v gcloud) diff --git a/src/sh/install/centos.sh b/src/sh/install/centos.sh index 6a6d4e5..932e448 100755 --- a/src/sh/install/centos.sh +++ b/src/sh/install/centos.sh @@ -3,15 +3,13 @@ __am_prompt_install_centos() { local SUDO=$(command -v sudo 2>/dev/null || "") local YUM=$(command -v dnf 2>/dev/null || command -v yum) - local PACKAGES='sudo curl file git which findutils bash' + local PACKAGES='sudo curl file git which findutils bash util-linux-user' $ECHO "${CLR_SUCCESS}installing development tools...${CLR_CLEAR}" $SUDO $YUM groupinstall -y "Development Tools" - for pkg in $PACKAGES; do - $ECHO "${CLR_SUCCESS}installing $pkg...${CLR_CLEAR}" - $SUDO $YUM install -y ${pkg} - done + $ECHO "${CLR_SUCCESS}installing $PACKAGES...${CLR_CLEAR}" + $SUDO $YUM install -y ${PACKAGES} . "$AM_PROMPT/sh/install/linux.sh" } diff --git a/src/sh/install/darwin.sh b/src/sh/install/darwin.sh index a4ff879..c1bcfe6 100755 --- a/src/sh/install/darwin.sh +++ b/src/sh/install/darwin.sh @@ -1,30 +1,130 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash -__am_prompt_install_darwin() { - local BREWS='openssl git go nvm python' +set -e + +__am_prompt_ensure_rosetta() { + + # determine if we are on x86 + if [ "$(uname -m)" = "x86_64" ]; then + + # install homebrew using defaults + __am_prompt_install_intel + + # move on immediately + return $? + fi + + $ECHO ${CLR_WARN} + $ECHO "##############################################################################" + $ECHO + $ECHO " DETECTED APPLE SILICON " + $ECHO + $ECHO " Apple Silicon is not yet officially supported by homebrew. We will install " + $ECHO " homebrew in the following locations: " + $ECHO " - /opt/homebrew : arm64e native (DEFAULT) " + $ECHO " - /usr/local : x86_64 emulation via Rosetta 2 " + $ECHO + $ECHO " The Apple Silicon (arm64e) version will be the default as it will be placed " + $ECHO " on the PATH variable before the native version. This is compatible with more" + $ECHO " formulae at this time. To use the intel (x86_64) version, you can use the " + $ECHO " \`brew-intel\` alias. For example: " + $ECHO + $ECHO " brew-intel install git " + $ECHO + $ECHO " NOTE: Installation will take significantly longer as most formulae will be " + $ECHO " built from source. NOT ALL FORMULA ARE GAURANTEED TO WORK. INCLUDING " + $ECHO " THOSE WE ATTEMPT TO INSTALL BY DEFAULT WITHIN PROMPT! We do this to " + $ECHO " enable these formulae via install as soon as they start working. " + $ECHO + $ECHO "##############################################################################" + $ECHO ${CLR_CLEAR} + + # install rosetta 2 + softwareupdate --install-rosetta --agree-to-license 2>/dev/null + + # create the homebrew directory + if [ ! -d "/opt/homebrew" ]; then + + # create the homebrew path + sudo mkdir -p /opt/homebrew + + # chown the path + sudo chown /opt/homebrew $(whoami):staff + fi + + # install homebrew for apple silicon + __am_prompt_install_arm64 + + # install homebrew in rosetta + __am_prompt_install_rosetta +} + +__am_prompt_install_intel() { + $ECHO ${CLR_SUCCESS} + $ECHO "##############################################################################" + $ECHO "INSTALLING VIA HOMEBREW FOR INTEL MACS" + $ECHO "##############################################################################" + $ECHO ${CLR_CLEAR} - if ! type brew 1>/dev/null 2>&1; then + if ! type "${BREW_CMD}" 1>/dev/null 2>&1; then $ECHO "${CLR_SUCCESS}installing homebrew...${CLR_CLEAR}" - bash -c "CI=true $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh) && brew config" + /bin/bash -c "CI=true $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh) && /usr/local/bin/brew config" fi + __am_prompt_install_darwin "/usr/local/bin/brew" +} + +__am_prompt_install_rosetta() { + $ECHO ${CLR_SUCCESS} + $ECHO "##############################################################################" + $ECHO "INSTALLING VIA HOMEBREW FOR ROSETTA 2 (x86_64)" + $ECHO "##############################################################################" + $ECHO ${CLR_CLEAR} + + if ! type "${BREW_CMD}" 1>/dev/null 2>&1; then + $ECHO "${CLR_SUCCESS}installing homebrew...${CLR_CLEAR}" + arch -x86_64 /bin/bash -c "HOMEBREW_PREFIX=/usr/local CI=true $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh) && /usr/local/bin/brew config" + fi + + __am_prompt_install_darwin "arch -x86_64 /usr/local/bin/brew" +} + +__am_prompt_install_arm64() { + $ECHO ${CLR_SUCCESS} + $ECHO "##############################################################################" + $ECHO "INSTALLING VIA HOMEBREW FOR APPLE SILICON (arm64e)" + $ECHO "##############################################################################" + $ECHO ${CLR_CLEAR} + + if ! type "${BREW_CMD}" 1>/dev/null 2>&1; then + $ECHO "${CLR_SUCCESS}installing homebrew...${CLR_CLEAR}" + arch -x86_64 /bin/bash -c "HOMEBREW_PREFIX=/opt/homebrew CI=true $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh) && /opt/homebrew/bin/brew config" + fi + + __am_prompt_install_darwin "arch -arm64e /opt/homebrew/bin/brew" +} + +__am_prompt_install_darwin() { + local BREWS='openssl git go nvm python gpg pinentry-mac' + local BREW_CMD=${1:-"/usr/local/bin/brew"} + $ECHO "${CLR_SUCCESS}updating homebrew...${CLR_CLEAR}" - brew update + ${BREW_CMD} update set +e for pkg in $BREWS; do - if brew list --formula -1 | grep -q "^${pkg}\$"; then + if ${BREW_CMD} list --formula -1 | grep -q "^${pkg}\$"; then $ECHO "${CLR_SUCCESS}upgrading: $pkg...${CLR_CLEAR}" - brew upgrade $pkg 2>/dev/null - brew link --overwrite $pkg 2>/dev/null + ${BREW_CMD} upgrade $pkg 2>/dev/null + ${BREW_CMD} link --overwrite $pkg 2>/dev/null else $ECHO "${CLR_SUCCESS}installing: $pkg...${CLR_CLEAR}" - brew install $pkg + ${BREW_CMD} install $pkg fi done - local NVM_PATH=$(brew --prefix nvm) + local NVM_PATH=$(${BREW_CMD} --prefix nvm) if [ -f "$NVM_PATH/nvm.sh" ]; then $ECHO "${CLR_SUCCESS}setting up nvm...${CLR_CLEAR}" @@ -38,4 +138,4 @@ __am_prompt_install_darwin() { git config --system credential.helper osxkeychain } -__am_prompt_install_darwin +__am_prompt_ensure_rosetta diff --git a/src/sh/install/debian.sh b/src/sh/install/debian.sh index e8c1587..1f83515 100755 --- a/src/sh/install/debian.sh +++ b/src/sh/install/debian.sh @@ -1,5 +1,7 @@ #!/usr/bin/env sh +set -e + __am_prompt_install_debian() { local SUDO=$(command -v sudo 2>/dev/null || "") local PACKAGES='sudo build-essential curl file git bash' @@ -7,10 +9,8 @@ __am_prompt_install_debian() { $ECHO "${CLR_SUCCESS}updating software repositories...${CLR_CLEAR}" $SUDO apt-get update - for pkg in $PACKAGES; do - $ECHO "${CLR_SUCCESS}installing $pkg...${CLR_CLEAR}" - $SUDO apt-get install -y ${pkg} - done + $ECHO "${CLR_SUCCESS}installing $PACKAGES...${CLR_CLEAR}" + $SUDO apt-get install -y ${PACKAGES} $ECHO "${CLR_SUCCESS}removing unnecessary dependencies...${CLR_CLEAR}" $SUDO apt-get autoremove -y @@ -19,4 +19,3 @@ __am_prompt_install_debian() { } __am_prompt_install_debian - diff --git a/src/sh/install/fedora.sh b/src/sh/install/fedora.sh index e9d8b3b..e47d7b0 100755 --- a/src/sh/install/fedora.sh +++ b/src/sh/install/fedora.sh @@ -1,3 +1,14 @@ #!/usr/bin/env sh -. "$AM_PROMPT/sh/install/centos.sh" +set -e + +__am_prompt_install_fedora() { + local PACKAGES='libxcrypt-compat' + + $ECHO "${CLR_SUCCESS}installing $PACKAGES...${CLR_CLEAR}" + sudo dnf install -y ${PACKAGES} + + . "$AM_PROMPT/sh/install/centos.sh" +} + +__am_prompt_install_fedora diff --git a/src/sh/install/linux.sh b/src/sh/install/linux.sh index 534fe31..1d03839 100755 --- a/src/sh/install/linux.sh +++ b/src/sh/install/linux.sh @@ -1,8 +1,10 @@ #!/usr/bin/env sh +set -e + __am_prompt_install_linux() { - local BREWS='gcc git' + local BREWS='gcc git gpg' if ! type brew 1>/dev/null 2>&1; then $ECHO "${CLR_SUCCESS}installing homebrew...${CLR_CLEAR}" @@ -27,8 +29,8 @@ __am_prompt_install_linux() { fi done - set -e - + # make sure we have ownership of linuxbrew + sudo chown -R $(whoami) /home/linuxbrew/.linuxbrew } __am_prompt_install_nvm() { diff --git a/src/sh/install/linuxmint.sh b/src/sh/install/linuxmint.sh index c58c1d9..42473af 100755 --- a/src/sh/install/linuxmint.sh +++ b/src/sh/install/linuxmint.sh @@ -1,21 +1,3 @@ #!/usr/bin/env sh -__am_prompt_install_mint() { - local SUDO=$(command -v sudo 2>/dev/null || "") - local PACKAGES='sudo build-essential curl file git bash' - - $ECHO "${CLR_SUCCESS}updating software repositories...${CLR_CLEAR}" - $SUDO apt-get update - - for pkg in $PACKAGES; do - $ECHO "${CLR_SUCCESS}installing $pkg...${CLR_CLEAR}" - $SUDO apt-get install -y ${pkg} - done - - $ECHO "${CLR_SUCCESS}removing unnecessary dependencies...${CLR_CLEAR}" - $SUDO apt-get autoremove -y - - . "$AM_PROMPT/sh/install/linux.sh" -} - -__am_prompt_install_mint +. "$AM_PROMPT/sh/install/debian.sh" diff --git a/src/sh/profile b/src/sh/profile index 521edff..dbfd1be 100755 --- a/src/sh/profile +++ b/src/sh/profile @@ -70,6 +70,13 @@ fi export HISTCONTROL=ignoredubs +# detect the apple silicon brew path +if [ -f /opt/homebrew/bin/brew ]; then + + # force update the path + export PATH="/opt/homebrew/bin:$PATH" +fi + if type brew 1>/dev/null 2>&1; then export LOCAL_PREFIX=$(brew --prefix) elif [ -d $LOCALAPPDATA/git ]; then @@ -93,7 +100,7 @@ fi # test for prompt bin if [ -d "$AM_PROMPT/user/bin" ]; then # append prompt to path - export PATH="$PATH:$AM_PROMPT/user/bin" + export PATH="$AM_PROMPT/user/bin:$PATH" fi # evaluate eval scripts diff --git a/src/sh/scripts/add-var b/src/sh/scripts/add-var index b677df5..a402989 100755 --- a/src/sh/scripts/add-var +++ b/src/sh/scripts/add-var @@ -30,10 +30,10 @@ __am_prompt_add_var() { local VARIABLE="$1"=\"$2\" local VAR_PATH="$AM_PROMPT/user/variables.sh" - echo 'Adding varable: $VARIABLE' + echo "add-var: adding varable: $VARIABLE" echo >> "$VAR_PATH" echo "$VARIABLE" >> "$VAR_PATH" - . "$VAR_PATH" + source "$VAR_PATH" } __am_prompt_add_var $@ diff --git a/src/sh/scripts/centos/install-dotnet-prerequisites b/src/sh/scripts/centos/install-dotnet-prerequisites new file mode 100755 index 0000000..ef14144 --- /dev/null +++ b/src/sh/scripts/centos/install-dotnet-prerequisites @@ -0,0 +1,8 @@ +#! /usr/bin/env sh + +sudo yum install -y \ + ca-certificates \ + \ + krb5-libs \ + libicu \ + openssl-libs diff --git a/src/sh/scripts/darwin/eval/pandoc-path b/src/sh/scripts/darwin/eval/pandoc-path deleted file mode 100755 index 846a4e7..0000000 --- a/src/sh/scripts/darwin/eval/pandoc-path +++ /dev/null @@ -1,5 +0,0 @@ -#! /usr/bin/env sh - -if type /usr/libexec/path_helper 1>/dev/null 2>&1; then - eval "$(/usr/libexec/path_helper)" -fi diff --git a/src/sh/scripts/darwin/eval/set-brew-path b/src/sh/scripts/darwin/eval/set-brew-path new file mode 100755 index 0000000..3b2de84 --- /dev/null +++ b/src/sh/scripts/darwin/eval/set-brew-path @@ -0,0 +1,11 @@ +#! /usr/bin/env sh + +# -- alias for homebrew versions + +if [ -f /usr/local/bin/brew ]; then + alias brew-intel='arch -x86_64 /usr/local/bin/brew' +fi + +if [ -f /opt/homebrew/bin/brew ]; then + alias brew-arm='arch -arm64e /opt/homebrew/bin/brew' +fi diff --git a/src/sh/scripts/darwin/install-pandoc b/src/sh/scripts/darwin/install-pandoc index 3b9fbb3..6c5e689 100755 --- a/src/sh/scripts/darwin/install-pandoc +++ b/src/sh/scripts/darwin/install-pandoc @@ -6,7 +6,7 @@ __am_prompt_pandoc_install() { brew install pandoc librsvg brew tap homebrew/cask brew cask install basictex - eval "$(/usr/libexec/path_helper)" + . <(/usr/libexec/path_helper -s) echo echo "You will be asked for admin credentials to install tex plugins" diff --git a/src/sh/scripts/debian/install-dotnet-prerequisites b/src/sh/scripts/debian/install-dotnet-prerequisites new file mode 100755 index 0000000..65b08dd --- /dev/null +++ b/src/sh/scripts/debian/install-dotnet-prerequisites @@ -0,0 +1,37 @@ +#! /usr/bin/env sh + +# source the os release +. /etc/os-release + +# get the major version +MAJOR_VERSION=${VERSION_ID%.*} + +sudo apt-get update + +case "${MAJOR_VERSION}" in + "9") + sudo apt-get install -y --no-install-recommends \ + ca-certificates \ + \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu57 \ + liblttng-ust0 \ + libssl1.0.2 \ + libstdc++6 \ + zlib1g + ;; + "10") + sudo apt-get install -y --no-install-recommends \ + ca-certificates \ + \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu63 \ + libssl1.1 \ + libstdc++6 \ + zlib1g + ;; +esac diff --git a/src/sh/scripts/eval/set-brew-path b/src/sh/scripts/eval/set-brew-path index 480600e..381ca71 100755 --- a/src/sh/scripts/eval/set-brew-path +++ b/src/sh/scripts/eval/set-brew-path @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash if [ -f "$HOME/.linuxbrew/bin/brew" ]; then eval $("$HOME/.linuxbrew/bin/brew" shellenv) diff --git a/src/sh/scripts/eval/set-gpg-agent b/src/sh/scripts/eval/set-gpg-agent index bd434df..c2445d1 100755 --- a/src/sh/scripts/eval/set-gpg-agent +++ b/src/sh/scripts/eval/set-gpg-agent @@ -1,5 +1,11 @@ #!/usr/bin/env sh +# determine if gpgconf is available on the system +if ! type gpgconf 1>/dev/null 2>&1; then + # move on immediately + return +fi + # determine if this is a tty if [ -t 1 ]; then diff --git a/src/sh/scripts/fedora/install-dotnet-prerequisites b/src/sh/scripts/fedora/install-dotnet-prerequisites new file mode 100755 index 0000000..69a804e --- /dev/null +++ b/src/sh/scripts/fedora/install-dotnet-prerequisites @@ -0,0 +1,8 @@ +#! /usr/bin/env sh + +sudo dnf install -y \ + ca-certificates \ + \ + krb5-libs \ + libicu \ + openssl-libs diff --git a/src/sh/scripts/install-dotnet b/src/sh/scripts/install-dotnet index ce1d791..daaa730 100755 --- a/src/sh/scripts/install-dotnet +++ b/src/sh/scripts/install-dotnet @@ -64,6 +64,12 @@ __am_prompt_dotnet_install() { mkdir -p "$DOTNET_INSTALL_DIR" fi + local DOTNET_PREREQUISITES=$(command -v install-dotnet-prerequisites 2>/dev/null) + + if [ ! -z "${DOTNET_PREREQUISITES}" ]; then + __am_prompt_safe_exec "${DOTNET_PREREQUISITES}" + fi + local DOTNET_INSTALL_SH="$DOTNET_INSTALL_DIR/dotnet-install.sh" local DOTNET_URI='https://dot.net/v1/dotnet-install.sh' diff --git a/src/sh/scripts/open-url b/src/sh/scripts/open-url index 525b904..fa0b863 100755 --- a/src/sh/scripts/open-url +++ b/src/sh/scripts/open-url @@ -1,24 +1,32 @@ #!/usr/bin/env sh __am_prompt_open_url() { - local url="$1" + local url=${1:-} - if [ -z ${1:-} ]; then + if [ -z $url ]; then echo 'open-url: url must be supplied' return 1 fi + set +e + for cmd in open gnome-open kde-open xdg-open sensible-browser; do - if type "$cmd" 1>/dev/null 2>&1; then + if type $cmd 1>/dev/null 2>&1; then echo "open-url: opening $url via $cmd..." - "$cmd" "$url" + $cmd "$url" 1>/dev/null 2>&1 + + exit_code=$? + + if [ $exit_code -ne 0 ]; then + echo "open-url: please open a browser to: $url" + fi + return 0 fi done # no open or browser was available (headless) - echo "Open a browser: $url" - return 0 + echo "open-url: please open a browser to: $url" } __am_prompt_open_url $@ diff --git a/src/sh/scripts/remove-var b/src/sh/scripts/remove-var index 29de0b7..3a9d46f 100755 --- a/src/sh/scripts/remove-var +++ b/src/sh/scripts/remove-var @@ -5,7 +5,7 @@ if [ ! -z "${AM_PROMPT_DEBUG:-}" ]; then fi __am_prompt_remove_var_usage() { - echo 'remove-var ' + echo 'remove-var ' echo ' name : a name for your variable' } diff --git a/src/sh/scripts/ubuntu/install-dotnet-prerequisites b/src/sh/scripts/ubuntu/install-dotnet-prerequisites new file mode 100755 index 0000000..c46d20d --- /dev/null +++ b/src/sh/scripts/ubuntu/install-dotnet-prerequisites @@ -0,0 +1,36 @@ +#! /usr/bin/env sh + +# source the os release +. /etc/os-release + +# get the major version +MAJOR_VERSION=${VERSION_ID%.*} + +sudo apt-get update + +case "${MAJOR_VERSION}" in + "20") + sudo apt-get install -y --no-install-recommends \ + ca-certificates \ + \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu66 \ + libssl1.1 \ + libstdc++6 \ + zlib1g + ;; + "18") + sudo apt-get install -y --no-install-recommends \ + ca-certificates \ + \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu60 \ + libssl1.1 \ + libstdc++6 \ + zlib1g + ;; +esac diff --git a/src/sh/scripts/use-shell b/src/sh/scripts/use-shell index 8507dcc..df422ac 100755 --- a/src/sh/scripts/use-shell +++ b/src/sh/scripts/use-shell @@ -10,7 +10,9 @@ __am_prompt_use_shell() { exit 1 fi - if type brew 1>/dev/null 2>&1; then + if [ -f /opt/homebrew/bin/brew ]; then + local LOCAL_PREFIX=$(/opt/homebrew/bin/brew --prefix) + elif type brew 1>/dev/null 2>&1; then local LOCAL_PREFIX=$(brew --prefix) elif [ -d $LOCALAPPDATA/git ]; then local LOCAL_PREFIX=$(echo "/$LOCALAPPDATA/git" | sed -e 's/\\/\//g' -e 's/://') @@ -39,7 +41,7 @@ __am_prompt_use_shell() { if [ "$SHELL" != "$PROMPT_SHELL_PATH" ]; then echo "${CLR_SUCCESS}setting updated $PROMPT_SHELL to default shell for user...${CLR_CLEAR}" - sudo chsh -s $PROMPT_SHELL_PATH $USER + sudo chsh -s $PROMPT_SHELL_PATH $(whoami) # set the default shell for the current session export SHELL="$PROMPT_SHELL_PATH" @@ -48,7 +50,8 @@ __am_prompt_use_shell() { echo "${CLR_SUCCESS}" echo "##############################################################################" echo "##############################################################################" - echo " PLEASE RUN: exec -l \$SHELL # ($SHELL)" + echo " # \$SHELL will be $SHELL" + echo " PLEASE RUN: exec -l \$SHELL" echo "##############################################################################" echo "##############################################################################" echo "${CLR_CLEAR}" diff --git a/src/zsh/install/darwin.sh b/src/zsh/install/darwin.sh index bd79a12..9dc00c0 100755 --- a/src/zsh/install/darwin.sh +++ b/src/zsh/install/darwin.sh @@ -16,22 +16,19 @@ __am_prompt_install_darwin() { fi done - # test to see if the zsh completion dir is specified - if [ ! -z "${ZSH_COMPLETION_DIR:-}" ]; then - - # iterate over each completion - for completion in $ZSH_COMPLETION_DIR/*; do + # set permissions on the site-functions paths + sudo chmod u=rwx,go=rx "$LOCAL_PREFIX/share/zsh" + sudo chown $(whoami) "$LOCAL_PREFIX/share/zsh" - # test for invalid completion - if [ ! -e $completion ]; then + sudo chmod u=rwx,go=rx "$LOCAL_PREFIX/share/zsh/site-functions" + sudo chown $(whoami) "$LOCAL_PREFIX/share/zsh/site-functions" - # let the user know we're removing the invalid completion - $ECHO "${CLR_WARN}removing: $completion as it no longer exists...${CLR_CLEAR}" + # test to see if the zsh completion dir is specified + if [ ! -z "${ZSH_COMPLETION_DIR:-}" ]; then - # remove the completion - rm -f $completion - fi - done + # set permissions on the script directory + sudo chmod u=rwx,go=rx $ZSH_COMPLETION_DIR + sudo chown $(whoami) $ZSH_COMPLETION_DIR fi } diff --git a/src/zsh/scripts/eval/set-completion b/src/zsh/scripts/eval/set-completion index 6b9e5d0..f1aa97e 100755 --- a/src/zsh/scripts/eval/set-completion +++ b/src/zsh/scripts/eval/set-completion @@ -3,14 +3,6 @@ # use case sensitive match followed by case-insensitive match zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}' -if type gulp 1>/dev/null 2>&1; then - . <(gulp --completion=zsh) -fi - -if type grunt 1>/dev/null 2>&1; then - . <(grunt --completion=zsh) -fi - if type kubectl 1>/dev/null 2>&1; then . <(kubectl completion zsh) fi diff --git a/test.sh b/test.sh deleted file mode 100755 index acfdedf..0000000 --- a/test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env sh - -set -eu - -# run the tests with a dummy terminal -TERM=dumb find ./test/sh/scripts -name '*.test.sh' -exec {} \; diff --git a/test/sh/scripts/install-dotnet.test.sh b/test/sh/scripts/install-dotnet.test.sh index b237f56..e888275 100755 --- a/test/sh/scripts/install-dotnet.test.sh +++ b/test/sh/scripts/install-dotnet.test.sh @@ -10,4 +10,3 @@ echo 'test channel install' echo 'test version install' ./src/sh/scripts/install-dotnet --version latest - diff --git a/test/sh/scripts/set-gpg-agent.test.sh b/test/sh/scripts/set-gpg-agent.test.sh new file mode 100755 index 0000000..df492ff --- /dev/null +++ b/test/sh/scripts/set-gpg-agent.test.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +set -eu + +echo 'test gpg-agent' +./src/sh/scripts/eval/set-gpg-agent