Enable install-powershell.ps1 to update the current running powershell (#5429)

1. Remove `[validate]` attribute from parameter so this script can be invoked directly from the web. This doesn't have any negative impact as the $Destination parameter will have a default value if null or empty.
2. Move removal of destination folder later as installing the package requires package management module and archive module (on Windows)
3. On Windows, because files have open handles when run from existing powershell-daily install, I rename the existing files and copy over the new ones.  User needs to exit and restart `pwsh` to take effect (similar to macOS/Linux where you have to exit and restart anyways)
This commit is contained in:
Steve Lee
2017-11-14 10:45:08 -08:00
committed by Dongbo Wang
parent 31f7639552
commit 83e1d64669
+47 -16
View File
@@ -19,7 +19,6 @@
[CmdletBinding()]
param(
[Parameter()]
[ValidateNotNullOrEmpty()]
[string] $Destination,
[Parameter()]
@@ -50,17 +49,34 @@ if (-not $Destination) {
$Destination = "${Destination}-daily"
}
}
if (Test-Path -Path $Destination) {
if ($DoNotOverwrite) {
throw "Destination folder '$Destination' already exist. Use a different path or omit '-DoNotOverwrite' to overwrite."
}
Remove-Item -Path $Destination -Recurse -Force
}
New-Item -ItemType Directory -Path $Destination -Force > $null
$Destination = Resolve-Path -Path $Destination | ForEach-Object -MemberName Path
$Destination = $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Destination)
Write-Verbose "Destination: $Destination" -Verbose
Function Remove-Destination([string] $Destination) {
if (Test-Path -Path $Destination) {
if ($DoNotOverwrite) {
throw "Destination folder '$Destination' already exist. Use a different path or omit '-DoNotOverwrite' to overwrite."
}
Write-Verbose "Removing old installation: $Destination" -Verbose
if (Test-Path -Path "$Destination.old") {
Remove-Item "$Destination.old" -Recurse -Force
}
if ($IsWinEnv -and ($Destination -eq $PSHome)) {
# handle the case where the updated folder is currently in use
Get-ChildItem -Recurse -File -Path $PSHome | ForEach-Object {
if ($_.extension -eq "old") {
Remove-Item $_
} else {
Move-Item $_.fullname "$($_.fullname).old"
}
}
} else {
# Unix systems don't keep open file handles so you can just move files/folders even if in use
Move-Item "$Destination" "$Destination.old"
}
}
}
$architecture = if (-not $IsWinEnv) {
"x64"
} else {
@@ -79,7 +95,7 @@ try {
}
if ($architecture -ne "x64") {
throw "The OS architecture is '$architecture'. However, we currently only support daily package for x64 Windows."
throw "The OS architecture is '$architecture'. However, we currently only support daily package for x64."
}
## Register source if not yet
@@ -99,10 +115,9 @@ try {
$package = Find-Package -Source powershell-core-daily -AllowPrereleaseVersions -Name $packageName
Write-Verbose "Daily package found. Name: $packageName; Version: $($package.Version)" -Verbose
Install-Package -InputObject $package -Destination $tempDir -ExcludeVersion > $null
Install-Package -InputObject $package -Destination $tempDir -ExcludeVersion > $null
$contentPath = [System.IO.Path]::Combine($tempDir, $packageName, "content")
Copy-Item -Path $contentPath\* -Destination $Destination -Recurse -Force
} else {
$metadata = Invoke-RestMethod https://api.github.com/repos/powershell/powershell/releases/latest
$release = $metadata.tag_name -replace '^v'
@@ -120,16 +135,29 @@ try {
$packagePath = Join-Path -Path $tempDir -ChildPath $packageName
Invoke-WebRequest -Uri $downloadURL -OutFile $packagePath
$contentPath = Join-Path -Path $tempDir -ChildPath "new"
New-Item -ItemType Directory -Path $contentPath > $null
if ($IsWinEnv) {
Expand-Archive -Path $packagePath -DestinationPath $Destination
Expand-Archive -Path $packagePath -DestinationPath $contentPath
} else {
tar zxf $packagePath -C $Destination
tar zxf $packagePath -C $contentPath
}
}
Remove-Destination $Destination
if (Test-Path $Destination) {
Write-Verbose "Copying files" -Verbose
# only copy files as folders will already exist at $Destination
Get-ChildItem -Recurse -Path "$contentPath" -File | ForEach-Object {
$DestinationFilePath = Join-Path $Destination $_.fullname.replace($contentPath,"")
Copy-Item $_.fullname -Destination $DestinationFilePath
}
} else {
Move-Item -Path $contentPath -Destination $Destination
}
## Change the mode of 'pwsh' to 'rwxr-xr-x' to allow execution
if (-not $IsWinEnv) { chmod 755 "$Destination/pwsh" }
if (-not $IsWinEnv) { chmod 755 $Destination/pwsh }
if ($AddToPath) {
if ($IsWinEnv -and (-not $env:Path.Contains($Destination))) {
@@ -179,6 +207,9 @@ try {
}
Write-Host "PowerShell Core has been installed at $Destination" -ForegroundColor Green
if ($Destination -eq $PSHome) {
Write-Host "Please restart pwsh" -ForegroundColor Magenta
}
} finally {
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}