|
| 1 | +# kvm.sh |
| 2 | +# Source this file from your .bash-profile or script to use |
| 3 | +_kvm_has() { |
| 4 | + type "$1" > /dev/null 2>&1 |
| 5 | + return $? |
| 6 | +} |
| 7 | + |
| 8 | +if _kvm_has "unsetopt"; then |
| 9 | + unsetopt nomatch 2>/dev/null |
| 10 | +fi |
| 11 | + |
| 12 | +if [ -z "$KRE_USER_HOME" ]; then |
| 13 | + eval KRE_USER_HOME=~/.kre |
| 14 | +fi |
| 15 | + |
| 16 | +KRE_USER_PACKAGES="$KRE_USER_HOME/packages" |
| 17 | +KRE_MONO45= |
| 18 | +KRE_X86= |
| 19 | +KRE_X64= |
| 20 | +KRE_NUGET_API_URL="https://www.myget.org/F/aspnetvnext/api/v2" |
| 21 | + |
| 22 | +_kvm_find_latest() { |
| 23 | + local platform="mono45" |
| 24 | + local architecture="x86" |
| 25 | + |
| 26 | + if ! _kvm_has "curl"; then |
| 27 | + echo 'KVM Needs curl to proceed.' >&2; |
| 28 | + return 1 |
| 29 | + fi |
| 30 | + |
| 31 | + local url="$KRE_NUGET_API_URL/GetUpdates()?packageIds=%27KRE-$platform-$architecture%27&versions=%270.0%27&includePrerelease=true&includeAllVersions=false" |
| 32 | + local cmd= |
| 33 | + local xml="$(curl $url 2>/dev/null)" |
| 34 | + version="$(echo $xml | sed 's/.*<[a-zA-Z]:Version>\([^<]*\).*/\1/')" |
| 35 | + [[ $xml == $version ]] && return 1 |
| 36 | + echo $version |
| 37 | +} |
| 38 | + |
| 39 | +_kvm_strip_path() { |
| 40 | + echo "$1" | sed -e "s#$KRE_USER_PACKAGES/[^/]*$2[^:]*:##g" -e "s#:$KRE_USER_PACKAGES/[^/]*$2[^:]*##g" -e "s#$KRE_USER_PACKAGES/[^/]*$2[^:]*##g" |
| 41 | +} |
| 42 | + |
| 43 | +_kvm_prepend_path() { |
| 44 | + if [ -z "$1" ]; then |
| 45 | + echo "$2" |
| 46 | + else |
| 47 | + echo "$2:$1" |
| 48 | + fi |
| 49 | +} |
| 50 | + |
| 51 | +_kvm_download() { |
| 52 | + local kreFullName="$1" |
| 53 | + local kreFolder="$2" |
| 54 | + |
| 55 | + local pkgName=$(echo "$kreFullName" | sed "s/\([^.]*\).*/\1/") |
| 56 | + local pkgVersion=$(echo "$kreFullName" | sed "s/[^.]*.\(.*\)/\1/") |
| 57 | + local url="$KRE_NUGET_API_URL/package/$pkgName/$pkgVersion" |
| 58 | + local kreFile="$kreFolder/$kreFullName.nupkg" |
| 59 | + |
| 60 | + if [ -e "$kreFolder" ]; then |
| 61 | + echo "$kreFullName already installed." |
| 62 | + return 0 |
| 63 | + fi |
| 64 | + |
| 65 | + echo "Downloading $kreFullName from $KRE_NUGET_API_URL" |
| 66 | + |
| 67 | + if ! _kvm_has "curl"; then |
| 68 | + echo "KVM Needs curl to proceed." >&2; |
| 69 | + return 1 |
| 70 | + fi |
| 71 | + |
| 72 | + mkdir -p "$kreFolder" > /dev/null 2>&1 |
| 73 | + |
| 74 | + local httpResult=$(curl -L -D - -u aspnetreadonly:4d8a2d9c-7b80-4162-9978-47e918c9658c "$url" -o "$kreFile" 2>/dev/null | grep "^HTTP/1.1" | head -n 1 | sed "s/HTTP.1.1 \([0-9]*\).*/\1/") |
| 75 | + |
| 76 | + [[ $httpResult == "404" ]] && echo "$kreFullName was not found in repository $KRE_NUGET_API_URL" && return 1 |
| 77 | + [[ $httpResult != "302" ]] && echo "Http Error $httpResult fetching $kreFullName from $KRE_NUGET_API_URL" && return 1 |
| 78 | + |
| 79 | + _kvm_unpack $kreFile $kreFolder |
| 80 | +} |
| 81 | + |
| 82 | +_kvm_unpack() { |
| 83 | + local kreFile="$1" |
| 84 | + local kreFolder="$2" |
| 85 | + |
| 86 | + echo "Installing to $kreFolder" |
| 87 | + |
| 88 | + if ! _kvm_has "unzip"; then |
| 89 | + echo "KVM Needs unzip to proceed." >&2; |
| 90 | + return 1 |
| 91 | + fi |
| 92 | + |
| 93 | + unzip $kreFile -d $kreFolder > /dev/null 2>&1 |
| 94 | + |
| 95 | + [ -e "$kreFolder/[Content_Types].xml" ] && rm "$kreFolder/[Content_Types].xml" |
| 96 | + |
| 97 | + [ -e "$kreFolder/_rels/" ] && rm -rf "$kreFolder/_rels/" |
| 98 | + |
| 99 | + [ -e "$kreFolder/package/" ] && rm -rf "$kreFolder/_package/" |
| 100 | + |
| 101 | + #Set shell commands as executable |
| 102 | + find "$kreFolder/bin/" -type f \ |
| 103 | + -exec sh -c "head -c 11 {} | grep '/bin/bash' > /dev/null" \; -print | xargs chmod 775 |
| 104 | +} |
| 105 | + |
| 106 | +# This is not currently required. Placeholder for the case when we have multiple platforms (ie if we bundle mono) |
| 107 | +_kvm_requested_platform() { |
| 108 | + local default=$1 |
| 109 | + [[ -z $KRE_MONO45 ]] && echo "mono45" && return |
| 110 | + echo $default |
| 111 | +} |
| 112 | + |
| 113 | +# This is not currently required. Placeholder for the case where we have multiple architectures (ie if we bundle mono) |
| 114 | +_kvm_requested_architecture() { |
| 115 | + local default=$1 |
| 116 | + |
| 117 | + [[ -n $KRE_X86 && -n $KRE_X64 ]] && echo "This command cannot accept both -x86 and -x64" && return 1 |
| 118 | + [[ -z $KRE_X86 ]] && echo "x86" && return |
| 119 | + [[ -z $KRE_X64 ]] && echo "x64" && return |
| 120 | + echo $default |
| 121 | +} |
| 122 | + |
| 123 | +_kvm_requested_version_or_alias() { |
| 124 | + local versionOrAlias="$1" |
| 125 | + |
| 126 | + if [ -e "$KRE_USER_HOME/alias/$versionOrAlias.alias" ]; then |
| 127 | + local kreFullName=$(cat "$KRE_USER_HOME/alias/$versionOrAlias.alias") |
| 128 | + local pkgName=$(echo $kreFullName | sed "s/\([^.]*\).*/\1/") |
| 129 | + local pkgVersion=$(echo $kreFullName | sed "s/[^.]*.\(.*\)/\1/") |
| 130 | + local pkgPlatform=$(_kvm_requested_platform $(echo "$pkgName" | sed "s/KRE-\([^-]*\).*/\1/")) |
| 131 | + local pkgArchitecture=$(_kvm_requested_architecture $(echo "$pkgName" | sed "s/.*-.*-\([^-]*\).*/\1/")) |
| 132 | + else |
| 133 | + local pkgVersion=$versionOrAlias |
| 134 | + local pkgPlatform=$(_kvm_requested_platform "mono45") |
| 135 | + local pkgArchitecture=$(_kvm_requested_architecture "x86") |
| 136 | + fi |
| 137 | + echo "KRE-$pkgPlatform-$pkgArchitecture.$pkgVersion" |
| 138 | +} |
| 139 | + |
| 140 | +# This will be more relevant if we support global installs |
| 141 | +_kvm_locate_kre_bin_from_full_name() { |
| 142 | + local kreFullName=$1 |
| 143 | + [ -e "$KRE_USER_PACKAGES/$kreFullName/bin" ] && echo "$KRE_USER_PACKAGES/$kreFullName/bin" && return |
| 144 | +} |
| 145 | + |
| 146 | +kvm() |
| 147 | +{ |
| 148 | + if [ $# -lt 1 ]; then |
| 149 | + kvm help |
| 150 | + return |
| 151 | + fi |
| 152 | + |
| 153 | + case $1 in |
| 154 | + "help" ) |
| 155 | + echo "" |
| 156 | + echo "K Runtime Environment Version Manager - Build {{BUILD_NUMBER}}" |
| 157 | + echo "" |
| 158 | + echo "USAGE: kvm <command> [options]" |
| 159 | + echo "" |
| 160 | + echo "kvm upgrade" |
| 161 | + echo "install latest KRE from feed" |
| 162 | + echo "set 'default' alias to installed version" |
| 163 | + echo "add KRE bin to user PATH environment variable persistently" |
| 164 | + echo "" |
| 165 | + echo "kvm install <semver>|<alias>|<nupkg>" |
| 166 | + echo "install requested KRE from feed" |
| 167 | + echo "add KRE bin to path of current command line" |
| 168 | + echo "" |
| 169 | + echo "kvm use <semver>|<alias>|none [-p -persistent]" |
| 170 | + echo "<semver>|<alias> add KRE bin to path of current command line " |
| 171 | + echo "none remove KRE bin from path of current command line" |
| 172 | + echo "-p -persistent set selected version as default" |
| 173 | + echo "" |
| 174 | + echo "kvm list" |
| 175 | + echo "list KRE versions installed " |
| 176 | + echo "" |
| 177 | + echo "kvm alias" |
| 178 | + echo "list KRE aliases which have been defined" |
| 179 | + echo "" |
| 180 | + echo "kvm alias <alias>" |
| 181 | + echo "display value of named alias" |
| 182 | + echo "" |
| 183 | + echo "kvm alias <alias> <semver>" |
| 184 | + echo "set alias to specific version" |
| 185 | + echo "" |
| 186 | + echo "" |
| 187 | + ;; |
| 188 | + |
| 189 | + "upgrade" ) |
| 190 | + [ $# -ne 1 ] && kvm help && return |
| 191 | + echo "Determining latest version" |
| 192 | + local version=$(_kvm_find_latest mono45 x86) |
| 193 | + echo $version |
| 194 | + kvm install $version |
| 195 | + kvm alias default $version |
| 196 | + ;; |
| 197 | + |
| 198 | + "install" ) |
| 199 | + [ $# -ne 2 ] && kvm help && return |
| 200 | + |
| 201 | + local versionOrAlias="$2" |
| 202 | + |
| 203 | + if [ "$versionOrAlias" == *.nupkg ]; then |
| 204 | + local kreFullName=$(echo $versionOrAlias | sed "s/\(.*\)\.nupkg/\1/") |
| 205 | + local kreFolder="$KRE_USER_PACKAGES/$kreFullName" |
| 206 | + local kreFile="$kreFolder/$kreFullName.nupkg" |
| 207 | + |
| 208 | + if [ -e "$kreFolder" ]; then |
| 209 | + echo "Target folder '$kreFolder' already exists" |
| 210 | + else |
| 211 | + mkdir "$kreFolder" > /dev/null 2>&1 |
| 212 | + cp -a "$versionOrAlias" "$kreFile" |
| 213 | + _kvm_unpack "$kreFile" "$kreFolder" |
| 214 | + fi |
| 215 | + |
| 216 | + echo "Adding $kreBin to current PATH" |
| 217 | + PATH=$(_kvm_strip_path "$PATH" "/bin") |
| 218 | + PATH=(_kvm_prepend_path "$PATH" "$kreBin") |
| 219 | + else |
| 220 | + local kreFullName="$(_kvm_requested_version_or_alias $versionOrAlias)" |
| 221 | + local kreFolder="$KRE_USER_PACKAGES/$kreFullName" |
| 222 | + _kvm_download "$kreFullName" "$kreFolder" |
| 223 | + kvm use "$versionOrAlias" |
| 224 | + fi |
| 225 | + ;; |
| 226 | + |
| 227 | + "use" ) |
| 228 | + [ $# -gt 3 ] && kvm help && return |
| 229 | + [ $# -lt 2 ] && kvm help && return |
| 230 | + |
| 231 | + shift |
| 232 | + local persistant= |
| 233 | + |
| 234 | + while [ $# -ne 0 ] |
| 235 | + do |
| 236 | + if [[ $1 == "-p" || $1 == "-persistant" ]]; then |
| 237 | + local persistant="true" |
| 238 | + else |
| 239 | + local versionOrAlias=$1 |
| 240 | + fi |
| 241 | + shift |
| 242 | + done |
| 243 | + |
| 244 | + if [[ $versionOrAlias == "none" ]]; then |
| 245 | + echo "Removing KRE from process PATH" |
| 246 | + # Strip other version from PATH |
| 247 | + PATH=`_kvm_strip_path "$PATH" "/bin"` |
| 248 | + |
| 249 | + if [[ -n $persistent && -e "$KRE_USER_HOME/alias/default.alias" ]]; then |
| 250 | + echo "Setting default KRE to none" |
| 251 | + rm "$KRE_USER_HOME/alias/default.alias" |
| 252 | + fi |
| 253 | + return 0 |
| 254 | + fi |
| 255 | + |
| 256 | + local kreFullName=$(_kvm_requested_version_or_alias "$versionOrAlias") |
| 257 | + local kreBin=$(_kvm_locate_kre_bin_from_full_name "$kreFullName") |
| 258 | + |
| 259 | + if [[ -z $kreBin ]]; then |
| 260 | + echo "Cannot find $kreFullName, do you need to run 'kvm install $versionOrAlias'?" |
| 261 | + return 1 |
| 262 | + fi |
| 263 | + |
| 264 | + echo "Adding" $kreBin "to process PATH" |
| 265 | + |
| 266 | + PATH=`_kvm_strip_path "$PATH" "/bin"` |
| 267 | + PATH=`_kvm_prepend_path "$PATH" "$kreBin"` |
| 268 | + |
| 269 | + if [[ -n $persistent ]]; then |
| 270 | + echo "Setting $kreBin as default KRE" |
| 271 | + kvm alias default "$versionOrAlias" |
| 272 | + fi |
| 273 | + ;; |
| 274 | + |
| 275 | + "alias" ) |
| 276 | + [[ $# -gt 3 ]] && kvm help && return |
| 277 | + |
| 278 | + if [[ $# == 1 ]]; then |
| 279 | + for f in $(find "$KRE_USER_HOME/alias" -name *.alias); do printf "%-20s %s\n" "$(basename $f | sed 's/.alias//')" "$(cat $f)"; done |
| 280 | + echo "" |
| 281 | + return |
| 282 | + fi |
| 283 | + |
| 284 | + local name="$2" |
| 285 | + |
| 286 | + if [[ $# == 2 ]]; then |
| 287 | + [[ ! -e "$KRE_USER_HOME/alias/$name.alias" ]] && echo "There is no alias called '$name'" && return |
| 288 | + cat "$KRE_USER_HOME/alias/$name.alias" |
| 289 | + echo "" |
| 290 | + return |
| 291 | + fi |
| 292 | + |
| 293 | + local semver="$3" |
| 294 | + local kreFullName="KRE-$(_kvm_requested_platform mono45)-$(_kvm_requested_architecture x86).$semver" |
| 295 | + |
| 296 | + [[ ! -d "$KRE_USER_PACKAGES/$kreFullName" ]] && echo "$semver is not an installed KRE version." && return 1 |
| 297 | + |
| 298 | + echo "Setting alias '$name' to '$kreFullName'" |
| 299 | + [[ ! -e "$KRE_USER_HOME/alias/" ]] && mkdir "$KRE_USER_HOME/alias/" > /dev/null |
| 300 | + |
| 301 | + echo "$kreFullName" > "$KRE_USER_HOME/alias/$name.alias" |
| 302 | + ;; |
| 303 | + |
| 304 | + "list" ) |
| 305 | + [[ $# -gt 2 ]] && kvm help && return |
| 306 | + |
| 307 | + [[ ! -d $KRE_USER_PACKAGES ]] && echo "KRE is not installed." && return 1 |
| 308 | + |
| 309 | + local searchGlob="KRE-*" |
| 310 | + if [ $# == 2 ]; then |
| 311 | + local versionOrAlias=$2 |
| 312 | + local searchGlob=$(_kvm_requested_version_or_alias "$versionOrAlias") |
| 313 | + echo $searchGlob |
| 314 | + fi |
| 315 | + |
| 316 | + for f in $(find $KRE_USER_PACKAGES/* -name $searchGlob -type d -prune -exec basename {} \;); do |
| 317 | + #TODO: Format, extract package, version arch etc |
| 318 | + echo -n $f |
| 319 | + if [[ $PATH == *"$KRE_USER_PACKAGES/$f/bin"* ]]; then |
| 320 | + echo " *" |
| 321 | + else |
| 322 | + echo "" |
| 323 | + fi |
| 324 | + [[ $# == 2 ]] && echo "" && return 0 |
| 325 | + done |
| 326 | + |
| 327 | + echo "" |
| 328 | + [[ $# == 2 ]] && return 1 # kvm list xxx - xxx was not found |
| 329 | + ;; |
| 330 | + |
| 331 | + *) |
| 332 | + echo "Unknown command $1" |
| 333 | + return 1 |
| 334 | + esac |
| 335 | +} |
| 336 | + |
| 337 | +kvm list default >/dev/null && kvm use default >/dev/null || true |
0 commit comments