diff --git a/CHANGELOG.md b/CHANGELOG.md index 633d595a07..90eef0570d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ - **decompress:** Fix nested Zstd archive extraction ([#4608](https://github.com/ScoopInstaller/Scoop/issues/4608)) - **shim:** Fix PS1 shim error when in different drive in PS7 ([#4614](https://github.com/ScoopInstaller/Scoop/issues/4614)) +### Code Refactoring + +- **depends:** Rewrite 'depends.ps1' ([#4638](https://github.com/ScoopInstaller/Scoop/issues/4638)) + ### Builds - **checkver:** Fix output with '-Version' ([#3774](https://github.com/ScoopInstaller/Scoop/issues/3774)) diff --git a/lib/core.ps1 b/lib/core.ps1 index 793b95cb78..d6e03bfd8c 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -314,7 +314,7 @@ function app_status($app, $global) { } $status.missing_deps = @() - $deps = @(runtime_deps $manifest) | Where-Object { + $deps = @($manifest.depends) | Where-Object { $app, $bucket, $null = parse_app $_ return !(installed $app) } diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 57d0ea57e3..695600ed14 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -1,58 +1,3 @@ -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)|(t[abgpx]z2?)|(lzma)|(bz2?)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))(\.[^.]+)?$' - } -} - -function Test-ZstdRequirement { - [CmdletBinding(DefaultParameterSetName = "URL")] - [OutputType([Boolean])] - param ( - [Parameter(Mandatory = $true, ParameterSetName = "URL")] - [String[]] - $URL, - [Parameter(Mandatory = $true, ParameterSetName = "File")] - [String] - $File - ) - if ($URL) { - return ($URL | Where-Object { Test-ZstdRequirement -File $_ }).Count -gt 0 - } else { - return $File -match '\.zst$' - } -} - -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 - } -} - function Expand-7zipArchive { [CmdletBinding()] param ( @@ -67,7 +12,7 @@ function Expand-7zipArchive { [Parameter(ValueFromRemainingArguments = $true)] [String] $Switches, - [ValidateSet("All", "Skip", "Rename")] + [ValidateSet('All', 'Skip', 'Rename')] [String] $Overwrite, [Switch] @@ -75,9 +20,9 @@ function Expand-7zipArchive { ) if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) { try { - $7zPath = (Get-Command '7z' -CommandType Application | Select-Object -First 1).Source + $7zPath = (Get-Command '7z' -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source } catch [System.Management.Automation.CommandNotFoundException] { - abort "Cannot find external 7-Zip (7z.exe) while '7ZIPEXTRACT_USE_EXTERNAL' is 'true'!`nRun 'scoop config 7ZIPEXTRACT_USE_EXTERNAL false' or install 7-Zip manually and try again." + abort "`nCannot find external 7-Zip (7z.exe) while '7ZIPEXTRACT_USE_EXTERNAL' is 'true'!`nRun 'scoop config 7ZIPEXTRACT_USE_EXTERNAL false' or install 7-Zip manually and try again." } } else { $7zPath = Get-HelperPath -Helper 7zip @@ -92,9 +37,9 @@ function Expand-7zipArchive { $ArgList += (-split $Switches) } switch ($Overwrite) { - "All" { $ArgList += "-aoa" } - "Skip" { $ArgList += "-aos" } - "Rename" { $ArgList += "-aou" } + 'All' { $ArgList += '-aoa' } + 'Skip' { $ArgList += '-aos' } + 'Rename' { $ArgList += '-aou' } } $Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath if (!$Status) { @@ -187,7 +132,7 @@ function Expand-MsiArchive { [Switch] $Removal ) - $DestinationPath = $DestinationPath.TrimEnd("\") + $DestinationPath = $DestinationPath.TrimEnd('\') if ($ExtractDir) { $OriDestinationPath = $DestinationPath $DestinationPath = "$DestinationPath\_tmp" @@ -248,9 +193,9 @@ function Expand-InnoArchive { $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}" } + '^[^{].*' { $ArgList += "-c{app}\$ExtractDir" } + '^{.*' { $ArgList += "-c$ExtractDir" } + Default { $ArgList += '-c{app}' } } if ($Switches) { $ArgList += (-split $Switches) @@ -286,34 +231,7 @@ function Expand-ZipArchive { $OriDestinationPath = $DestinationPath $DestinationPath = "$DestinationPath\_tmp" } - # 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 (Test-HelperInstalled -Helper 7zip) { - Expand-7zipArchive $Path $DestinationPath -Removal - 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 (Test-HelperInstalled -Helper 7zip) { - 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: $_" - } - } else { - # Use Expand-Archive to unzip in PowerShell 5+ - # Compatible with Pscx (https://github.com/Pscx/Pscx) - Microsoft.PowerShell.Archive\Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force - } + Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force if ($ExtractDir) { movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null Remove-Item $DestinationPath -Recurse -Force @@ -356,23 +274,3 @@ function Expand-DarkArchive { Remove-Item $Path -Force } } - -function extract_7zip($path, $to, $removal) { - Show-DeprecatedWarning $MyInvocation 'Expand-7zipArchive' - Expand-7zipArchive -Path $path -DestinationPath $to -Removal:$removal @args -} - -function extract_msi($path, $to, $removal) { - Show-DeprecatedWarning $MyInvocation 'Expand-MsiArchive' - Expand-MsiArchive -Path $path -DestinationPath $to -Removal:$removal -} - -function unpack_inno($path, $to, $removal) { - Show-DeprecatedWarning $MyInvocation 'Expand-InnoArchive' - Expand-InnoArchive -Path $path -DestinationPath $to -Removal:$removal @args -} - -function extract_zip($path, $to, $removal) { - Show-DeprecatedWarning $MyInvocation 'Expand-ZipArchive' - Expand-ZipArchive -Path $path -DestinationPath $to -Removal:$removal -} diff --git a/lib/depends.ps1 b/lib/depends.ps1 index e7404ff732..cd7f322117 100644 --- a/lib/depends.ps1 +++ b/lib/depends.ps1 @@ -1,107 +1,169 @@ -# 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} - } - if ($res -notcontains $app) { $res += $app } - } - return $res -} +function Get-Dependency { + <# + .SYNOPSIS + Get app's dependencies (with apps attached at the end). + .PARAMETER AppName + App's name + .PARAMETER Architecture + App's architecture + .PARAMETER Resolved + List of resolved dependencies (internal use) + .PARAMETER Unresolved + List of unresolved dependencies (internal use) + .OUTPUTS + [Object[]] + List of app's dependencies + .NOTES + When pipeline input is used, the output will have duplicate items, and should be filtered by 'Select-Object -Unique'. + ALgorithm: http://www.electricmonk.nl/docs/dependency_resolving_algorithm/dependency_resolving_algorithm.html + #> + [CmdletBinding()] + [OutputType([Object[]])] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [PSObject] + $AppName, + [Parameter(Mandatory = $true, Position = 1)] + [String] + $Architecture, + [String[]] + $Resolved = @(), + [String[]] + $Unresolved = @() + ) + process { + $AppName, $bucket, $null = parse_app $AppName + $Unresolved += $AppName + $null, $manifest, $null, $null = Find-Manifest $AppName $bucket -# http://www.electricmonk.nl/docs/dependency_resolving_algorithm/dependency_resolving_algorithm.html -function deps($app, $arch) { - $resolved = new-object collections.arraylist - dep_resolve $app $arch $resolved @() - - if ($resolved.count -eq 1) { return @() } # no dependencies - return $resolved[0..($resolved.count - 2)] -} - -function dep_resolve($app, $arch, $resolved, $unresolved) { - $app, $bucket, $null = parse_app $app - $unresolved += $app - $null, $manifest, $null, $null = Find-Manifest $app $bucket - - if(!$manifest) { - if(((Get-LocalBucket) -notcontains $bucket) -and $bucket) { - warn "Bucket '$bucket' not installed. Add it with 'scoop bucket add $bucket' or 'scoop bucket add $bucket '." + if (!$manifest) { + if (((Get-LocalBucket) -notcontains $bucket) -and $bucket) { + warn "Bucket '$bucket' not installed. Add it with 'scoop bucket add $bucket' or 'scoop bucket add $bucket '." + } + abort "Couldn't find manifest for '$AppName'$(if(!$bucket) { '.' } else { " from '$bucket' bucket." })" } - abort "Couldn't find manifest for '$app'$(if(!$bucket) { '.' } else { " from '$bucket' bucket." })" - } - $deps = @(install_deps $manifest $arch) + @(runtime_deps $manifest) | Select-Object -Unique + $deps = @(Get-InstallationHelper $manifest $Architecture) + @($manifest.depends) | Select-Object -Unique - foreach ($dep in $deps) { - if ($resolved -notcontains $dep) { - if ($unresolved -contains $dep) { - abort "Circular dependency detected: '$app' -> '$dep'." + foreach ($dep in $deps) { + if ($Resolved -notcontains $dep) { + if ($Unresolved -contains $dep) { + abort "Circular dependency detected: '$AppName' -> '$dep'." + } + $Resolved, $Unresolved = Get-Dependency $dep $Architecture -Resolved $Resolved -Unresolved $Unresolved } - dep_resolve $dep $arch $resolved $unresolved } - } - $resolved.add($app) | Out-Null - $unresolved = $unresolved -ne $app # remove from unresolved -} -function runtime_deps($manifest) { - if ($manifest.depends) { return $manifest.depends } -} - -function script_deps($script) { - $deps = @() - if($script -is [Array]) { - $script = $script -join "`n" - } - if([String]::IsNullOrEmpty($script)) { - return $deps + $Unresolved = $Unresolved -ne $AppName + $Resolved += $AppName + if ($Unresolved.Length -eq 0) { + return $Resolved + } else { + return $Resolved, $Unresolved + } } +} - if (!(Test-HelperInstalled -Helper 7zip) -and ($script -like '*Expand-7zipArchive *' -or $script -like '*extract_7zip *')) { - $deps += '7zip' - } - if (!(Test-HelperInstalled -Helper Lessmsi) -and ($script -like '*Expand-MsiArchive *' -or $script -like '*extract_msi *')) { - $deps += 'lessmsi' - } - if (!(Test-HelperInstalled -Helper Innounp) -and ($script -like '*Expand-InnoArchive *' -or $script -like '*unpack_inno *')) { - $deps += 'innounp' +function Get-InstallationHelper { + <# + .SYNOPSIS + Get helpers that used in installation + .PARAMETER Manifest + App's manifest + .PARAMETER Architecture + Architecture of the app + .PARAMETER All + If true, return all helpers, otherwise return only helpers that are not already installed + .OUTPUTS + [Object[]] + List of helpers + #> + [CmdletBinding()] + [OutputType([Object[]])] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [PSObject] + $Manifest, + [Parameter(Mandatory = $true, Position = 1)] + [String] + $Architecture, + [Switch] + $All + ) + begin { + $helper = @() } - if (!(Test-HelperInstalled -Helper Dark) -and $script -like '*Expand-DarkArchive *') { - $deps += 'dark' + process { + $url = arch_specific 'url' $Manifest $Architecture + if (!$url) { + $url = '' + } + $pre_install = arch_specific 'pre_install' $Manifest $Architecture + $installer = arch_specific 'installer' $Manifest $Architecture + $post_install = arch_specific 'post_install' $Manifest $Architecture + $script = $pre_install + $installer.script + $post_install + if (!$script) { + $script = '' + } + if (((Test-7zipRequirement -Uri $url) -or ($script -like '*Expand-7zipArchive *')) -and !(get_config 7ZIPEXTRACT_USE_EXTERNAL)) { + $helper += '7zip' + } + if (((Test-LessmsiRequirement -Uri $url) -or ($script -like '*Expand-MsiArchive *')) -and (get_config MSIEXTRACT_USE_LESSMSI)) { + $helper += 'lessmsi' + } + if ($Manifest.innosetup -or ($script -like '*Expand-InnoArchive *')) { + $helper += 'innounp' + } + if ($script -like '*Expand-DarkArchive *') { + $helper += 'dark' + } + if ((Test-ZstdRequirement -Uri $url) -or ($script -like '*Expand-ZstdArchive *')) { + $helper += 'zstd' + } + if (!$All) { + '7zip', 'lessmsi', 'innounp', 'dark', 'zstd' | ForEach-Object { + if (Test-HelperInstalled -Helper $_) { + $helper = $helper -ne $_ + } + } + } } - if (!(Test-HelperInstalled -Helper Zstd) -and $script -like '*Expand-ZstdArchive *') { - $deps += 'zstd' + end { + return $helper } - - return $deps } -function install_deps($manifest, $arch) { - $deps = @() - - $test_url = script:url $manifest $arch - if (-not $test_url) { $test_url = " " } - - if (!(Test-HelperInstalled -Helper 7zip) -and (Test-7zipRequirement -URL $test_url)) { - $deps += '7zip' - } - if (!(Test-HelperInstalled -Helper Lessmsi) -and (Test-LessmsiRequirement -URL $test_url)) { - $deps += 'lessmsi' - } - if (!(Test-HelperInstalled -Helper Innounp) -and $manifest.innosetup) { - $deps += 'innounp' - } - if (!(Test-HelperInstalled -Helper Zstd) -and (Test-ZstdRequirement -URL $test_url)) { - $deps += 'zstd' - } +function Test-7zipRequirement { + [CmdletBinding()] + [OutputType([Boolean])] + param ( + [Parameter(Mandatory = $true)] + [String[]] + $Uri + ) + return ($Uri | Where-Object { + $_ -match '\.((gz)|(tar)|(t[abgpx]z2?)|(lzma)|(bz2?)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))(\.[^.]+)?$' + }).Count -gt 0 +} - $pre_install = arch_specific 'pre_install' $manifest $arch - $installer = arch_specific 'installer' $manifest $arch - $post_install = arch_specific 'post_install' $manifest $arch - $deps += script_deps $pre_install - $deps += script_deps $installer.script - $deps += script_deps $post_install +function Test-ZstdRequirement { + [CmdletBinding()] + [OutputType([Boolean])] + param ( + [Parameter(Mandatory = $true)] + [String[]] + $Uri + ) + return ($Uri | Where-Object { $_ -match '\.zst$' }).Count -gt 0 +} - return $deps | Select-Object -Unique +function Test-LessmsiRequirement { + [CmdletBinding()] + [OutputType([Boolean])] + param ( + [Parameter(Mandatory = $true)] + [String[]] + $Uri + ) + return ($Uri | Where-Object { $_ -match '\.msi$' }).Count -gt 0 } diff --git a/lib/install.ps1 b/lib/install.ps1 index 88c1e8a0ae..4d05ca6c18 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -608,9 +608,9 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c } else { $extract_fn = 'Expand-MsiArchive' } - } elseif(Test-ZstdRequirement -File $fname) { # Zstd first + } elseif(Test-ZstdRequirement -Uri $fname) { # Zstd first $extract_fn = 'Expand-ZstdArchive' - } elseif(Test-7zipRequirement -File $fname) { # 7zip + } elseif(Test-7zipRequirement -Uri $fname) { # 7zip $extract_fn = 'Expand-7zipArchive' } @@ -1088,8 +1088,9 @@ function failed($app, $global) { function ensure_none_failed($apps, $global) { foreach($app in $apps) { - if(failed $app $global) { - abort "'$app' install failed previously. Please uninstall it and try again." + if (failed $app $global) { + warn "Purging previous failed installation of $app." + & "$PSScriptRoot\..\libexec\scoop-uninstall.ps1" $app$(if ($global) { ' --global' }) } } } diff --git a/libexec/scoop-depends.ps1 b/libexec/scoop-depends.ps1 index 50193ccdfd..a88831276f 100644 --- a/libexec/scoop-depends.ps1 +++ b/libexec/scoop-depends.ps1 @@ -23,7 +23,7 @@ try { abort "ERROR: $_" } -$deps = @(deps $app $architecture) +$deps = @(Get-Dependency $app $architecture) -ne $app if($deps) { $deps[($deps.length - 1)..0] } diff --git a/libexec/scoop-install.ps1 b/libexec/scoop-install.ps1 index efce325b9a..955799de8c 100644 --- a/libexec/scoop-install.ps1 +++ b/libexec/scoop-install.ps1 @@ -114,7 +114,7 @@ $apps = @(($specific_versions_paths + $difference) | Where-Object { $_ } | Sort- $explicit_apps = $apps if (!$independent) { - $apps = install_order $apps $architecture # adds dependencies + $apps = $apps | Get-Dependency -Architecture $architecture | Select-Object -Unique # adds dependencies } ensure_none_failed $apps $global diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index c307b7435d..dab1570efa 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -168,14 +168,8 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c } $url = $install.url - if (!$independent) { - # check dependencies - $man = if ($url) { $url } else { $app } - $deps = @(deps $man $architecture) | Where-Object { !(installed $_) } - $deps | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash } - } - - $version = Get-LatestVersion -AppName $app -Bucket $bucket -Uri $url + $manifest = manifest $app $bucket $url + $version = $manifest.version $is_nightly = $version -eq 'nightly' if ($is_nightly) { $version = nightly_version $(get-date) $quiet @@ -194,8 +188,6 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c return } - $manifest = manifest $app $bucket $url - write-host "Updating '$app' ($old_version -> $version)" # region Workaround @@ -275,7 +267,14 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c # use the url of the install json if the application was installed through url $app = $install.url } - install_app $app $architecture $global $suggested $use_cache $check_hash + + if ($independent) { + install_app $app $architecture $global $suggested $use_cache $check_hash + } else { + # Also add missing dependencies + $apps = @(Get-Dependency $app $architecture) | Where-Object { !(installed $_) } + $apps | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash } + } } if (-not ($apps -or $all)) { diff --git a/libexec/scoop-virustotal.ps1 b/libexec/scoop-virustotal.ps1 index ff461dbb42..f0535dbbe9 100644 --- a/libexec/scoop-virustotal.ps1 +++ b/libexec/scoop-virustotal.ps1 @@ -66,8 +66,8 @@ if($apps_param -eq '*') { $apps += installed_apps $true } -if (!$opt.n -and !$opt."no-depends") { - $apps = install_order $apps $architecture +if (!$opt.n -and !$opt.'no-depends') { + $apps = $apps | Get-Dependency -Architecture $architecture | Select-Object -Unique } $_ERR_UNSAFE = 2 diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index a80041f6b3..cad7d2a8f8 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -6,17 +6,18 @@ $isUnix = is_unix -function test_extract($extract_fn, $from, $removal) { - $to = (strip_ext $from) -replace '\.tar$', '' - & $extract_fn ($from -replace '/', '\') ($to -replace '/', '\') -Removal:$removal - return $to -} - Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { + BeforeAll { $working_dir = setup_working 'decompress' - It "Decompression test cases should exist" { + function test_extract($extract_fn, $from, $removal) { + $to = (strip_ext $from) -replace '\.tar$', '' + & $extract_fn ($from -replace '/', '\') ($to -replace '/', '\') -Removal:$removal + return $to + } + + It 'Decompression test cases should exist' { $testcases = "$working_dir\TestCases.zip" $testcases | Should -Exist compute_hash $testcases 'sha256' | Should -Be '3a442e85b466833eeafbd08c57d8f51bf7ff041867ee0bdb7db1f12480b3624a' @@ -26,7 +27,7 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { } } - Context "7zip extraction" { + Context '7zip extraction' { BeforeAll { if ($env:CI) { @@ -40,42 +41,42 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test4 = "$working_dir\7ZipTest4.tar.gz" } - It "extract normal compressed file" -Skip:$isUnix { - $to = test_extract "Expand-7zipArchive" $test1 + It 'extract normal compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-7zipArchive' $test1 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "extract nested compressed file" -Skip:$isUnix { + It 'extract nested compressed file' -Skip:$isUnix { # file ext: tgz - $to = test_extract "Expand-7zipArchive" $test2 + $to = test_extract 'Expand-7zipArchive' $test2 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 # file ext: tar.bz2 - $to = test_extract "Expand-7zipArchive" $test3 + $to = test_extract 'Expand-7zipArchive' $test3 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "extract nested compressed file with different inner name" -Skip:$isUnix { - $to = test_extract "Expand-7zipArchive" $test4 + It 'extract nested compressed file with different inner name' -Skip:$isUnix { + $to = test_extract 'Expand-7zipArchive' $test4 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test1 | Should -Exist - test_extract "Expand-7zipArchive" $test1 $true + test_extract 'Expand-7zipArchive' $test1 $true $test1 | Should -Not -Exist } } - Context "zstd extraction" { + Context 'zstd extraction' { BeforeAll { if ($env:CI) { @@ -88,28 +89,28 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test2 = "$working_dir\ZstdTest.tar.zst" } - It "extract normal compressed file" -Skip:$isUnix { - $to = test_extract "Expand-ZstdArchive" $test1 + It 'extract normal compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-ZstdArchive' $test1 $to | Should -Exist "$to\ZstdTest" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "extract nested compressed file" -Skip:$isUnix { - $to = test_extract "Expand-ZstdArchive" $test2 + It 'extract nested compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-ZstdArchive' $test2 $to | Should -Exist "$to\ZstdTest" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test1 | Should -Exist - test_extract "Expand-ZstdArchive" $test1 $true + test_extract 'Expand-ZstdArchive' $test1 $true $test1 | Should -Not -Exist } } - Context "msi extraction" { + Context 'msi extraction' { BeforeAll { if ($env:CI) { @@ -121,29 +122,29 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test2 = "$working_dir\MSITestNull.msi" } - It "extract normal MSI file" -Skip:$isUnix { + It 'extract normal MSI file' -Skip:$isUnix { Mock get_config { $false } - $to = test_extract "Expand-MsiArchive" $test1 + $to = test_extract 'Expand-MsiArchive' $test1 $to | Should -Exist "$to\MSITest\empty" | Should -Exist (Get-ChildItem "$to\MSITest").Count | Should -Be 1 } - It "extract empty MSI file using lessmsi" -Skip:$isUnix { + It 'extract empty MSI file using lessmsi' -Skip:$isUnix { Mock get_config { $true } - $to = test_extract "Expand-MsiArchive" $test2 + $to = test_extract 'Expand-MsiArchive' $test2 $to | Should -Exist } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { Mock get_config { $false } $test1 | Should -Exist - test_extract "Expand-MsiArchive" $test1 $true + test_extract 'Expand-MsiArchive' $test1 $true $test1 | Should -Not -Exist } } - Context "inno extraction" { + Context 'inno extraction' { BeforeAll { if ($env:CI) { @@ -154,36 +155,36 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test = "$working_dir\InnoTest.exe" } - It "extract Inno Setup file" -Skip:$isUnix { - $to = test_extract "Expand-InnoArchive" $test + It 'extract Inno Setup file' -Skip:$isUnix { + $to = test_extract 'Expand-InnoArchive' $test $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test | Should -Exist - test_extract "Expand-InnoArchive" $test $true + test_extract 'Expand-InnoArchive' $test $true $test | Should -Not -Exist } } - Context "zip extraction" { + Context 'zip extraction' { BeforeAll { $test = "$working_dir\ZipTest.zip" } - It "extract compressed file" -Skip:$isUnix { - $to = test_extract "Expand-ZipArchive" $test + It 'extract compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-ZipArchive' $test $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test | Should -Exist - test_extract "Expand-ZipArchive" $test $true + test_extract 'Expand-ZipArchive' $test $true $test | Should -Not -Exist } } diff --git a/test/Scoop-Depends.Tests.ps1 b/test/Scoop-Depends.Tests.ps1 new file mode 100644 index 0000000000..96354efa67 --- /dev/null +++ b/test/Scoop-Depends.Tests.ps1 @@ -0,0 +1,58 @@ +. "$psscriptroot\Scoop-TestLib.ps1" +. "$psscriptroot\..\lib\depends.ps1" +. "$psscriptroot\..\lib\install.ps1" +. "$psscriptroot\..\lib\manifest.ps1" + +Describe 'Requirement function' -Tag 'Scoop' { + It 'Test 7zip requirement' { + Test-7zipRequirement -Uri 'test.xz' | Should -BeTrue + Test-7zipRequirement -Uri 'test.bin' | Should -BeFalse + Test-7zipRequirement -Uri @('test.xz', 'test.bin') | Should -BeTrue + } + It 'Test Zstd requirement' { + Test-ZstdRequirement -Uri 'test.zst' | Should -BeTrue + Test-ZstdRequirement -Uri 'test.bin' | Should -BeFalse + Test-ZstdRequirement -Uri @('test.zst', 'test.bin') | Should -BeTrue + } + It 'Test lessmsi requirement' { + Mock get_config { $true } + Test-LessmsiRequirement -Uri 'test.msi' | Should -BeTrue + Test-LessmsiRequirement -Uri 'test.bin' | Should -BeFalse + Test-LessmsiRequirement -Uri @('test.msi', 'test.bin') | Should -BeTrue + } +} + +Describe 'InstallationHelper function' -Tag 'Scoop' { + BeforeAll { + $working_dir = setup_working 'format/formated' + $manifest1 = parse_json (Join-Path $working_dir '3-array-with-single-and-multi.json') + $manifest2 = parse_json (Join-Path $working_dir '4-script-block.json') + Mock Test-HelperInstalled { $false } + } + It 'Get helpers from URL' { + Mock get_config { $true } + Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -Be @('lessmsi') + } + It 'Get helpers from script' { + Mock get_config { $false } + Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -Be @('7zip') + } + It 'Helpers reflect config changes' { + Mock get_config { $false } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' } + Mock get_config { $true } -ParameterFilter { $name -eq '7ZIPEXTRACT_USE_EXTERNAL' } + Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -BeNullOrEmpty + Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -BeNullOrEmpty + } + It 'Not return installed helpers' { + Mock get_config { $true } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' } + Mock get_config { $false } -ParameterFilter { $name -eq '7ZIPEXTRACT_USE_EXTERNAL' } + Mock Test-HelperInstalled { $true }-ParameterFilter { $Helper -eq '7zip' } + Mock Test-HelperInstalled { $false }-ParameterFilter { $Helper -eq 'Lessmsi' } + Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -Be @('lessmsi') + Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -BeNullOrEmpty + Mock Test-HelperInstalled { $false }-ParameterFilter { $Helper -eq '7zip' } + Mock Test-HelperInstalled { $true }-ParameterFilter { $Helper -eq 'Lessmsi' } + Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -BeNullOrEmpty + Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -Be @('7zip') + } +} diff --git a/test/fixtures/format/formated/4-script-block.json b/test/fixtures/format/formated/4-script-block.json index 1a0b651143..ace916f850 100644 --- a/test/fixtures/format/formated/4-script-block.json +++ b/test/fixtures/format/formated/4-script-block.json @@ -9,12 +9,12 @@ "architecture": { "64bit": { "installer": { - "script": "extract_7zip \"$dir\\app-64.7z\" \"$dir\"" + "script": "Expand-7zipArchive \"$dir\\app-64.7z\" \"$dir\"" } }, "32bit": { "installer": { - "script": "extract_7zip \"$dir\\app-32.7z\" \"$dir\"" + "script": "Expand-7zipArchive \"$dir\\app-32.7z\" \"$dir\"" } } }, diff --git a/test/fixtures/format/unformated/4-script-block.json b/test/fixtures/format/unformated/4-script-block.json index 5e4cc7523a..f02f33b171 100644 --- a/test/fixtures/format/unformated/4-script-block.json +++ b/test/fixtures/format/unformated/4-script-block.json @@ -10,14 +10,14 @@ "64bit": { "installer": { "script": [ - "extract_7zip \"$dir\\app-64.7z\" \"$dir\"" + "Expand-7zipArchive \"$dir\\app-64.7z\" \"$dir\"" ] } }, "32bit": { "installer": { "script": [ - "extract_7zip \"$dir\\app-32.7z\" \"$dir\"" + "Expand-7zipArchive \"$dir\\app-32.7z\" \"$dir\"" ] } }