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

refactor(install): Separate archive extraction from downloader #5951

Merged
merged 3 commits into from
May 12, 2024
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
- **system:** Fix argument passing to `Split-PathLikeEnvVar()` in deprecated `strip_path()` ([#5937](https://github.com/ScoopInstaller/Scoop/issues/5937))
- **scoop-cache:** Fix regression in 36026f18 ([#5944](https://github.com/ScoopInstaller/Scoop/issues/5944))

### Code Refactoring

- **install:** Separate archive extraction from downloader ([#5951](https://github.com/ScoopInstaller/Scoop/issues/5951))

## [v0.4.1](https://github.com/ScoopInstaller/Scoop/compare/v0.4.0...v0.4.1) - 2024-04-25

### Bug Fixes
Expand Down
68 changes: 68 additions & 0 deletions lib/decompress.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,71 @@
# Description: Functions for decompressing archives or installers

function Invoke-Extraction {
param (
[string]
$Path,
[string[]]
$Name,
[psobject]
$Manifest,
[Alias('Arch', 'Architecture')]
[string]
$ProcessorArchitecture
)

# 'url', 'extract_dir' and 'extract_to' are paired
$uri = @(url $Manifest $ProcessorArchitecture)
$extractDir = @(extract_dir $Manifest $ProcessorArchitecture)
$extractTo = @(extract_to $Manifest $ProcessorArchitecture)

for ($i = 0; $i -lt $Name.Length; $i++) {
$fnArgs = @{
Path = Join-Path $Path $Name[$i]
DestinationPath = Join-Path $Path $extractTo[$i]
ExtractDir = $extractDir[$i]
}
# work out extraction method, if applicable
$extractFn = $null
switch -regex ($fnArgs.Path) {
'\.zip$' {
if ((Test-HelperInstalled -Helper 7zip) -or ((get_config 7ZIPEXTRACT_USE_EXTERNAL) -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-ZstdRequirement -Uri $_ } {
# Check Zstd first
$extractFn = 'Expand-ZstdArchive'
continue
}
{ Test-7zipRequirement -Uri $_ } {
# Then check 7zip
$extractFn = 'Expand-7zipArchive'
continue
}
}
if ($extractFn) {
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
}
}
}

function Expand-7zipArchive {
[CmdletBinding()]
param (
Expand Down
55 changes: 5 additions & 50 deletions lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru
$persist_dir = persistdir $app $global

$fname = Invoke-ScoopDownload $app $version $manifest $bucket $architecture $dir $use_cache $check_hash
Invoke-Extraction -Path $dir -Name $fname -Manifest $manifest -ProcessorArchitecture $architecture
Invoke-HookScript -HookType 'pre_install' -Manifest $manifest -Arch $architecture

run_installer $fname $manifest $architecture $dir $global
run_installer @($fname)[-1] $manifest $architecture $dir $global
ensure_install_dir_not_in_path $dir $global
$dir = link_current $dir
create_shims $manifest $dir $global $architecture
Expand Down Expand Up @@ -539,21 +540,12 @@ function Invoke-ScoopDownload ($app, $version, $manifest, $bucket, $architecture
# we only want to show this warning once
if (!$use_cache) { warn 'Cache is being ignored.' }

# can be multiple urls: if there are, then installer should go last,
# so that $fname is set properly
# can be multiple urls: if there are, then installer should go last to make 'installer.args' section work
$urls = @(script:url $manifest $architecture)

# can be multiple cookies: they will be used for all HTTP requests.
$cookies = $manifest.cookie

$fname = $null

# extract_dir and extract_to in manifest are like queues: for each url that
# needs to be extracted, will get the next dir from the queue
$extract_dirs = @(extract_dir $manifest $architecture)
$extract_tos = @(extract_to $manifest $architecture)
$extracted = 0

# download first
if (Test-Aria2Enabled) {
Invoke-CachedAria2Download $app $version $manifest $architecture $dir $cookies $use_cache $check_hash
Expand Down Expand Up @@ -587,44 +579,7 @@ function Invoke-ScoopDownload ($app, $version, $manifest, $bucket, $architecture
}
}

foreach ($url in $urls) {
$fname = url_filename $url

$extract_dir = $extract_dirs[$extracted]
$extract_to = $extract_tos[$extracted]

# work out extraction method, if applicable
$extract_fn = $null
if ($manifest.innosetup) {
$extract_fn = 'Expand-InnoArchive'
} elseif ($fname -match '\.zip$') {
# Use 7zip when available (more fast)
if (((get_config USE_EXTERNAL_7ZIP) -and (Test-CommandAvailable 7z)) -or (Test-HelperInstalled -Helper 7zip)) {
$extract_fn = 'Expand-7zipArchive'
} else {
$extract_fn = 'Expand-ZipArchive'
}
} elseif ($fname -match '\.msi$') {
$extract_fn = 'Expand-MsiArchive'
} elseif (Test-ZstdRequirement -Uri $fname) {
# Zstd first
$extract_fn = 'Expand-ZstdArchive'
} elseif (Test-7zipRequirement -Uri $fname) {
# 7zip
$extract_fn = 'Expand-7zipArchive'
}

if ($extract_fn) {
Write-Host 'Extracting ' -NoNewline
Write-Host $fname -f Cyan -NoNewline
Write-Host ' ... ' -NoNewline
& $extract_fn -Path "$dir\$fname" -DestinationPath "$dir\$extract_to" -ExtractDir $extract_dir -Removal
Write-Host 'done.' -f Green
$extracted++
}
}

$fname # returns the last downloaded file
return $urls.ForEach({ url_filename $_ })
}

function cookie_header($cookies) {
Expand Down Expand Up @@ -710,7 +665,7 @@ function run_installer($fname, $manifest, $architecture, $dir, $global) {
return
}
if ($installer) {
$prog = "$dir\$(coalesce $installer.file "$fname")"
$prog = "$dir\$(coalesce $installer.file $fname)"
if (!(is_in_dir $dir $prog)) {
abort "Error in manifest: Installer $prog is outside the app directory."
}
Expand Down