mirror of
https://github.com/ScoopInstaller/Scoop.git
synced 2025-12-02 22:32:37 +00:00
355 lines
12 KiB
PowerShell
355 lines
12 KiB
PowerShell
# Description: Functions for decompressing archives or installers
|
|
|
|
function Invoke-Extraction {
|
|
param (
|
|
[string]
|
|
$Path,
|
|
[string[]]
|
|
$Name,
|
|
[psobject]
|
|
$Manifest,
|
|
[Alias('Arch', 'Architecture')]
|
|
[string]
|
|
$ProcessorArchitecture
|
|
)
|
|
|
|
$uri = @(url $Manifest $ProcessorArchitecture)
|
|
# 'extract_dir' and 'extract_to' are paired
|
|
$extractDir = @(extract_dir $Manifest $ProcessorArchitecture)
|
|
$extractTo = @(extract_to $Manifest $ProcessorArchitecture)
|
|
$extracted = 0
|
|
|
|
for ($i = 0; $i -lt $Name.Length; $i++) {
|
|
# work out extraction method, if applicable
|
|
$extractFn = $null
|
|
switch -regex ($Name[$i]) {
|
|
'\.zip$' {
|
|
if ((Test-HelperInstalled -Helper 7zip) -or ((get_config USE_EXTERNAL_7ZIP) -and (Test-CommandAvailable 7z))) {
|
|
$extractFn = 'Expand-7zipArchive'
|
|
} else {
|
|
$extractFn = 'Expand-ZipArchive'
|
|
}
|
|
continue
|
|
}
|
|
'\.msi$' {
|
|
$extractFn = 'Expand-MsiArchive'
|
|
continue
|
|
}
|
|
'\.exe$' {
|
|
if ($Manifest.innosetup) {
|
|
$extractFn = 'Expand-InnoArchive'
|
|
}
|
|
continue
|
|
}
|
|
{ Test-7zipRequirement -Uri $_ } {
|
|
$extractFn = 'Expand-7zipArchive'
|
|
continue
|
|
}
|
|
}
|
|
if ($extractFn) {
|
|
$fnArgs = @{
|
|
Path = Join-Path $Path $Name[$i]
|
|
DestinationPath = Join-Path $Path $extractTo[$extracted]
|
|
ExtractDir = $extractDir[$extracted]
|
|
}
|
|
Write-Host 'Extracting ' -NoNewline
|
|
Write-Host $(url_remote_filename $uri[$i]) -ForegroundColor Cyan -NoNewline
|
|
Write-Host ' ... ' -NoNewline
|
|
& $extractFn @fnArgs -Removal
|
|
Write-Host 'done.' -ForegroundColor Green
|
|
$extracted++
|
|
}
|
|
}
|
|
}
|
|
|
|
function Expand-7zipArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[String]
|
|
$ExtractDir,
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[String]
|
|
$Switches,
|
|
[ValidateSet('All', 'Skip', 'Rename')]
|
|
[String]
|
|
$Overwrite,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
if ((get_config USE_EXTERNAL_7ZIP)) {
|
|
try {
|
|
$7zPath = (Get-Command '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"
|
|
$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 ($Switches) {
|
|
$ArgList += (-split $Switches)
|
|
}
|
|
switch ($Overwrite) {
|
|
'All' { $ArgList += '-aoa' }
|
|
'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')"
|
|
}
|
|
if ($IsTar) {
|
|
# Check for tar
|
|
$Status = Invoke-ExternalCommand $7zPath @('l', $Path) -LogPath $LogPath
|
|
if ($Status) {
|
|
# 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
|
|
# 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
|
|
}
|
|
}
|
|
if (Test-Path $LogPath) {
|
|
Remove-Item $LogPath -Force
|
|
}
|
|
if ($Removal) {
|
|
if (($Path -replace '.*\.([^\.]*)$', '$1') -eq '001') {
|
|
# Remove splitted 7-zip archive parts
|
|
Get-ChildItem "$($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
|
|
}
|
|
}
|
|
}
|
|
|
|
function Expand-ZstdArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[String]
|
|
$ExtractDir,
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[String]
|
|
$Switches,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
# TODO: Remove this function after 2024/12/31
|
|
Show-DeprecatedWarning $MyInvocation 'Expand-7zipArchive'
|
|
Expand-7zipArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Switches $Switches -Removal:$Removal
|
|
}
|
|
|
|
function Expand-MsiArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[String]
|
|
$ExtractDir,
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[String]
|
|
$Switches,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
$DestinationPath = $DestinationPath.TrimEnd('\')
|
|
if ($ExtractDir) {
|
|
$OriDestinationPath = $DestinationPath
|
|
$DestinationPath = "$DestinationPath\_tmp"
|
|
}
|
|
if ((get_config USE_LESSMSI)) {
|
|
$MsiPath = Get-HelperPath -Helper Lessmsi
|
|
$ArgList = @('x', $Path, "$DestinationPath\")
|
|
} else {
|
|
$MsiPath = 'msiexec.exe'
|
|
$ArgList = @('/a', $Path, '/qn', "TARGETDIR=$DestinationPath\SourceDir")
|
|
}
|
|
$LogPath = "$(Split-Path $Path)\msi.log"
|
|
if ($Switches) {
|
|
$ArgList += (-split $Switches)
|
|
}
|
|
$Status = Invoke-ExternalCommand $MsiPath $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')"
|
|
}
|
|
if ($ExtractDir -and (Test-Path "$DestinationPath\SourceDir")) {
|
|
movedir "$DestinationPath\SourceDir\$ExtractDir" $OriDestinationPath | Out-Null
|
|
Remove-Item $DestinationPath -Recurse -Force
|
|
} elseif ($ExtractDir) {
|
|
movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null
|
|
Remove-Item $DestinationPath -Recurse -Force
|
|
} elseif (Test-Path "$DestinationPath\SourceDir") {
|
|
movedir "$DestinationPath\SourceDir" $DestinationPath | Out-Null
|
|
}
|
|
if (($DestinationPath -ne (Split-Path $Path)) -and (Test-Path "$DestinationPath\$(fname $Path)")) {
|
|
Remove-Item "$DestinationPath\$(fname $Path)" -Force
|
|
}
|
|
if (Test-Path $LogPath) {
|
|
Remove-Item $LogPath -Force
|
|
}
|
|
if ($Removal) {
|
|
# Remove original archive file
|
|
Remove-Item $Path -Force
|
|
}
|
|
}
|
|
|
|
function Expand-InnoArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[String]
|
|
$ExtractDir,
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[String]
|
|
$Switches,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
$LogPath = "$(Split-Path $Path)\innounp.log"
|
|
$ArgList = @('-x', "-d$DestinationPath", $Path, '-y')
|
|
switch -Regex ($ExtractDir) {
|
|
'^[^{].*' { $ArgList += "-c{app}\$ExtractDir" }
|
|
'^{.*' { $ArgList += "-c$ExtractDir" }
|
|
Default { $ArgList += '-c{app}' }
|
|
}
|
|
if ($Switches) {
|
|
$ArgList += (-split $Switches)
|
|
}
|
|
$Status = Invoke-ExternalCommand (Get-HelperPath -Helper Innounp) $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')"
|
|
}
|
|
if (Test-Path $LogPath) {
|
|
Remove-Item $LogPath -Force
|
|
}
|
|
if ($Removal) {
|
|
# Remove original archive file
|
|
Remove-Item $Path -Force
|
|
}
|
|
}
|
|
|
|
function Expand-ZipArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[String]
|
|
$ExtractDir,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
if ($ExtractDir) {
|
|
$OriDestinationPath = $DestinationPath
|
|
$DestinationPath = "$DestinationPath\_tmp"
|
|
}
|
|
# Disable progress bar to gain performance
|
|
$oldProgressPreference = $ProgressPreference
|
|
$global:ProgressPreference = 'SilentlyContinue'
|
|
|
|
# Compatible with Pscx v3 (https://github.com/Pscx/Pscx) ('Microsoft.PowerShell.Archive' is not needed for Pscx v4)
|
|
Microsoft.PowerShell.Archive\Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force
|
|
|
|
$global:ProgressPreference = $oldProgressPreference
|
|
if ($ExtractDir) {
|
|
movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null
|
|
Remove-Item $DestinationPath -Recurse -Force
|
|
}
|
|
if ($Removal) {
|
|
# Remove original archive file
|
|
Remove-Item $Path -Force
|
|
}
|
|
}
|
|
|
|
function Expand-DarkArchive {
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
|
[String]
|
|
$Path,
|
|
[Parameter(Position = 1)]
|
|
[String]
|
|
$DestinationPath = (Split-Path $Path),
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[String]
|
|
$Switches,
|
|
[Switch]
|
|
$Removal
|
|
)
|
|
$LogPath = "$(Split-Path $Path)\dark.log"
|
|
$DarkPath = Get-HelperPath -Helper Dark
|
|
if ((Split-Path $DarkPath -Leaf) -eq 'wix.exe') {
|
|
$ArgList = @('burn', 'extract', $Path, '-out', $DestinationPath, '-outba', "$DestinationPath\UX")
|
|
} else {
|
|
$ArgList = @('-nologo', '-x', $DestinationPath, $Path)
|
|
}
|
|
if ($Switches) {
|
|
$ArgList += (-split $Switches)
|
|
}
|
|
$Status = Invoke-ExternalCommand $DarkPath $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')"
|
|
}
|
|
if (Test-Path "$DestinationPath\WixAttachedContainer") {
|
|
Rename-Item "$DestinationPath\WixAttachedContainer" 'AttachedContainer' -ErrorAction Ignore
|
|
} else {
|
|
if (Test-Path "$DestinationPath\AttachedContainer\a0") {
|
|
$Xml = [xml](Get-Content -Raw "$DestinationPath\UX\manifest.xml" -Encoding utf8)
|
|
$Xml.BurnManifest.UX.Payload | ForEach-Object {
|
|
Rename-Item "$DestinationPath\UX\$($_.SourcePath)" $_.FilePath -ErrorAction Ignore
|
|
}
|
|
$Xml.BurnManifest.Payload | ForEach-Object {
|
|
Rename-Item "$DestinationPath\AttachedContainer\$($_.SourcePath)" $_.FilePath -ErrorAction Ignore
|
|
}
|
|
}
|
|
}
|
|
if (Test-Path $LogPath) {
|
|
Remove-Item $LogPath -Force
|
|
}
|
|
if ($Removal) {
|
|
# Remove original archive file
|
|
Remove-Item $Path -Force
|
|
}
|
|
}
|