1#!/usr/bin/env bash 2 3# Stop script on NZEC 4# set -e 5# Stop script if unbound variable found (use ${var:-} if intentional) 6set -u 7# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success 8# This is causing it to fail 9set -o pipefail 10 11# Use in the the functions: eval $invocation 12invocation='say_verbose "Calling: ${FUNCNAME[0]}"' 13 14# standard output may be used as a return value in the functions 15# we need a way to write text on the screen in the functions so that 16# it won't interfere with the return value. 17# Exposing stream 3 as a pipe to standard output of the script itself 18exec 3>&1 19 20say_err() { 21 printf "%b\n" "bootstrap: Error: $1" >&2 22} 23 24say() { 25 # using stream 3 (defined in the beginning) to not interfere with stdout of functions 26 # which may be used as return value 27 printf "%b\n" "bootstrap: $1" >&3 28} 29 30say_verbose() { 31 if [ "$verbose" = true ]; then 32 say "$1" 33 fi 34} 35 36machine_has() { 37 eval $invocation 38 39 hash "$1" > /dev/null 2>&1 40 return $? 41} 42 43check_min_reqs() { 44 if ! machine_has "curl"; then 45 say_err "curl is required to download dotnet. Install curl to proceed." 46 return 1 47 fi 48 49 return 0 50} 51 52# args: 53# remote_path - $1 54# [out_path] - $2 - stdout if not provided 55download() { 56 eval $invocation 57 58 local remote_path=$1 59 local out_path=${2:-} 60 61 local failed=false 62 if [ -z "$out_path" ]; then 63 curl --retry 10 -sSL --create-dirs $remote_path || failed=true 64 else 65 curl --retry 10 -sSL --create-dirs -o $out_path $remote_path || failed=true 66 fi 67 68 if [ "$failed" = true ]; then 69 say_err "Download failed" 70 return 1 71 fi 72} 73 74verbose=false 75repoRoot=`pwd` 76toolsLocalPath="<auto>" 77cliLocalPath="<auto>" 78symlinkPath="<auto>" 79sharedFxVersion="<auto>" 80force= 81forcedCliLocalPath="<none>" 82architecture="<auto>" 83dotNetInstallBranch="release/2.0.0" 84 85while [ $# -ne 0 ] 86do 87 name=$1 88 case $name in 89 -r|--repositoryRoot|-[Rr]epositoryRoot) 90 shift 91 repoRoot="$1" 92 ;; 93 -t|--toolsLocalPath|-[Tt]oolsLocalPath) 94 shift 95 toolsLocalPath="$1" 96 ;; 97 -c|--cliInstallPath|--cliLocalPath|-[Cc]liLocalPath) 98 shift 99 cliLocalPath="$1" 100 ;; 101 -u|--useLocalCli|-[Uu]seLocalCli) 102 shift 103 forcedCliLocalPath="$1" 104 ;; 105 -a|--architecture|-[Aa]rchitecture) 106 shift 107 architecture="$1" 108 ;; 109 --dotNetInstallBranch|-[Dd]ot[Nn]et[Ii]nstall[Bb]ranch) 110 shift 111 dotNetInstallBranch="$1" 112 ;; 113 --sharedFrameworkSymlinkPath|--symlink|-[Ss]haredFrameworkSymlinkPath) 114 shift 115 symlinkPath="$1" 116 ;; 117 --sharedFrameworkVersion|-[Ss]haredFrameworkVersion) 118 sharedFxVersion="$1" 119 ;; 120 --force|-[Ff]orce) 121 force=true 122 ;; 123 -v|--verbose|-[Vv]erbose) 124 verbose=true 125 ;; 126 *) 127 say_err "Unknown argument \`$name\`" 128 exit 1 129 ;; 130 esac 131 132 shift 133done 134 135if [ $toolsLocalPath = "<auto>" ]; then 136 toolsLocalPath="$repoRoot/Tools" 137fi 138 139if [ $cliLocalPath = "<auto>" ]; then 140 if [ $forcedCliLocalPath = "<none>" ]; then 141 cliLocalPath="$toolsLocalPath/dotnetcli" 142 else 143 cliLocalPath=$forcedCliLocalPath 144 fi 145fi 146 147if [ $symlinkPath = "<auto>" ]; then 148 symlinkPath="$toolsLocalPath/dotnetcli/shared/Microsoft.NETCore.App/version" 149fi 150 151 152rootCliVersion="$repoRoot/.cliversion" 153globalJson="$repoRoot/global.json" 154bootstrapComplete="$toolsLocalPath/bootstrap.complete" 155 156# if the force switch is specified delete the semaphore file if it exists 157if [[ $force && -f $bootstrapComplete ]]; then 158 rm -f $bootstrapComplete 159fi 160 161# if the semaphore file exists and is identical to the specified version then exit 162if [[ -f $bootstrapComplete && ! `cmp $bootstrapComplete $rootCliVersion` ]]; then 163 say "$bootstrapComplete appears to show that bootstrapping is complete. Use --force if you want to re-bootstrap." 164 exit 0 165fi 166 167initCliScript="dotnet-install.sh" 168dotnetInstallPath="$toolsLocalPath/$initCliScript" 169 170# blow away the tools directory so we can start from a known state 171if [ -d $toolsLocalPath ]; then 172 # if the bootstrap.sh script was downloaded to the tools directory don't delete it 173 find $toolsLocalPath -type f -not -name bootstrap.sh -exec rm -f {} \; 174else 175 mkdir $toolsLocalPath 176fi 177 178if [ $forcedCliLocalPath = "<none>" ]; then 179 check_min_reqs 180 181 # download CLI boot-strapper script 182 download "https://raw.githubusercontent.com/dotnet/cli/$dotNetInstallBranch/scripts/obtain/dotnet-install.sh" "$dotnetInstallPath" 183 chmod u+x "$dotnetInstallPath" 184 185 # load the version of the CLI 186 dotNetCliVersion=`cat $rootCliVersion` 187 188 if [ ! -e $cliLocalPath ]; then 189 mkdir -p "$cliLocalPath" 190 fi 191 192 # now execute the script 193 say_verbose "installing CLI: $dotnetInstallPath --version \"$dotNetCliVersion\" --install-dir $cliLocalPath --architecture \"$architecture\"" 194 $dotnetInstallPath --version "$dotNetCliVersion" --install-dir $cliLocalPath --architecture "$architecture" 195 if [ $? != 0 ]; then 196 say_err "The .NET CLI installation failed with exit code $?" 197 exit $? 198 fi 199 200 echo "{ \"sdk\": { \"version\": \"$dotNetCliVersion\" } }" > $globalJson 201fi 202 203cp $rootCliVersion $bootstrapComplete 204 205say "Bootstrap finished successfully." 206 207