- 
      
- 
        Save igmrrf/2eb017a400f85653d93f942ed95f1b85 to your computer and use it in GitHub Desktop. 
    A Script to bulk install applications using Homebrew and the App Store.
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | # !/bin/bash | |
| VERSION=0.0.1 | |
| NONINTERACTIVE=1 # for homebrew install | |
| DRY_RUN=false | |
| ENABLED_DEFAULT=true | |
| TAPS_ENABLED=$ENABLED_DEFAULT | |
| TAPS_ENABLED_ASK=true | |
| FORMULAS_ENABLED=$ENABLED_DEFAULT | |
| FORMULAS_ENABLED_ASK=true | |
| CASKS_ENABLED=$ENABLED_DEFAULT | |
| CASKS_ENABLED_ASK=true | |
| APPS_ENABLED=$ENABLED_DEFAULT | |
| APPS_ENABLED_ASK=true | |
| IS_ZSH=false | |
| IS_BASH=false | |
| DOTFILE=$HOME/.zshrc # default for new macs | |
| XCODE_SELECT_PATH=/Applications/Xcode.app/Contents/Developer | |
| RUBY_VERSION="$(curl -s https://raw.githubusercontent.com/facebook/react-native/main/template/_ruby-version)" | |
| NVM_DIR=$HOME/.nvm | |
| IS_HOMEBREW_INSTALLED=$(command -v brew > /dev/null && echo "true" || echo "false" ) | |
| # Add Homebrew Repositories | |
| # | |
| taps=( | |
| "homebrew/cask-versions" # add a repository for zulu | |
| "homebrew/cask-fonts" # for fira-code font and spaceship | |
| ) | |
| # Homebrew formulas (usually binaries) | |
| # run `brew search <keyword>` to find out if you can install something | |
| # via brew if it's found and shows under Casks section of results add it to | |
| # the $casks=(...) list below | |
| # | |
| formulas=( | |
| "mas" # used to install app store apps | |
| "nvm" # node version manager | |
| "rbenv" # (react native) ruby version manager | |
| "ruby-build" # (react native) needed for cocoapods | |
| "cocoapods" # (react native) kinda like npm for Xcode | |
| # "watchman" # (react native) build watcher | |
| # "nmap" # useful scanning tool | |
| # "gh" # github cli | |
| # "spaceship" # a nifty terminal prompt | |
| ) | |
| # Homebrew casks (usually gui apps) | |
| # | |
| casks=( | |
| # "slack" # chat | |
| # "discord" # chat | |
| "microsoft-teams" # chat | |
| "microsoft-outlook" # email/calendar | |
| "microsoft-edge" # browser | |
| "google-chrome" # browser | |
| "firefox" # browser | |
| # "postman" # browser | |
| # "github" # github desktop app | |
| # "docker" # docker desktop for mac | |
| # "zulu11" # (react native) java | |
| # "reactotron" # (react native) debug tool | |
| # "android-studio" # (react native) ide | |
| # "visual-studio-code" # ide | |
| # "mongodb-compass" # db client | |
| # "mysqlworkbench" # db client | |
| # "font-fira-code" # preferred font used by spaceship | |
| # "intellij-idea" # (paid) ide | |
| # "dropbox" # (paid) cloud storage | |
| # "timing" # (paid) time tracking app | |
| # "parallels" # (paid) virual machines | |
| ) | |
| # App Store Apps (installed using appId found in app's url) | |
| # low budget assoc array so when adding an app make sure | |
| # there's two entries (id, name) per line. | |
| # | |
| apps=( | |
| # "497799835" "Xcode" # (react native) | |
| # "899247664" "TestFlight" # (react native) | |
| # "1450874784" "Transporter" # (react native) | |
| "1289197285" "Mind Node" # flow/diagrams | |
| "668208984" "GIPHY Capture" # create screen recording gifs | |
| "456609775" "Window Tidy" # (paid) window manager | |
| # "409907375" "Apple Remote Desktop" # (paid) manage other macs | |
| # "1006087419" "SnippetsLab" # (paid) code snippet manager | |
| # "920404675" "Monodraw" # (paid) ascii art tool | |
| ) | |
| function pre_install () { | |
| print_title "Pre-Install:" | |
| create_dotfile_if_not_exists && | |
| create_nvm_directory_if_not_exists | |
| } | |
| function install_homebrew_if_not_installed () { | |
| IS_HOMEBREW_INSTALLED=$(command -v brew > /dev/null && echo "true" || echo "false" ) | |
| if $IS_HOMEBREW_INSTALLED; then | |
| echo "> [✓] Homebrew is installed." | |
| else | |
| echo "> [x] Homebrew is NOT installed. Installing..." | |
| if $DRY_RUN == 'true'; then | |
| printf '\n\t /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && \n\n' | |
| printf '\n\t echo "# Set PATH, MANPATH, etc., for Homebrew." >> $DOTFILE && \n' | |
| printf '\n\t echo "eval "$(/opt/homebrew/bin/brew shellenv)"" >> $DOTFILE && \n' | |
| printf '\n\t eval "$(/opt/homebrew/bin/brew shellenv)" && \n' | |
| printf '\n\t source $DOTFILE && \n' | |
| printf '\n\t install_homebrew_if_not_installed \n\n'; | |
| else | |
| NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && | |
| echo '# Set PATH, MANPATH, etc., for Homebrew.' >> $DOTFILE && | |
| echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> $DOTFILE && | |
| eval "$(/opt/homebrew/bin/brew shellenv)" && | |
| source $DOTFILE && | |
| install_homebrew_if_not_installed | |
| fi | |
| fi | |
| } | |
| function create_dotfile_if_not_exists () { | |
| if test -e $DOTFILE; then | |
| echo "> [✓] $DOTFILE exists" | |
| else | |
| touch $DOTFILE | |
| echo "> [✓] $DOTFILE created" | |
| fi | |
| } | |
| function create_nvm_directory_if_not_exists () { | |
| if test -e $HOME/.nvm; then | |
| echo "> [✓] $HOME/.nvm exists" | |
| else | |
| mkdir -p $HOME/.nvm | |
| echo "> [✓] $HOME/.nvm created" | |
| fi | |
| } | |
| function post_install_xcode () { | |
| print_title "Configuring Xcode and Commandline Tools:" | |
| if test -e "/Applications/Xcode.app"; then | |
| echo "> [✓] Xcode is installed" | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t sudo xcode-select --switch $XCODE_SELECT_PATH \n\n" | |
| else | |
| sudo xcode-select --switch $XCODE_SELECT_PATH | |
| fi | |
| echo "> [✓] xode-select path set to $XCODE_SELECT_PATH" | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t sudo xcodebuild -license accept \n\n" | |
| else | |
| sudo xcodebuild -license accept | |
| fi | |
| echo "> [✓] Accepting xcodebuild license" | |
| else | |
| echo "> [x] Xcode is not installed." | |
| fi | |
| } | |
| function post_install_nvm () { | |
| export NVM_DIR="$HOME/.nvm" | |
| if test -e $NVM_DIR/nvm.sh; then | |
| source $NVM_DIR/nvm.sh | |
| else | |
| nvm_installed=$(command -v nvm && echo "true" || echo "false" ) | |
| node_installed=$(command -v node && echo "true" || echo "false" ) | |
| if $nvm_installed; then | |
| if ! $node_installed; then | |
| echo "> [x] Node is not installed. Installing..." && | |
| printf "\n\n\t nvm install --latest-npm --default --lts \n\n" | |
| fi | |
| echo "> [✓] Node is installed!" | |
| else | |
| echo "> [x] NVM is not installed. Skipping Node install." | |
| fi | |
| fi | |
| } | |
| function post_install_test () { | |
| print_title "Quick Check:" | |
| if $DRY_RUN == 'true'; then | |
| echo "DRY RUN: (No changes were made)" | |
| fi | |
| echo "brew ......................... $(command -v brew)" | |
| echo "xcodebuild ................... $(command -v xcodebuild)" | |
| echo "xcode-select ................. $(command -v xcode-select)" | |
| echo "nvm .......................... $(command -v nvm)" | |
| echo "node ......................... $(command -v node)" | |
| echo "java ......................... $(command -v java)" | |
| echo "rbenv ........................ $(command -v rbenv)" | |
| echo "ruby ......................... $(command -v ruby)" | |
| echo "cocoapods .................... $(command -v pod)" | |
| echo "python3 ...................... $(command -v python3)" | |
| } | |
| function uninstall_app () { | |
| local app=$1 | |
| if test -e "/Applications/$app.app"; then | |
| echo "> [✓] $app is installed. Uninstalling..." | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t sudo rm -rf /Applications/$app.app \n\n" | |
| else | |
| sudo rm -rf "/Applications/$app.app" | |
| fi | |
| else | |
| echo "> [x] $app is not installed." | |
| fi | |
| } | |
| function uninstall() { | |
| print_title "Uninstalling:" | |
| for ((i=0;i<${#apps[@]};i+=2)); do | |
| local app_name="${apps[i+1]}" | |
| uninstall_app $app_name | |
| done | |
| if $DRY_RUN == 'true'; then | |
| printf '\n\t /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && ' | |
| printf "\n\t sudo rm -rf /opt/homebrew \n\n" | |
| else | |
| /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && | |
| sudo rm -rf /opt/homebrew | |
| fi | |
| echo "> [✓] Homebrew uninstalled." | |
| exit 0; | |
| } | |
| function print_help () { | |
| echo " " | |
| echo "VERSION: v$VERSION" | |
| echo " " | |
| echo "USAGE:" | |
| echo " " | |
| echo " Setup a clean mac or modify the install lists to add additional software." | |
| echo " " | |
| echo " $0 --dry-run [options]" | |
| echo " " | |
| echo " $0 [options]" | |
| echo " " | |
| echo "OPTIONS: " | |
| echo " " | |
| echo " -h, --help This help information" | |
| echo " -v, --version Prints version number" | |
| echo " --dry-run Don't actually install anything, just print what it would be" | |
| echo " doing. This can be handy for seeing if some apps are already" | |
| echo " added or debugging the script." | |
| echo " --taps Install Taps without prompting first" | |
| echo " --formulas Install Formulas without prompting first" | |
| echo " --casks Install Casks without prompting first" | |
| echo " --apps Install Apps (Apple App Store) without prompting first" | |
| echo " " | |
| echo " --uninstall Uninstalls Homebrew and all installed packages" | |
| echo " " | |
| echo " If you see things you don't want or would like to add applications to be" | |
| echo " installed, press ctrl + c then edit the lists and run again." | |
| echo " " | |
| echo " EXAMPLES:" | |
| echo " " | |
| echo " $0 -h" | |
| echo " $0 --help" | |
| echo " " | |
| echo " $0 -v" | |
| echo " $0 --version" | |
| echo " " | |
| echo " $0 # prompts for each taps, formulas, casks, and apps" | |
| echo " $0 --dry-run # prompts for each taps, formulas, casks, and apps" | |
| echo " " | |
| echo " $0 --taps --casks --formulas --apps" | |
| echo " " | |
| echo " $0 --taps" | |
| echo " $0 --formulas" | |
| echo " $0 --casks" | |
| echo " $0 --apps" | |
| echo " " | |
| echo " $0 --uninstall" | |
| exit 0; | |
| } | |
| function print_title () { | |
| echo "" | |
| echo "===============================================================================" | |
| echo " $1 "; | |
| echo "===============================================================================" | |
| } | |
| function print_subtitle () { | |
| echo " $1 "; | |
| echo "-------------------------------------------------------------------------------" | |
| } | |
| function print_list () { | |
| echo "-------------------------------------------------------------------------------" | |
| print_subtitle $1; | |
| shift; | |
| for arg in "$@"; do | |
| echo " - $arg" | |
| done | |
| echo "" | |
| } | |
| function print_apps_list () { | |
| echo "-------------------------------------------------------------------------------" | |
| print_subtitle $1; | |
| shift; | |
| for (( i=0; i<${#apps[@]}; i+=2 )) | |
| do | |
| key="${apps[i]}" | |
| val="${apps[i+1]}" | |
| echo " $key\t $val " | |
| done | |
| echo "" | |
| } | |
| # by default macOS uses zsh as the shell | |
| # | |
| # if [ $SHELL == "/bin/zsh" ]; then | |
| # IS_ZSH=true | |
| # DOTFILE=$HOME/.zshrc | |
| # elif [ $SHELL == "/bin/bash" ]; then | |
| # IS_BASH=true | |
| # DOTFILE=$HOME/.bashrc | |
| # elif [ $SHELL == "/bin/sh" ]; then | |
| # IS_BASH=true | |
| # DOTFILE=$HOME/.bashrc | |
| # fi | |
| # echo "> Sourcing $DOTFILE" | |
| # test -e $DOTFILE && source $DOTFILE; | |
| # echo "> Using shell: $SHELL" | |
| # echo "> Using dotfile: $DOTFILE" | |
| while test $# -gt 0; do | |
| # echo "arg: $1"; | |
| case "$1" in | |
| --version|-v) | |
| echo $VERSION; | |
| exit 0 | |
| ;; | |
| --dry-run) | |
| export DRY_RUN=true | |
| shift | |
| ;; | |
| --uninstall) | |
| uninstall; | |
| ;; | |
| --taps) | |
| export TAPS_ENABLED=true | |
| export TAPS_ENABLED_ASK=false | |
| shift | |
| ;; | |
| --formulas) | |
| export FORMULAS_ENABLED=true | |
| export FORMULAS_ENABLED_ASK=false | |
| shift | |
| ;; | |
| --casks) | |
| export CASKS_ENABLED=true | |
| export CASKS_ENABLED_ASK=false | |
| shift | |
| ;; | |
| --apps) | |
| export APPS_ENABLED=true | |
| export APPS_ENABLED_ASK=false | |
| shift | |
| ;; | |
| --help|-h) | |
| print_help; | |
| exit 0; | |
| ;; | |
| *) | |
| break | |
| ;; | |
| esac | |
| done | |
| # need sudo for some things. | |
| sudo -v | |
| # QUESTIONS: | |
| # Ask user what they want to install | |
| answer= | |
| print_list "Taps" "${taps[@]}"; | |
| if $TAPS_ENABLED_ASK == 'true'; then | |
| read -p " Install Taps? [y/N]: " answer; | |
| case "$answer" in y|Y) answer=true ;; n|N|*) answer=false ;; esac | |
| TAPS_ENABLED=$answer | |
| else | |
| TAPS_ENABLED=true | |
| fi | |
| print_list "Formulas" "${formulas[@]}"; | |
| if $FORMULAS_ENABLED_ASK == 'true'; then | |
| read -p " Install Formulas? [y/N]: " answer; | |
| case "$answer" in y|Y) answer=true ;; n|N|*) answer=false ;; esac | |
| FORMULAS_ENABLED=$answer | |
| else | |
| FORMULAS_ENABLED=true | |
| fi | |
| print_list "Casks" "${casks[@]}"; | |
| if $CASKS_ENABLED_ASK == 'true'; then | |
| read -p " Install Casks? [y/N]: " answer; | |
| case "$answer" in y|Y) answer=true ;; n|N|*) answer=false ;; esac | |
| CASKS_ENABLED=$answer | |
| else | |
| CASKS_ENABLED=true | |
| fi | |
| print_apps_list "Apps" "${apps[@]}"; | |
| if $APPS_ENABLED_ASK == 'true'; then | |
| read -p " Install Apps? [y/N]: " answer; | |
| case "$answer" in y|Y) answer=true ;; n|N|*) answer=false ;; esac | |
| APPS_ENABLED=$answer | |
| else | |
| APPS_ENABLED=true | |
| fi | |
| # PRE-INSTALL: | |
| pre_install; | |
| # INSTALL: | |
| IS_HOMEBREW_INSTALLED=$(command -v brew > /dev/null && echo "true" || echo "false" ) | |
| # Will recursivly re-run function if hombrew install is needed. | |
| install_homebrew_if_not_installed && | |
| # Print a table of what the scripts configuration is set to do. | |
| table="\n" | |
| C="CAN INSTALL" | |
| W="WILL INSTALL" | |
| table+="CATEGORY\tCAN INSTALL\tWILL INSTALL\n"; | |
| table+="--------\t-----------\t------------\n"; | |
| CAN_INSTALL_TAPS=$( $IS_HOMEBREW_INSTALLED == "true" && echo "true" || echo "false" ) | |
| WILL_INSTALL_TAPS=$( $TAPS_ENABLED == "true" && $CAN_INSTALL_TAPS == "true" && echo "true" || echo "false" ) | |
| C=$( $CAN_INSTALL_TAPS == "true" && echo "Yes" || echo "No" ) | |
| W=$( $WILL_INSTALL_TAPS == "true" && echo "Yes" || echo "No" ) | |
| table+="Taps\t$C\t$W\n"; | |
| CAN_INSTALL_FORMULAS=$( $IS_HOMEBREW_INSTALLED == "true" && echo "true" || echo "false" ) | |
| WILL_INSTALL_FORMULAS=$( $FORMULAS_ENABLED == "true" && $CAN_INSTALL_FORMULAS == "true" && echo "true" || echo "false" ) | |
| C=$( $CAN_INSTALL_FORMULAS == "true" && echo "Yes" || echo "No" ) | |
| W=$( $WILL_INSTALL_FORMULAS == "true" && echo "Yes" || echo "No" ) | |
| table+="Formulas\t$C\t$W\n"; | |
| CAN_INSTALL_CASKS=$( $IS_HOMEBREW_INSTALLED == "true" && echo "true" || echo "false" ) | |
| WILL_INSTALL_CASKS=$( $CASKS_ENABLED == "true" && $CAN_INSTALL_CASKS == "true" && echo "true" || echo "false" ) | |
| C=$( $CAN_INSTALL_CASKS == "true" && echo "Yes" || echo "No" ) | |
| W=$( $WILL_INSTALL_CASKS == "true" && echo "Yes" || echo "No" ) | |
| table+="Casks\t$C\t$W\n"; | |
| CAN_INSTALL_APPS=$( $IS_HOMEBREW_INSTALLED == "true" && brew ls --versions mas > /dev/null && echo "true" || echo "false" ) | |
| WILL_INSTALL_APPS=$( $CAN_INSTALL_APPS == "true" && $APPS_ENABLED == "true" && echo "true" || echo "false" ) | |
| C=$( $CAN_INSTALL_APPS == "true" && echo "Yes" || echo "No" ) | |
| W=$( $WILL_INSTALL_APPS == "true" && echo "Yes" || echo "No" ) | |
| table+="Apps\t$C\t$W"; | |
| echo $table | awk \ | |
| -F'\t' \ | |
| '{ printf "%+9s %+13s %+14s \n", $1, $2, $3 }' | |
| echo "" | |
| # | |
| # Start install process. | |
| # | |
| if [[ $TAPS_ENABLED == "true" ]]; then | |
| print_title "Installing Homebrew Taps:" | |
| for tap in "${taps[@]}"; do | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t brew tap $tap \n\n" | |
| else | |
| brew tap $tap | |
| fi | |
| echo "> [✓] Homebrew Tap $tap added." | |
| done | |
| else | |
| echo "> [✓] Skipping Taps" | |
| fi | |
| if [[ $WILL_INSTALL_FORMULAS == "true" ]]; then | |
| print_title "Installing Formulas with Homebrew:" | |
| for app in "${formulas[@]}"; do | |
| if brew ls --versions $app > /dev/null; then | |
| echo "> [✓] Formula $app is already installed" | |
| else | |
| echo "> [x] Formula $app is not installed. Installing with brew" | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t brew install $app \n\n" | |
| else | |
| brew install $app | |
| fi | |
| echo "> [✓] Formula $app is installed" | |
| fi | |
| done | |
| else | |
| echo "> [✓] Skipping Formulas" | |
| fi | |
| if [[ $WILL_INSTALL_CASKS == "true" ]]; then | |
| print_title "Installing Casks with Homebrew:" | |
| for app in "${casks[@]}"; do | |
| if brew ls --cask --versions $app > /dev/null; | |
| then | |
| echo "> [✓] Cask $app is already installed" | |
| else | |
| echo "> [x] Cask $app is not installed. Installing with brew" | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t brew install --cask $app \n\n" | |
| else | |
| brew install --cask $app | |
| fi | |
| fi | |
| done | |
| else | |
| echo "> [✓] Skipping Casks" | |
| fi | |
| if [[ $WILL_INSTALL_APPS == "true" ]]; then | |
| print_title "Installing Apps from App Store:" | |
| for ((i=0;i<${#apps[@]};i+=2)); do | |
| app_id="${apps[i]}" | |
| app_name="${apps[i+1]}" | |
| echo "> Installing '$app_name' from App Store" | |
| if $DRY_RUN == 'true'; then | |
| printf "\n\t mas install $app_id \n\n" | |
| else | |
| mas install $app_id | |
| fi | |
| echo "> [✓] $app_name installed" | |
| done | |
| else | |
| echo "> [✓] Skipping App Store Apps" | |
| fi | |
| post_install_xcode && | |
| post_install_nvm && | |
| post_install_test && | |
| print_title "Done!" | |
| # echo ' | |
| # ------------------------------------------------------------------------------- | |
| # To update your dotfile ('$DOTFILE') paste the content below into a | |
| # new Terminal window. | |
| # ------------------------------------------------------------------------------- | |
| # | |
| # echo " | |
| # # SHELL OPTIONS ############################################################### | |
| # | |
| # ## Enable history filtering by what you have already typed using up/down keys | |
| # autoload -U history-search-end | |
| # zle -N history-beginning-search-backward-end history-search-end | |
| # zle -N history-beginning-search-forward-end history-search-end | |
| # bindkey "^[[A" history-beginning-search-backward-end | |
| # bindkey "^[[B" history-beginning-search-forward-end | |
| # | |
| # ## Load Spaceship Prompt | |
| # source $(brew --prefix)/opt/spaceship/spaceship.zsh | |
| # | |
| # # ENVIRONMENT ################################################################# | |
| # | |
| # ## Set PATH, MANPATH, etc., for Homebrew. | |
| # eval "$(/opt/homebrew/bin/brew shellenv)" | |
| # | |
| # ## Ruby Environment | |
| # eval "$(rbenv init - zsh)" | |
| # | |
| # # ALIASES ##################################################################### | |
| # | |
| # alias reload="source '$DOTFILE'" | |
| # alias ll="ls -lah" | |
| # alias docker-compose="docker compose" | |
| # | |
| # # EXPORTS ##################################################################### | |
| # | |
| # export AWS_DEFAULT_REGION="us-east-1" | |
| # export AWS_PAGER="" | |
| # export AWS_DEFAULT_PROFILE="" | |
| # | |
| # export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/Contents/Home/ | |
| # export ANDROID_HOME=$HOME/Library/Android/sdk | |
| # export ANDROID_SDK_ROOT=$ANDROID_HOME | |
| # | |
| # export PATH=$HOME/.sencha/Cmd:$PATH | |
| # export PATH=$HOME/aws-cli/aws:$PATH | |
| # export PATH=$PATH:$ANDROID_HOME/emulator | |
| # export PATH=$PATH:$ANDROID_HOME/platform-tools | |
| # | |
| # export NVM_DIR=$HOME/.nvm | |
| # [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh" # This loads nvm | |
| # [ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion | |
| # | |
| # " >> '$DOTFILE' | |
| # | |
| # ------------------------------------------------------------------------------- | |
| # '; | |
| exit 0; | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment