From aff069cf34c402dde416628ab34bc993797c4e30 Mon Sep 17 00:00:00 2001 From: Mark Tiedemann Date: Tue, 22 Jan 2019 20:50:50 +0100 Subject: [PATCH] Rewrite PowerShell script to be cross-platform (#25) --- .appveyor.yml | 11 ++-- .travis.yml | 25 +++++++ README.md | 2 + install.ps1 | 165 ++++++++++++++++++++++++++--------------------- install_test.ps1 | 43 ++++++++++++ 5 files changed, 165 insertions(+), 81 deletions(-) create mode 100644 install_test.ps1 diff --git a/.appveyor.yml b/.appveyor.yml index 1395a81..e153ea2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,14 +13,11 @@ for: only: - TYPE: powershell install: - - ps: $url = "https://raw.githubusercontent.com", $env:APPVEYOR_REPO_NAME, - $env:APPVEYOR_REPO_COMMIT, "install.ps1" -join "/" - - ps: iex (iwr $url) + - ps: iex (new-object net.webclient).downloadstring('https://get.scoop.sh') + - ps: scoop install pwsh test_script: - - ps: if (-not (Test-Path "~\.deno\bin\deno.exe")) { - throw "deno.exe not found in expected location" - } - - ps: deno --help + - ps: .\install_test.ps1 + - ps: pwsh install_test.ps1 - matrix: only: diff --git a/.travis.yml b/.travis.yml index 372570c..1a2556f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,3 +39,28 @@ matrix: - shfmt script: - ./install_test.sh + + - language: minimal + os: + - linux + before_script: + - wget -q https://packages.microsoft.com/config/ubuntu/14.04/packages-microsoft-prod.deb + - sudo dpkg -i packages-microsoft-prod.deb + - sudo apt-get update + - sudo apt-get install -y powershell + script: + - pwsh install_test.ps1 + + - language: minimal + os: + - osx + cache: + directories: + - $HOME/Library/Caches/Homebrew + before_cache: + - brew cleanup + before_script: + - brew tap caskroom/cask + - brew cask install powershell + script: + - pwsh install_test.ps1 diff --git a/README.md b/README.md index e814d81..4b641cd 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,5 @@ curl -L https://deno.land/x/install/install.py | python - v0.2.0 ```powershell iwr https://deno.land/x/install/install.ps1 -out install.ps1; .\install.ps1 v0.2.0 ``` + +_Note: Depending on your security settings, you may have to run `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` first to allow downloaded scripts to be executed._ diff --git a/install.ps1 b/install.ps1 index a1b0ea2..f23fdf6 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,88 +1,105 @@ +#!/usr/bin/env pwsh # Copyright 2018 the Deno authors. All rights reserved. MIT license. # TODO(everyone): Keep this script simple and easily auditable. + param ( - [alias("v")] - [string] $version + [ValidatePattern('^v(\d+).(\d+).(\d+)$')] + [String] $Version ) -$ErrorActionPreference = "Stop" +$ErrorActionPreference = 'Stop' -# Enable TLS 1.2 since it is required for connections to GitHub. -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - -# Helper functions for pretty terminal output. -function Write-Part ([string] $Text) { - Write-Host $Text -NoNewline -} -function Write-Emphasized ([string] $Text) { - Write-Host $Text -NoNewLine -ForegroundColor "Yellow" -} -function Write-Done { - Write-Host " done" -NoNewline -ForegroundColor "Green"; - Write-Host "." +if ($PSVersionTable.PSVersion.Major -lt 6) { + $IsWin = $true + $IsOsx = $false +} else { + $IsWin = $IsWindows + $IsOsx = $IsMacOS } -if (-not $version) { - # Determine latest Deno release via GitHub API. - $latest_release_uri = "https://api.github.com/repos/denoland/deno/releases/latest" - Write-Part "Downloading "; Write-Emphasized $latest_release_uri; Write-Part "..." - $latest_release_json = Invoke-WebRequest -Uri $latest_release_uri - Write-Done - - Write-Part "Determining latest Deno release: " - $version = ($latest_release_json | ConvertFrom-Json).tag_name - Write-Emphasized $version; Write-Part "... " - Write-Done +$BinDir = if ($IsWin) { + "$Home\.deno\bin" +} else { + "$Home/.deno/bin" } -# Create ~\.deno\bin directory if it doesn't already exist -$deno_dir = "${Home}\.deno\bin" -if (-not (Test-Path $deno_dir)) { - Write-Part "Creating directory "; Write-Emphasized $deno_dir; Write-Part "..." - New-Item -Path $deno_dir -ItemType Directory | Out-Null - Write-Done +$Zip = if ($IsWin) { + 'zip' +} else { + 'gz' } -# Download Deno release. -$zip_file = "${deno_dir}\deno_win_x64.zip" -$download_uri = "https://github.com/denoland/deno/releases/download/" + - "${version}/deno_win_x64.zip" -Write-Part "Downloading "; Write-Emphasized $download_uri; Write-Part "..." -Invoke-WebRequest -Uri $download_uri -OutFile $zip_file -Write-Done - -# Extract deno.exe from .zip file. -Write-Part "Extracting "; Write-Emphasized $zip_file -Write-Part " into "; Write-Emphasized ${deno_dir}; Write-Part "..." -# Using -Force to overwrite deno.exe if it already exists -Expand-Archive -Path $zip_file -DestinationPath $deno_dir -Force -Write-Done - -# Remove .zip file. -Write-Part "Removing "; Write-Emphasized $zip_file; Write-Part "..." -Remove-Item -Path $zip_file -Write-Done - -# Get Path environment variable for the current user. -$user = [EnvironmentVariableTarget]::User -$path = [Environment]::GetEnvironmentVariable("PATH", $user) - -# Check whether Deno is in the Path. -$paths = $path -split ";" -$is_in_path = $paths -contains $deno_dir -or $paths -contains "${deno_dir}\" - -# Add Deno to PATH if it hasn't been added already. -if (-not $is_in_path) { - Write-Part "Adding "; Write-Emphasized $deno_dir; Write-Part " to the " - Write-Emphasized "PATH"; Write-Part " environment variable..." - [Environment]::SetEnvironmentVariable("PATH", "${path};${deno_dir}", $user) - # Add Deno to the PATH variable of the current terminal session - # so `deno` can be used immediately without restarting the terminal. - $env:PATH += ";${deno_dir}" - Write-Done +$DenoZip = if ($IsWin) { + "$BinDir\deno.$Zip" +} else { + "$BinDir/deno.$Zip" } -Write-Host "" -Write-Host "Deno was installed successfully." -ForegroundColor "Green" -Write-Part "Run "; Write-Emphasized "deno --help"; Write-Host " to get started." -Write-Host "" +$DenoExe = if ($IsWin) { + "$BinDir\deno.exe" +} else { + "$BinDir/deno" +} + +$OS = if ($IsWin) { + 'win' +} else { + if ($IsOsx) { + 'osx' + } else { + 'linux' + } +} + +if (!$Version) { + if ($PSVersionTable.PSVersion.Major -lt 6) { + $Response = Invoke-WebRequest 'https://github.com/denoland/deno/releases' + $HTMLFile = New-Object -Com HTMLFile + $HTMLFile.IHTMLDocument2_write($Response.Content) + $DenoUri = $HTMLFile.getElementsByTagName('a') | + Where-Object { $_.href -like "about:/denoland/deno/releases/download/*/deno_${OS}_x64.$Zip" } | + ForEach-Object { $_.href -replace 'about:', 'https://github.com' } | + Select-Object -First 1 + } else { + $DenoUri = (Invoke-WebRequest 'https://github.com/denoland/deno/releases').Links | + Where-Object { $_.href -like "/denoland/deno/releases/download/*/deno_${OS}_x64.$Zip" } | + ForEach-Object { 'https://github.com' + $_.href } | + Select-Object -First 1 + } +} else { + $DenoUri = "https://github.com/denoland/deno/releases/download/$Version/deno_${OS}_x64.$Zip" +} + +if (!(Test-Path $BinDir)) { + New-Item $BinDir -ItemType Directory | Out-Null +} + +Invoke-WebRequest $DenoUri -Out $DenoZip + +if ($IsWindows) { + Expand-Archive $DenoZip -Destination $BinDir -Force + Remove-Item $DenoZip +} else { + gunzip -df $DenoZip +} + +if ($IsWindows) { + $User = [EnvironmentVariableTarget]::User + $Path = [Environment]::GetEnvironmentVariable('Path', $User) + if (!(";$Path;".ToLower() -like "*;$BinDir;*".ToLower())) { + [Environment]::SetEnvironmentVariable('Path', "$Path;$BinDir", $User) + $Env:Path += ";$BinDir" + } + Write-Output "Deno was installed successfully to $DenoExe" + Write-Output "Run 'deno --help' to get started" +} else { + chmod +x "$BinDir/deno" + Write-Output "Deno was installed successfully to $DenoExe" + if (Get-Command deno -ErrorAction SilentlyContinue) { + Write-Output "Run 'deno --help' to get started" + } else { + Write-Output "Manually add the directory to your `$HOME/.bash_profile (or similar)" + Write-Output " export PATH=`"${BinDir}:`$PATH`"" + Write-Output "Run '~/.deno/bin/deno --help' to get started" + } +} diff --git a/install_test.ps1 b/install_test.ps1 new file mode 100644 index 0000000..843012a --- /dev/null +++ b/install_test.ps1 @@ -0,0 +1,43 @@ +#!/usr/bin/env pwsh + +$ErrorActionPreference = 'Stop' + +if (!(Get-PSRepository)) { + Register-PSRepository -Default +} + +if (!(Get-Module PSScriptAnalyzer -ListAvailable)) { + Install-Module PSScriptAnalyzer -Scope CurrentUser -Force +} + +Invoke-ScriptAnalyzer *.ps1 -EnableExit + +$IsWin = if ($PSVersionTable.PSVersion.Major -lt 6) { + $true +} else { + $IsWindows +} + +.\install.ps1 v0.2.0 +$DenoVersion = if ($IsWin) { + deno --version +} else { + ~/.deno/bin/deno --version +} +if (!($DenoVersion[0] -eq 'deno: 0.2.0')) { + throw $DenoVersion +} else { + Write-Output $DenoVersion +} + +.\install.ps1 +$DenoVersion = if ($IsWin) { + deno --version +} else { + ~/.deno/bin/deno --version +} +if (!($DenoVersion[0] -match 'deno: \d+\.\d+\.\d+')) { + throw $DenoVersion +} else { + Write-Output $DenoVersion +}