Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decompress.ps1: Rewrite extract_xxx functions #3204

Merged
merged 18 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 183 additions & 98 deletions lib/decompress.ps1
Original file line number Diff line number Diff line change
@@ -1,123 +1,208 @@
function requires_7zip($manifest, $architecture) {
foreach($dlurl in @(url $manifest $architecture)) {
if(file_requires_7zip $dlurl) { return $true }
function Test-7ZipRequirement {
[CmdletBinding(DefaultParameterSetName = "URL")]
[OutputType([Boolean])]
param(
[Parameter(Mandatory = $true, ParameterSetName = "URL")]
[String[]]
$URL,
[Parameter(Mandatory = $true, ParameterSetName = "File")]
[String]
$File
)
if ($URL) {
if (get_config 7ZIPEXTRACT_USE_EXTERNAL) {
return $false
} else {
return ($URL | Where-Object { Test-7ZipRequirement -File $_ }).Count -gt 0
}
} else {
return $File -match '\.((gz)|(tar)|(tgz)|(lzma)|(bz)|(bz2)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))$'
}
}

function requires_lessmsi ($manifest, $architecture) {
$useLessMsi = get_config MSIEXTRACT_USE_LESSMSI
if (!$useLessMsi) { return $false }

$(url $manifest $architecture | Where-Object {
$_ -match '\.(msi)$'
} | Measure-Object | Select-Object -exp count) -gt 0
}

function file_requires_7zip($fname) {
$fname -match '\.((gz)|(tar)|(tgz)|(lzma)|(bz)|(bz2)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))$'
}

function extract_7zip($path, $to, $recurse) {
$output = 7z x "$path" -o"$to" -y
if($lastexitcode -ne 0) { abort "Exit code was $lastexitcode." }

# check for tar
$tar = (split-path $path -leaf) -replace '\.[^\.]*$', ''
if($tar -match '\.tar$') {
if(test-path "$to\$tar") { extract_7zip "$to\$tar" $to $true }
function Test-LessMSIRequirement {
[CmdletBinding()]
[OutputType([Boolean])]
param(
[Parameter(Mandatory = $true)]
[String[]]
$URL
)
if (get_config MSIEXTRACT_USE_LESSMSI) {
return ($URL | Where-Object { $_ -match '\.msi$' }).Count -gt 0
} else {
return $false
}

if($recurse) { Remove-Item $path } # clean up intermediate files
}

function extract_msi($path, $to) {
$logfile = "$(split-path $path)\msi.log"
$ok = run 'msiexec' @('/a', "`"$path`"", '/qn', "TARGETDIR=`"$to`"", "/lwe `"$logfile`"")
if(!$ok) { abort "Failed to extract files from $path.`nLog file:`n $(friendly_path $logfile)" }
if(test-path $logfile) { Remove-Item $logfile }
}

function lessmsi_config ($extract_dir) {
$extract_fn = 'extract_lessmsi'
if ($extract_dir) {
$extract_dir = join-path SourceDir $extract_dir
function Expand-7ZipArchive {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[String]
$Path,
[Parameter(Position = 1)]
[String]
$DestinationPath = (Split-Path $Path),
[Switch]
$Removal
)
$LogLocation = "$(Split-Path $Path)\7zip.log"
if (get_config 7ZIPEXTRACT_USE_EXTERNAL) {
try {
7z x "$Path" -o"$DestinationPath" -y | Out-File $LogLocation
} catch [System.Management.Automation.CommandNotFoundException] {
abort "Cannot find external 7Zip (7z.exe) while '7ZIPEXTRACT_USE_EXTERNAL' is 'true'!`nRun 'scoop config 7ZIPEXTRACT_USE_EXTERNAL false' or install 7Zip manually and try again."
}
} else {
$extract_dir = "SourceDir"
&(file_path 7zip 7z.exe) x "$Path" -o"$DestinationPath" -y | Out-File $LogLocation
}
if ($LASTEXITCODE -ne 0) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogLocation)"
}
if (Test-Path $LogLocation) {
Remove-Item $LogLocation -Force
}
if ((strip_ext $Path) -match '\.tar$' -or $Path -match '\.tgz$') {
# Check for tar
$ArchivedFile = &(file_path 7zip 7z.exe) l "$Path"
if ($LASTEXITCODE -eq 0) {
$TarFile = $ArchivedFile[-3] -replace '.{53}(.*)', '$1' # get inner tar file name
Expand-7ZipArchive "$DestinationPath\$TarFile" $DestinationPath -Removal
} else {
abort "Failed to list files in $Path.`nNot a 7Zip supported archive file."
}
}
if ($Removal) {
# Remove original archive file
Remove-Item $Path -Force
}

$extract_fn, $extract_dir
}

function extract_lessmsi($path, $to) {
Invoke-Expression "lessmsi x `"$path`" `"$to\`""
function Expand-MSIArchive {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[String]
$Path,
[Parameter(Position = 1)]
[String]
$DestinationPath = (Split-Path $Path),
[Switch]
$Removal
)
$LogLocation = "$(Split-Path $Path)\msi.log"
if (get_config MSIEXTRACT_USE_LESSMSI) {
&(file_path lessmsi lessmsi.exe) x "$Path" "$DestinationPath\" | Out-File $LogLocation
if ($LASTEXITCODE -ne 0) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogLocation)"
}
if (Test-Path "$DestinationPath\SourceDir") {
movedir "$DestinationPath\SourceDir" "$DestinationPath" | Out-Null
}
} else {
$ok = run 'msiexec' @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath`"", "/lwe `"$LogLocation`"")
if (!$ok) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogLocation)"
}
Remove-Item "$DestinationPath\$(fname $Path)" -Force
}
if (Test-Path $LogLocation) {
Remove-Item $LogLocation -Force
}
if ($Removal) {
# Remove original archive file
Remove-Item $Path -Force
}
}

function unpack_inno($fname, $manifest, $dir) {
if (!$manifest.innosetup) { return }

write-host "Unpacking innosetup... " -nonewline
innounp -x -d"$dir\_scoop_unpack" "$dir\$fname" > "$dir\innounp.log"
if ($lastexitcode -ne 0) {
abort "Failed to unpack innosetup file. See $dir\innounp.log"
function Expand-InnoArchive {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[String]
$Path,
[Parameter(Position = 1)]
[String]
$DestinationPath = (Split-Path $Path),
[Switch]
$Removal
)
$LogLocation = "$(Split-Path $Path)\innounp.log"
&(file_path innounp innounp.exe) -x -d"$DestinationPath" -c'{app}' "$Path" -y | Out-File $LogLocation
if ($LASTEXITCODE -ne 0) {
abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogLocation)"
}
if (Test-Path $LogLocation) {
Remove-Item $LogLocation -Force
}
if ($Removal) {
# Remove original archive file
Remove-Item $Path -Force
}

Get-ChildItem "$dir\_scoop_unpack\{app}" -r | Move-Item -dest "$dir" -force

Remove-Item -r -force "$dir\_scoop_unpack"

Remove-Item "$dir\$fname"
Write-Host "done." -f Green
}

function extract_zip($path, $to) {
if (!(test-path $path)) { abort "can't find $path to unzip"}
try { add-type -assembly "System.IO.Compression.FileSystem" -ea stop }
catch { unzip_old $path $to; return } # for .net earlier than 4.5
$retries = 0
while ($retries -le 10) {
if ($retries -eq 10) {
function Expand-ZipArchive {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[String]
$Path,
[Parameter(Position = 1)]
[String]
$DestinationPath = (Split-Path $Path),
[Switch]
$Removal
)
# All methods to unzip the file require .NET4.5+
if ($PSVersionTable.PSVersion.Major -lt 5) {
Add-Type -AssemblyName System.IO.Compression.FileSystem
try {
[System.IO.Compression.ZipFile]::ExtractToDirectory($Path, $DestinationPath)
} catch [System.IO.PathTooLongException] {
# try to fall back to 7zip if path is too long
if (7zip_installed) {
extract_7zip $path $to $false
Expand-7ZipArchive $Path $DestinationPath -Removal
return
} else {
abort "Unzip failed: Windows can't unzip because a process is locking the file.`nRun 'scoop install 7zip' and try again."
abort "Unzip failed: Windows can't handle the long paths in this zip file.`nRun 'scoop install 7zip' and try again."
}
} catch [System.IO.IOException] {
if (7zip_installed) {
Expand-7ZipArchive $Path $DestinationPath -Removal
return
} else {
abort "Unzip failed: Windows can't handle the file names in this zip file.`nRun 'scoop install 7zip' and try again."
}
} catch {
abort "Unzip failed: $_"
}
if (isFileLocked $path) {
write-host "Waiting for $path to be unlocked by another process... ($retries/10)"
$retries++
Start-Sleep -s 2
} else {
break
}
} else {
# Use Expand-Archive to unzip in PowerShell 5+
Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force
}

try {
[io.compression.zipfile]::extracttodirectory($path, $to)
} catch [system.io.pathtoolongexception] {
# try to fall back to 7zip if path is too long
if (7zip_installed) {
extract_7zip $path $to $false
return
} else {
abort "Unzip failed: Windows can't handle the long paths in this zip file.`nRun 'scoop install 7zip' and try again."
}
} catch [system.io.ioexception] {
if (7zip_installed) {
extract_7zip $path $to $false
return
} else {
abort "Unzip failed: Windows can't handle the file names in this zip file.`nRun 'scoop install 7zip' and try again."
}
} catch {
abort "Unzip failed: $_"
if ($Removal) {
# Remove original archive file
Remove-Item $Path -Force
}
}

function unzip_old($path, $to) {
# fallback for .net earlier than 4.5
$shell = (new-object -com shell.application -strict)
$zipfiles = $shell.namespace("$path").items()
$to = ensure $to
$shell.namespace("$to").copyHere($zipfiles, 4) # 4 = don't show progress dialog
function extract_7zip($path, $to, $removal) {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
Show-DeprecationMessage $MyInvocation 'Expand-7ZipArchive'
Expand-7ZipArchive -Path $path -DestinationPath $to -Removal:$removal
}

function extract_msi($path, $to, $removal) {
Show-DeprecationMessage $MyInvocation 'Expand-MSIArchive'
Expand-MSIArchive -Path $path -DestinationPath $to -Removal:$removal
}

function extract_inno($path, $to, $removal) {
Show-DeprecationMessage $MyInvocation 'Expand-InnoArchive'
Expand-InnoArchive -Path $path -DestinationPath $to -Removal:$removal
}

function extract_zip($path, $to, $removal) {
Show-DeprecationMessage $MyInvocation 'Expand-ZipArchive'
Expand-ZipArchive -Path $path -DestinationPath $to -Removal:$removal
}
26 changes: 12 additions & 14 deletions lib/depends.ps1
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# resolve dependencies for the supplied apps, and sort into the correct order
function install_order($apps, $arch) {
$res = @()
foreach($app in $apps) {
foreach($dep in deps $app $arch) {
if($res -notcontains $dep) { $res += $dep}
foreach ($app in $apps) {
foreach ($dep in deps $app $arch) {
if ($res -notcontains $dep) { $res += $dep}
}
if($res -notcontains $app) { $res += $app }
if ($res -notcontains $app) { $res += $app }
}
return $res
}
Expand All @@ -15,7 +15,7 @@ function deps($app, $arch) {
$resolved = new-object collections.arraylist
dep_resolve $app $arch $resolved @()

if($resolved.count -eq 1) { return @() } # no dependencies
if ($resolved.count -eq 1) { return @() } # no dependencies
return $resolved[0..($resolved.count - 2)]
}

Expand All @@ -33,9 +33,9 @@ function dep_resolve($app, $arch, $resolved, $unresolved) {

$deps = @(install_deps $manifest $arch) + @(runtime_deps $manifest) | Select-Object -Unique

foreach($dep in $deps) {
if($resolved -notcontains $dep) {
if($unresolved -contains $dep) {
foreach ($dep in $deps) {
if ($resolved -notcontains $dep) {
if ($unresolved -contains $dep) {
abort "Circular dependency detected: '$app' -> '$dep'."
}
dep_resolve $dep $arch $resolved $unresolved
Expand All @@ -46,17 +46,15 @@ function dep_resolve($app, $arch, $resolved, $unresolved) {
}

function runtime_deps($manifest) {
if($manifest.depends) { return $manifest.depends }
if ($manifest.depends) { return $manifest.depends }
}

function install_deps($manifest, $arch) {
$deps = @()

if((requires_7zip $manifest $arch) -and !(7zip_installed)) {
$deps += '7zip'
}
if(requires_lessmsi $manifest $arch) { $deps += 'lessmsi' }
if($manifest.innosetup) { $deps += 'innounp' }
if (Test-7ZipRequirement -URL (url $manifest $arch)) { $deps += '7zip' }
if (Test-LessMSIRequirement -URL (url $manifest $arch)) { $deps += 'lessmsi' }
if ($manifest.innosetup) { $deps += 'innounp' }

return $deps
}
Loading