mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user