From 19e1e3cb8359747458ec696d3925ba4429db77b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:12:01 +0200 Subject: [PATCH 1/8] Fix for Expand-7zipArchive --- lib/decompress.ps1 | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 3f174bf0c3..2a00e49dab 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -84,19 +84,25 @@ function Expand-7zipArchive { ) if ((get_config USE_EXTERNAL_7ZIP)) { try { - $7zPath = (Get-Command '7z' -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source + $7zPath = (Get-Command -Name '7z' -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source } catch [System.Management.Automation.CommandNotFoundException] { abort "`nCannot find external 7-Zip (7z.exe) while 'use_external_7zip' is 'true'!`nRun 'scoop config use_external_7zip false' or install 7-Zip manually and try again." } } else { $7zPath = Get-HelperPath -Helper 7zip } - $LogPath = "$(Split-Path $Path)\7zip.log" + $LogPath = "$(Split-Path -Path $Path)\7zip.log" + $IsTar = ((strip_ext -fname $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') $DestinationPath = $DestinationPath.TrimEnd('\') - $ArgList = @('x', $Path, "-o$DestinationPath", '-xr!*.nsis', '-y') - $IsTar = ((strip_ext $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') - if (!$IsTar -and $ExtractDir) { - $ArgList += "-ir!$ExtractDir\*" + if ($ExtractDir) { + $DestinationPathTemp = [System.IO.Path]::Combine($DestinationPath, [guid]::NewGuid().'Guid') + $ArgList = @('x', $Path, "-o$DestinationPathTemp", '-xr!*.nsis', '-y') + if (-not $IsTar) { + $ArgList += "-ir!$ExtractDir\*" + } + } + else { + $ArgList = @('x', $Path, "-o$DestinationPath", '-xr!*.nsis', '-y') } if ($Switches) { $ArgList += (-split $Switches) @@ -106,28 +112,25 @@ function Expand-7zipArchive { 'Skip' { $ArgList += '-aos' } 'Rename' { $ArgList += '-aou' } } - $Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath - if (!$Status) { - abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" + $Status = Invoke-ExternalCommand -FilePath $7zPath -ArgumentList $ArgList -LogPath $LogPath + if (-not $Status) { + abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path -path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" } if ($IsTar) { # Check for tar - $Status = Invoke-ExternalCommand $7zPath @('l', $Path) -LogPath $LogPath + $Status = Invoke-ExternalCommand -FilePath $7zPath -ArgumentList @('l', $Path) -LogPath $LogPath if ($Status) { - # get inner tar file name + # Get inner tar file name $TarFile = (Select-String -Path $LogPath -Pattern '[^ ]*tar$').Matches.Value Expand-7zipArchive -Path "$DestinationPath\$TarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal } else { abort "Failed to list files in $Path.`nNot a 7-Zip supported archive file." } } - if (!$IsTar -and $ExtractDir) { - movedir "$DestinationPath\$ExtractDir" $DestinationPath | Out-Null + if ($ExtractDir -and -not $IsTar) { + $null = movedir -from "$DestinationPathTemp\$ExtractDir" -to $DestinationPath # Remove temporary directory if it is empty - $ExtractDirTopPath = [string] "$DestinationPath\$($ExtractDir -replace '[\\/].*')" - if ((Get-ChildItem -Path $ExtractDirTopPath -Force -ErrorAction Ignore).Count -eq 0) { - Remove-Item -Path $ExtractDirTopPath -Recurse -Force -ErrorAction Ignore - } + Remove-Item -Path $DestinationPathTemp -Recurse -Force -ErrorAction Ignore } if (Test-Path $LogPath) { Remove-Item $LogPath -Force @@ -135,13 +138,13 @@ function Expand-7zipArchive { if ($Removal) { if (($Path -replace '.*\.([^\.]*)$', '$1') -eq '001') { # Remove splitted 7-zip archive parts - Get-ChildItem "$($Path -replace '\.[^\.]*$', '').???" | Remove-Item -Force + Get-ChildItem -Path "$($Path -replace '\.[^\.]*$', '').???" | Remove-Item -Force } elseif (($Path -replace '.*\.part(\d+)\.rar$', '$1')[-1] -eq '1') { # Remove splitted RAR archive parts Get-ChildItem "$($Path -replace '\.part(\d+)\.rar$', '').part*.rar" | Remove-Item -Force } else { # Remove original archive file - Remove-Item $Path -Force + Remove-Item -Path $Path -Force } } } From 48782a23e8a7ab447d40cb0ac1c3b4c02fbd3a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:19:56 +0200 Subject: [PATCH 2/8] Use shorter temp directory name, a GUID can be a bit long? --- lib/decompress.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 2a00e49dab..603f69dc3b 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -95,7 +95,7 @@ function Expand-7zipArchive { $IsTar = ((strip_ext -fname $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') $DestinationPath = $DestinationPath.TrimEnd('\') if ($ExtractDir) { - $DestinationPathTemp = [System.IO.Path]::Combine($DestinationPath, [guid]::NewGuid().'Guid') + $DestinationPathTemp = [System.IO.Path]::Combine($DestinationPath, '_tmp') $ArgList = @('x', $Path, "-o$DestinationPathTemp", '-xr!*.nsis', '-y') if (-not $IsTar) { $ArgList += "-ir!$ExtractDir\*" From 2db3db89508ab4894a0e271566e9753ba8c7dbf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:24:52 +0200 Subject: [PATCH 3/8] Both zip and 7z should extract to TEMP when ExtractDir --- lib/decompress.ps1 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 603f69dc3b..e4621e4e8a 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -95,7 +95,7 @@ function Expand-7zipArchive { $IsTar = ((strip_ext -fname $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') $DestinationPath = $DestinationPath.TrimEnd('\') if ($ExtractDir) { - $DestinationPathTemp = [System.IO.Path]::Combine($DestinationPath, '_tmp') + $DestinationPathTemp = [System.IO.Path]::Combine($env:TEMP, [guid]::NewGuid().'Guid') $ArgList = @('x', $Path, "-o$DestinationPathTemp", '-xr!*.nsis', '-y') if (-not $IsTar) { $ArgList += "-ir!$ExtractDir\*" @@ -128,12 +128,13 @@ function Expand-7zipArchive { } } if ($ExtractDir -and -not $IsTar) { + # Move content to destination path $null = movedir -from "$DestinationPathTemp\$ExtractDir" -to $DestinationPath - # Remove temporary directory if it is empty + # Remove temporary directory Remove-Item -Path $DestinationPathTemp -Recurse -Force -ErrorAction Ignore } - if (Test-Path $LogPath) { - Remove-Item $LogPath -Force + if (Test-Path -Path $LogPath -PathType 'Leaf') { + Remove-Item -Path $LogPath -Force } if ($Removal) { if (($Path -replace '.*\.([^\.]*)$', '$1') -eq '001') { @@ -283,9 +284,10 @@ function Expand-ZipArchive { [Switch] $Removal ) + $DestinationPath = [string] $DestinationPath.TrimEnd('\') if ($ExtractDir) { - $OriDestinationPath = $DestinationPath - $DestinationPath = "$DestinationPath\_tmp" + $OriDestinationPath = [string] $DestinationPath + $DestinationPath = [string] [System.IO.Path]::Combine($env:TEMP, [guid]::NewGuid().'Guid') } # Disable progress bar to gain performance $oldProgressPreference = $ProgressPreference From 0192d79451b4fd3774f70fc369e28bb07fd2a676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:25:37 +0200 Subject: [PATCH 4/8] Add named parameters and use $null = instead of | Out-Null --- lib/decompress.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index e4621e4e8a..b1122a6a9c 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -298,12 +298,12 @@ function Expand-ZipArchive { $global:ProgressPreference = $oldProgressPreference if ($ExtractDir) { - movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null - Remove-Item $DestinationPath -Recurse -Force + $null = movedir "$DestinationPath\$ExtractDir" $OriDestinationPath + Remove-Item -Path $DestinationPath -Recurse -Force } if ($Removal) { # Remove original archive file - Remove-Item $Path -Force + Remove-Item -Path $Path -Force } } From 5d3912095f834d3d2ced8e807715385d31b7acf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:34:36 +0200 Subject: [PATCH 5/8] Added changelog item --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9875359d01..04baf287f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) +- **decompress:** Expand to temp directory if `$ExpandDir` is specified with `Expand-7zipArchive` and `Expand-ZipArchive`, to make it more robust ([#6515](https://github.com/ScoopInstaller/Scoop/issues/6515)) ### Code Refactoring From 5b8b2486d2c831ea9843bcb773c70a258ce1f445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 18:55:00 +0200 Subject: [PATCH 6/8] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d26fe6d7b6..104dd76df3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) -- **decompress:** Expand to temp directory if `$ExpandDir` is specified with `Expand-7zipArchive` and `Expand-ZipArchive`, to make it more robust ([#6515](https://github.com/ScoopInstaller/Scoop/issues/6515)) +- **decompress:** Expand to temp directory if `$ExtractDir` is specified with `Expand-7zipArchive` and `Expand-ZipArchive`, to make it more robust ([#6515](https://github.com/ScoopInstaller/Scoop/issues/6515)) ### Code Refactoring From ebfebbf10a3013246d854da34f6bc979143b123a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 19:05:27 +0200 Subject: [PATCH 7/8] Use the same logic as in Extract-ZipArchive --- lib/decompress.ps1 | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index b1122a6a9c..c23028f458 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -93,16 +93,14 @@ function Expand-7zipArchive { } $LogPath = "$(Split-Path -Path $Path)\7zip.log" $IsTar = ((strip_ext -fname $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') - $DestinationPath = $DestinationPath.TrimEnd('\') + $DestinationPath = [string] $DestinationPath.TrimEnd('\') if ($ExtractDir) { - $DestinationPathTemp = [System.IO.Path]::Combine($env:TEMP, [guid]::NewGuid().'Guid') - $ArgList = @('x', $Path, "-o$DestinationPathTemp", '-xr!*.nsis', '-y') - if (-not $IsTar) { - $ArgList += "-ir!$ExtractDir\*" - } + $OriDestinationPath = [string] $DestinationPath + $DestinationPath = [System.IO.Path]::Combine($env:TEMP, [guid]::NewGuid().'Guid') } - else { - $ArgList = @('x', $Path, "-o$DestinationPath", '-xr!*.nsis', '-y') + $ArgList = @('x', $Path, "-o$DestinationPath", '-xr!*.nsis', '-y') + if ($ExtractDir -and -not $IsTar) { + $ArgList += "-ir!$ExtractDir\*" } if ($Switches) { $ArgList += (-split $Switches) @@ -118,7 +116,7 @@ function Expand-7zipArchive { } if ($IsTar) { # Check for tar - $Status = Invoke-ExternalCommand -FilePath $7zPath -ArgumentList @('l', $Path) -LogPath $LogPath + $Status = Invoke-ExternalCommand -FilePath $7zPath -ArgumentList @('l', $Path) -LogPath $LogPath if ($Status) { # Get inner tar file name $TarFile = (Select-String -Path $LogPath -Pattern '[^ ]*tar$').Matches.Value @@ -128,10 +126,10 @@ function Expand-7zipArchive { } } if ($ExtractDir -and -not $IsTar) { - # Move content to destination path - $null = movedir -from "$DestinationPathTemp\$ExtractDir" -to $DestinationPath + # Move content to original destination path + $null = movedir -from "$DestinationPath\$ExtractDir" -to $OriDestinationPath # Remove temporary directory - Remove-Item -Path $DestinationPathTemp -Recurse -Force -ErrorAction Ignore + Remove-Item -Path $DestinationPath -Recurse -Force -ErrorAction Ignore } if (Test-Path -Path $LogPath -PathType 'Leaf') { Remove-Item -Path $LogPath -Force From 0a117c1b36ad665182e723e46553673471a13e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Mon, 13 Oct 2025 19:10:23 +0200 Subject: [PATCH 8/8] Highlight that this can be a breaking change in some instances --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 104dd76df3..5a8af357d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,11 @@ - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) + +### BREAKING CHANGE + - **decompress:** Expand to temp directory if `$ExtractDir` is specified with `Expand-7zipArchive` and `Expand-ZipArchive`, to make it more robust ([#6515](https://github.com/ScoopInstaller/Scoop/issues/6515)) + - Changes extraction semantics when `extract_dir` is used; manifests relying on post-extraction cleanup workarounds may need updates. ### Code Refactoring