2016-09-19 11:50:08 +08:00
[ CmdletBinding ( ) ]
param (
2017-02-17 10:48:14 +08:00
[ string ] $Dependency ,
[ ValidateNotNullOrEmpty ( ) ]
[ string ] $downloadPromptOverride = " 0 "
2016-09-19 11:50:08 +08:00
)
2017-02-17 10:48:14 +08:00
$downloadPromptOverride_NO_OVERRIDE = 0
$downloadPromptOverride_DO_NOT_PROMPT = 1
$downloadPromptOverride_ALWAYS_PROMPT = 2
2016-09-19 11:50:08 +08:00
Import-Module BitsTransfer
2016-09-20 09:46:02 +08:00
$scriptsDir = split-path -parent $MyInvocation . MyCommand . Definition
$vcpkgRootDir = & $scriptsDir \ findFileRecursivelyUp . ps1 $scriptsDir . vcpkg-root
$downloadsDir = " $vcpkgRootDir \downloads "
2016-09-19 11:50:08 +08:00
function SelectProgram([Parameter(Mandatory=$true)][string]$Dependency )
{
2017-02-17 10:48:14 +08:00
function promptForDownload([string]$title , [ string ] $message , [ string ] $yesDescription , [ string ] $noDescription , [ string ] $downloadPromptOverride )
2016-09-19 11:50:08 +08:00
{
2017-02-17 10:48:14 +08:00
$do_not_prompt = ( $downloadPromptOverride -eq $downloadPromptOverride_DO_NOT_PROMPT ) -Or
( Test-Path " $downloadsDir \AlwaysAllowEverything " ) -Or
( Test-Path " $downloadsDir \AlwaysAllowDownloads " )
if ( ( $downloadPromptOverride -ne $downloadPromptOverride_ALWAYS_PROMPT ) -And $do_not_prompt )
2016-09-19 11:50:08 +08:00
{
return $true
}
$yes = New-Object System . Management . Automation . Host . ChoiceDescription " &Yes " , $yesDescription
$no = New-Object System . Management . Automation . Host . ChoiceDescription " &No " , $noDescription
$AlwaysAllowDownloads = New-Object System . Management . Automation . Host . ChoiceDescription " &Always Allow Downloads " , ( $yesDescription + " (Future download prompts will not be displayed) " )
$options = [ System.Management.Automation.Host.ChoiceDescription[] ] ( $yes , $no , $AlwaysAllowDownloads )
$result = $host . ui . PromptForChoice ( $title , $message , $options , 0 )
switch ( $result )
{
0 { return $true }
1 { return $false }
2 {
2016-09-20 09:46:02 +08:00
New-Item " $downloadsDir \AlwaysAllowDownloads " -type file -force | Out-Null
2016-09-19 11:50:08 +08:00
return $true
}
}
throw " Unexpected result "
}
function performDownload ( [ Parameter ( Mandatory = $true ) ] [ string ] $Dependency ,
[ Parameter ( Mandatory = $true ) ] [ string ] $url ,
2016-09-20 09:46:02 +08:00
[ Parameter ( Mandatory = $true ) ] [ string ] $downloadDir ,
2016-09-19 11:50:08 +08:00
[ Parameter ( Mandatory = $true ) ] [ string ] $downloadPath ,
[ Parameter ( Mandatory = $true ) ] [ string ] $downloadVersion ,
[ Parameter ( Mandatory = $true ) ] [ string ] $requiredVersion )
{
if ( Test-Path $downloadPath )
{
return
}
2017-01-24 09:02:43 +08:00
2016-09-19 11:50:08 +08:00
$title = " Download " + $Dependency
$message = ( " No suitable version of " + $Dependency + " was found (requires $requiredVersion or higher). Download portable version? " )
$yesDescription = " Downloads " + $Dependency + " v " + $downloadVersion + " app-locally. "
2017-01-24 09:02:43 +08:00
$noDescription = " Does not download " + $Dependency + " . "
2017-02-17 10:48:14 +08:00
$userAllowedDownload = promptForDownload $title $message $yesDescription $noDescription $downloadPromptOverride
2016-09-19 11:50:08 +08:00
if ( ! $userAllowedDownload )
{
throw [ System.IO.FileNotFoundException ] ( " Could not detect suitable version of " + $Dependency + " and download not allowed " )
}
2016-09-20 09:46:02 +08:00
if ( ! ( Test-Path $downloadDir ) )
2016-09-19 11:50:08 +08:00
{
2016-09-20 09:46:02 +08:00
New-Item -ItemType directory -Path $downloadDir | Out-Null
2016-09-19 11:50:08 +08:00
}
if ( $Dependency -ne " git " ) # git fails with BITS
{
2017-02-03 08:00:30 +08:00
try {
2017-02-22 19:51:05 +08:00
$WC = New-Object System . Net . WebClient
$ProxyAuth = ! $WC . Proxy . IsBypassed ( $url )
If ( $ProxyAuth ) {
$ProxyCred = Get-Credential -Message " Enter credentials for Proxy Authentication "
$PSDefaultParameterValues . Add ( " Start-BitsTransfer:ProxyAuthentication " , " Basic " )
$PSDefaultParameterValues . Add ( " Start-BitsTransfer:ProxyCredential " , $ProxyCred )
}
2017-02-03 08:00:30 +08:00
Start-BitsTransfer -Source $url -Destination $downloadPath -ErrorAction Stop
}
catch [ System.Exception ] {
# If BITS fails for any reason, delete any potentially partially downloaded files and continue
if ( Test-Path $downloadPath )
{
Remove-Item $downloadPath
}
}
2016-09-19 11:50:08 +08:00
}
2017-02-03 08:00:30 +08:00
if ( ! ( Test-Path $downloadPath ) )
2016-09-19 11:50:08 +08:00
{
2017-02-03 08:00:30 +08:00
Write-Host ( " Downloading $Dependency ... " )
( New-Object System . Net . WebClient ) . DownloadFile ( $url , $downloadPath )
2016-09-19 11:50:08 +08:00
}
}
# Enums (without resorting to C#) are only available on powershell 5+.
$ExtractionType_NO_EXTRACTION_REQUIRED = 0
$ExtractionType_ZIP = 1
$ExtractionType_SELF_EXTRACTING_7Z = 2
2017-01-24 09:02:43 +08:00
2016-09-19 11:50:08 +08:00
# Using this to wait for the execution to finish
2017-01-24 09:02:43 +08:00
function Invoke-Command ( )
2016-09-19 11:50:08 +08:00
{
param ( [ string ] $program = $ ( throw " Please specify a program " ) ,
[ string ] $argumentString = " " ,
[ switch ] $waitForExit )
$psi = new-object " Diagnostics.ProcessStartInfo "
$psi . FileName = $program
$psi . Arguments = $argumentString
$proc = [ Diagnostics.Process ] :: Start ( $psi )
2017-01-24 09:02:43 +08:00
if ( $waitForExit )
2016-09-19 11:50:08 +08:00
{
$proc . WaitForExit ( ) ;
}
}
function Expand-ZIPFile($file , $destination )
{
2017-02-16 08:35:51 +08:00
if ( ! ( Test-Path $destination ) )
{
New-Item -ItemType Directory -Path $destination | Out-Null
}
2016-09-19 11:50:08 +08:00
$shell = new-object -com shell . application
$zip = $shell . NameSpace ( $file )
foreach ( $item in $zip . items ( ) )
{
# Piping to Out-Null is used to block until finished
$shell . Namespace ( $destination ) . copyhere ( $item ) | Out-Null
}
}
if ( $Dependency -eq " cmake " )
{
2017-02-17 10:02:16 +08:00
$requiredVersion = " 3.8.0 "
$downloadVersion = " 3.8.0 "
$url = " https://cmake.org/files/v3.8/cmake-3.8.0-rc1-win32-x86.zip "
$downloadPath = " $downloadsDir \cmake-3.8.0-rc1-win32-x86.zip "
$expectedDownloadedFileHash = " ccdbd92fbfb548aa35a545e4e45ff19fd6d13c88c90370acdf940c3cf464e9c9 "
$executableFromDownload = " $downloadsDir \cmake-3.8.0-rc1-win32-x86\bin\cmake.exe "
2016-09-19 11:50:08 +08:00
$extractionType = $ExtractionType_ZIP
2017-02-16 08:35:51 +08:00
$extractionFolder = $downloadsDir
2016-09-19 11:50:08 +08:00
}
elseif ( $Dependency -eq " nuget " )
{
2017-01-24 10:42:34 +08:00
$requiredVersion = " 3.3.0 "
$downloadVersion = " 3.5.0 "
$url = " https://dist.nuget.org/win-x86-commandline/v3.5.0/nuget.exe "
2017-01-25 04:30:14 +08:00
$downloadPath = " $downloadsDir \nuget-3.5.0\nuget.exe "
2017-01-24 10:42:34 +08:00
$expectedDownloadedFileHash = " 399ec24c26ed54d6887cde61994bb3d1cada7956c1b19ff880f06f060c039918 "
2017-01-25 04:30:14 +08:00
$executableFromDownload = $downloadPath
2016-09-19 11:50:08 +08:00
$extractionType = $ExtractionType_NO_EXTRACTION_REQUIRED
}
elseif ( $Dependency -eq " git " )
{
$requiredVersion = " 2.0.0 "
2017-02-16 08:35:51 +08:00
$downloadVersion = " 2.11.1 "
$url = " https://github.com/git-for-windows/git/releases/download/v2.11.1.windows.1/MinGit-2.11.1-32-bit.zip " # We choose the 32-bit version
$downloadPath = " $downloadsDir \MinGit-2.11.1-32-bit.zip "
$expectedDownloadedFileHash = " 6ca79af09015625f350ef4ad74a75cfb001b340aec095b6963be9d45becb3bba "
# There is another copy of git.exe in MinGit\bin. However, an installed version of git add the cmd dir to the PATH.
2017-01-24 09:02:43 +08:00
# Therefore, choosing the cmd dir here as well.
2017-02-16 08:35:51 +08:00
$executableFromDownload = " $downloadsDir \MinGit-2.11.1-32-bit\cmd\git.exe "
$extractionType = $ExtractionType_ZIP
$extractionFolder = " $downloadsDir \MinGit-2.11.1-32-bit "
2016-09-19 11:50:08 +08:00
}
else
{
throw " Unknown program requested "
}
2017-01-25 04:30:14 +08:00
$downloadSubdir = Split-path $downloadPath -Parent
if ( ! ( Test-Path $downloadSubdir ) )
{
New-Item -ItemType Directory -Path $downloadSubdir | Out-Null
}
2016-09-20 09:46:02 +08:00
performDownload $Dependency $url $downloadsDir $downloadPath $downloadVersion $requiredVersion
2016-09-19 11:50:08 +08:00
#calculating the hash
$hashAlgorithm = [ Security.Cryptography.HashAlgorithm ] :: Create ( " SHA256 " )
$fileAsByteArray = [ io.File ] :: ReadAllBytes ( $downloadPath )
$hashByteArray = $hashAlgorithm . ComputeHash ( $fileAsByteArray )
$downloadedFileHash = -Join ( $hashByteArray | ForEach { " {0:x2} " -f $_ } )
if ( $expectedDownloadedFileHash -ne $downloadedFileHash )
{
throw [ System.IO.FileNotFoundException ] ( " Mismatching hash of the downloaded " + $Dependency )
}
if ( $extractionType -eq $ExtractionType_NO_EXTRACTION_REQUIRED )
{
# do nothing
}
elseif ( $extractionType -eq $ExtractionType_ZIP )
{
if ( -not ( Test-Path $executableFromDownload ) ) # consider renaming the extraction folder to make sure the extraction finished
{
2017-02-16 08:35:51 +08:00
# Expand-Archive $downloadPath -dest "$extractionFolder" -Force # Requires powershell 5+
Expand-ZIPFile -File $downloadPath -Destination $extractionFolder
2016-09-19 11:50:08 +08:00
}
}
elseif ( $extractionType -eq $ExtractionType_SELF_EXTRACTING_7Z )
{
if ( -not ( Test-Path $executableFromDownload ) )
{
Invoke-Command $downloadPath " -y " -waitForExit: $true
2017-01-24 09:02:43 +08:00
}
2016-09-19 11:50:08 +08:00
}
else
{
throw " Invalid extraction type "
}
if ( -not ( Test-Path $executableFromDownload ) )
{
throw [ System.IO.FileNotFoundException ] ( " Could not detect or download " + $Dependency )
}
2017-01-25 04:36:46 +08:00
return $downloadPath
2016-09-19 11:50:08 +08:00
}
SelectProgram $Dependency