diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d4c2a444..3299daaa2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ - **scoop-search:** Require files in 'bucket' dir for remote known buckets ([#4943](https://github.com/ScoopInstaller/Scoop/issues/4943)) - **update:** Prevent uninstall when update ([#4949](https://github.com/ScoopInstaller/Scoop/issues/4949)) +### Code Refactoring + +- **manifest:** Rename 'Find-Manifest()' to 'Get-Manifest() ([#4966](https://github.com/ScoopInstaller/Scoop/issues/4966)) + ### Documentation - **readme:** Update license badge ([#4929](https://github.com/ScoopInstaller/Scoop/issues/4929)) diff --git a/lib/buckets.ps1 b/lib/buckets.ps1 index 3314761b99..7254b7e592 100644 --- a/lib/buckets.ps1 +++ b/lib/buckets.ps1 @@ -72,39 +72,6 @@ function buckets { return Get-LocalBucket } -function Find-Manifest($app, $bucket) { - $manifest, $url = $null, $null - - # check if app is a URL or UNC path - if ($app -match '^(ht|f)tps?://|\\\\') { - $url = $app - $app = appname_from_url $url - $manifest = url_manifest $url - } else { - if ($bucket) { - $manifest = manifest $app $bucket - } else { - foreach ($bucket in Get-LocalBucket) { - $manifest = manifest $app $bucket - if ($manifest) { break } - } - } - - if (!$manifest) { - # couldn't find app in buckets: check if it's a local path - $path = $app - if (!$path.endswith('.json')) { $path += '.json' } - if (Test-Path $path) { - $url = "$(Resolve-Path $path)" - $app = appname_from_url $url - $manifest, $bucket = url_manifest $url - } - } - } - - return $app, $manifest, $bucket, $url -} - function Convert-RepositoryUri { [CmdletBinding()] param ( @@ -197,7 +164,7 @@ function rm_bucket($name) { } function new_issue_msg($app, $bucket, $title, $body) { - $app, $manifest, $bucket, $url = Find-Manifest $app $bucket + $app, $manifest, $bucket, $url = Get-Manifest "$bucket/$app" $url = known_bucket_repo $bucket $bucket_path = "$bucketsdir\$bucket" diff --git a/lib/core.ps1 b/lib/core.ps1 index b767469b66..d5917a49b3 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -941,11 +941,12 @@ function applist($apps, $global) { return ,@($apps | ForEach-Object { ,@($_, $global) }) } -function parse_app([string] $app) { - if($app -match '(?:(?[a-zA-Z0-9-_.]+)\/)?(?.*\.json$|[a-zA-Z0-9-_.]+)(?:@(?.*))?') { - return $matches['app'], $matches['bucket'], $matches['version'] +function parse_app([string]$app) { + if ($app -match '^(?:(?[a-zA-Z0-9-_.]+)/)?(?.*\.json$|[a-zA-Z0-9-_.]+)(?:@(?.*))?$') { + return $Matches['app'], $Matches['bucket'], $Matches['version'] + } else { + return $app, $null, $null } - return $app, $null, $null } function show_app($app, $bucket, $version) { diff --git a/lib/depends.ps1 b/lib/depends.ps1 index 99ca440bde..5f010f0119 100644 --- a/lib/depends.ps1 +++ b/lib/depends.ps1 @@ -32,9 +32,8 @@ function Get-Dependency { $Unresolved = @() ) process { - $AppName, $bucket, $null = parse_app $AppName + $AppName, $manifest, $bucket, $null = Get-Manifest $AppName $Unresolved += $AppName - $null, $manifest, $null, $null = Find-Manifest $AppName $bucket if (!$manifest) { if (((Get-LocalBucket) -notcontains $bucket) -and $bucket) { diff --git a/lib/install.ps1 b/lib/install.ps1 index ca4026db9d..648255fcdf 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -7,8 +7,7 @@ function nightly_version($date, $quiet = $false) { } function install_app($app, $architecture, $global, $suggested, $use_cache = $true, $check_hash = $true) { - $app, $bucket, $null = parse_app $app - $app, $manifest, $bucket, $url = Find-Manifest $app $bucket + $app, $manifest, $bucket, $url = Get-Manifest $app if(!$manifest) { abort "Couldn't find manifest for '$app'$(if($url) { " at the URL $url" })." diff --git a/lib/manifest.ps1 b/lib/manifest.ps1 index efc8701b56..3ad52483dd 100644 --- a/lib/manifest.ps1 +++ b/lib/manifest.ps1 @@ -22,13 +22,47 @@ function url_manifest($url) { $str | convertfrom-json } +function Get-Manifest($app) { + $bucket, $manifest, $url = $null + # check if app is a URL or UNC path + if ($app -match '^(ht|f)tps?://|\\\\') { + $url = $app + $app = appname_from_url $url + $manifest = url_manifest $url + } else { + $app, $bucket, $version = parse_app $app + if ($bucket) { + $manifest = manifest $app $bucket + } else { + foreach ($bucket in Get-LocalBucket) { + $manifest = manifest $app $bucket + if ($manifest) { + break + } + } + } + if (!$manifest) { + # couldn't find app in buckets: check if it's a local path + if (!$app.EndsWith('.json')) { + $app += '.json' + } + if (Test-Path $app) { + $url = Convert-Path $app + $app = appname_from_url $url + $manifest = url_manifest $url + } + } + } + return $app, $manifest, $bucket, $url +} + function manifest($app, $bucket, $url) { - if($url) { return url_manifest $url } + if ($url) { return url_manifest $url } parse_json (manifest_path $app $bucket) } function save_installed_manifest($app, $bucket, $dir, $url) { - if($url) { + if ($url) { $wc = New-Object Net.Webclient $wc.Headers.Add('User-Agent', (Get-UserAgent)) $wc.downloadstring($url) > "$dir\manifest.json" @@ -51,7 +85,7 @@ function save_install_info($info, $dir) { function install_info($app, $version, $global) { $path = "$(versiondir $app $version $global)\install.json" - if(!(test-path $path)) { return $null } + if (!(Test-Path $path)) { return $null } parse_json $path } @@ -73,20 +107,21 @@ function default_architecture { } function arch_specific($prop, $manifest, $architecture) { - if($manifest.architecture) { + if ($manifest.architecture) { $val = $manifest.architecture.$architecture.$prop - if($val) { return $val } # else fallback to generic prop + if ($val) { return $val } # else fallback to generic prop } - if($manifest.$prop) { return $manifest.$prop } + if ($manifest.$prop) { return $manifest.$prop } } function supports_architecture($manifest, $architecture) { return -not [String]::IsNullOrEmpty((arch_specific 'url' $manifest $architecture)) } -function generate_user_manifest($app, $bucket, $version) { # 'autoupdate.ps1' 'buckets.ps1' 'manifest.ps1' - $null, $manifest, $bucket, $null = Find-Manifest $app $bucket +function generate_user_manifest($app, $bucket, $version) { + # 'autoupdate.ps1' 'buckets.ps1' 'manifest.ps1' + $app, $manifest, $bucket, $null = Get-Manifest "$bucket/$app" if ("$($manifest.version)" -eq "$version") { return manifest_path $app $bucket } diff --git a/libexec/scoop-cat.ps1 b/libexec/scoop-cat.ps1 index be217ad79b..ea59d1c73c 100644 --- a/libexec/scoop-cat.ps1 +++ b/libexec/scoop-cat.ps1 @@ -4,12 +4,11 @@ param($app) . "$PSScriptRoot\..\lib\json.ps1" # 'ConvertToPrettyJson' -. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' if (!$app) { error ' missing'; my_usage; exit 1 } -$app, $bucket, $null = parse_app $app -$app, $manifest, $bucket, $url = Find-Manifest $app $bucket +$null, $manifest, $bucket, $url = Get-Manifest $app if ($manifest) { $style = get_config cat_style diff --git a/libexec/scoop-download.ps1 b/libexec/scoop-download.ps1 index faab60bb6b..846750eb97 100644 --- a/libexec/scoop-download.ps1 +++ b/libexec/scoop-download.ps1 @@ -18,7 +18,7 @@ . "$PSScriptRoot\..\lib\getopt.ps1" . "$PSScriptRoot\..\lib\json.ps1" # 'autoupdate.ps1' (indirectly) . "$PSScriptRoot\..\lib\autoupdate.ps1" # 'generate_user_manifest' (indirectly) -. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Find-Manifest' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Get-Manifest' . "$PSScriptRoot\..\lib\install.ps1" $opt, $apps, $err = getopt $args 'fhua:' 'force', 'no-hash-check', 'no-update-scoop', 'arch=' @@ -51,7 +51,7 @@ foreach ($curr_app in $apps) { $bucket = $version = $app = $manifest = $url = $null $app, $bucket, $version = parse_app $curr_app - $app, $manifest, $bucket, $url = Find-Manifest $app $bucket + $app, $manifest, $bucket, $url = Get-Manifest "$bucket/$app" info "Starting download for $app..." diff --git a/libexec/scoop-home.ps1 b/libexec/scoop-home.ps1 index 916b09af25..da495454ad 100644 --- a/libexec/scoop-home.ps1 +++ b/libexec/scoop-home.ps1 @@ -2,10 +2,10 @@ # Summary: Opens the app homepage param($app) -. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' if ($app) { - $null, $manifest, $bucket, $null = Find-Manifest $app + $null, $manifest, $bucket, $null = Get-Manifest $app if ($manifest) { if ($manifest.homepage) { Start-Process $manifest.homepage diff --git a/libexec/scoop-info.ps1 b/libexec/scoop-info.ps1 index ebd7b8d8c5..d4e186136e 100644 --- a/libexec/scoop-info.ps1 +++ b/libexec/scoop-info.ps1 @@ -4,7 +4,7 @@ # -v, --verbose Show full paths and URLs . "$PSScriptRoot\..\lib\getopt.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' . "$PSScriptRoot\..\lib\versions.ps1" # 'Get-InstalledVersion' $opt, $app, $err = getopt $args 'v' 'verbose' @@ -13,31 +13,21 @@ $verbose = $opt.v -or $opt.verbose if (!$app) { my_usage; exit 1 } -if ($app -match '^(ht|f)tps?://|\\\\') { - # check if $app is a URL or UNC path - $url = $app - $app = appname_from_url $url - $global = installed $app $true - $status = app_status $app $global - $manifest = url_manifest $url - $manifest_file = $url -} else { - # else $app is a normal app name - $global = installed $app $true - $app, $bucket, $null = parse_app $app - $status = app_status $app $global - $app, $manifest, $bucket, $url = Find-Manifest $app $bucket -} +$app, $manifest, $bucket, $url = Get-Manifest $app if (!$manifest) { abort "Could not find manifest for '$(show_app $app)' in local buckets." } +$global = installed $app $true +$status = app_status $app $global $install = install_info $app $status.version $global $status.installed = $bucket -and $install.bucket -eq $bucket $version_output = $manifest.version -if (!$manifest_file) { - $manifest_file = if ($bucket) { manifest_path $app $bucket } else { $url } +$manifest_file = if ($bucket) { + manifest_path $app $bucket +} else { + $url } if ($verbose) { diff --git a/libexec/scoop-install.ps1 b/libexec/scoop-install.ps1 index 9c11ddfce0..a0c856a502 100644 --- a/libexec/scoop-install.ps1 +++ b/libexec/scoop-install.ps1 @@ -20,7 +20,7 @@ . "$PSScriptRoot\..\lib\getopt.ps1" . "$PSScriptRoot\..\lib\json.ps1" # 'autoupdate.ps1' 'manifest.ps1' (indirectly) . "$PSScriptRoot\..\lib\autoupdate.ps1" # 'generate_user_manifest' (indirectly) -. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Select-CurrentVersion' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Get-Manifest' 'Select-CurrentVersion' (indirectly) . "$PSScriptRoot\..\lib\install.ps1" . "$PSScriptRoot\..\lib\decompress.ps1" . "$PSScriptRoot\..\lib\shortcuts.ps1" diff --git a/libexec/scoop-uninstall.ps1 b/libexec/scoop-uninstall.ps1 index df065b9e7e..44f5561db5 100644 --- a/libexec/scoop-uninstall.ps1 +++ b/libexec/scoop-uninstall.ps1 @@ -7,7 +7,7 @@ # -p, --purge Remove all persistent data . "$PSScriptRoot\..\lib\getopt.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" # 'Select-CurrentVersion' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' 'Select-CurrentVersion' (indirectly) . "$PSScriptRoot\..\lib\install.ps1" . "$PSScriptRoot\..\lib\shortcuts.ps1" . "$PSScriptRoot\..\lib\psmodules.ps1" diff --git a/libexec/scoop-virustotal.ps1 b/libexec/scoop-virustotal.ps1 index e3e847bad9..5be7a10f56 100644 --- a/libexec/scoop-virustotal.ps1 +++ b/libexec/scoop-virustotal.ps1 @@ -35,7 +35,7 @@ # -u, --no-update-scoop Don't update Scoop before checking if it's outdated . "$PSScriptRoot\..\lib\getopt.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly) +. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' . "$PSScriptRoot\..\lib\json.ps1" # 'json_path' . "$PSScriptRoot\..\lib\install.ps1" # 'hash_for_url' . "$PSScriptRoot\..\lib\depends.ps1" # 'Get-Dependency' @@ -155,8 +155,8 @@ Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying = $False) { $api_key = get_config virustotal_api_key if ($do_scan -and !$api_key -and !$warned_no_api_key) { $warned_no_api_key = $true - info "Submitting unknown apps needs a VirusTotal API key. " + - "Set it up with`n`tscoop config virustotal_api_key " + info 'Submitting unknown apps needs a VirusTotal API key. ' + + "Set it up with`n`tscoop config virustotal_api_key " } if (!$do_scan -or !$api_key) { @@ -167,14 +167,14 @@ Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying = $False) { try { # Follow redirections (for e.g. sourceforge URLs) because # VirusTotal analyzes only "direct" download links - $url = $url.Split("#").GetValue(0) + $url = $url.Split('#').GetValue(0) $new_redir = $url do { $orig_redir = $new_redir $new_redir = Submit-RedirectedUrl $orig_redir } while ($orig_redir -ne $new_redir) $requests += 1 - $result = Invoke-WebRequest -Uri "https://www.virustotal.com/vtapi/v2/url/scan" -Body @{apikey=$api_key;url=$new_redir} -Method Post -UseBasicParsing + $result = Invoke-WebRequest -Uri 'https://www.virustotal.com/vtapi/v2/url/scan' -Body @{apikey = $api_key; url = $new_redir } -Method Post -UseBasicParsing $submitted = $result.StatusCode -eq 200 if ($submitted) { warn "$app`: not found`: submitted $url" @@ -191,7 +191,7 @@ Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying = $False) { Submit-ToVirusTotal $new_redir $app $do_scan $True } else { warn "$app`: VirusTotal submission of $url failed`:`n" + - "`tAPI returned $($result.StatusCode) after retrying" + "`tAPI returned $($result.StatusCode) after retrying" } } catch [Exception] { warn "$app`: VirusTotal submission failed`: $($_.Exception.Message)" @@ -199,14 +199,13 @@ Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying = $False) { } } -$apps | ForEach-Object { - $app = $_ +foreach ($app in $apps) { # write-host $app - $null, $manifest, $bucket, $null = Find-Manifest $app - if(!$manifest) { + $null, $manifest, $bucket, $null = Get-Manifest $app + if (!$manifest) { $exit_code = $exit_code -bor $_ERR_NO_INFO warn "$app`: manifest not found" - return + continue } $urls = script:url $manifest $architecture @@ -215,17 +214,17 @@ $apps | ForEach-Object { $hash = hash_for_url $manifest $url $architecture try { - if($hash) { + if ($hash) { $exit_code = $exit_code -bor (Search-VirusTotal $hash $app) } else { warn "$app`: Can't find hash for $url" } } catch [Exception] { $exit_code = $exit_code -bor $_ERR_EXCEPTION - if ($_.Exception.Message -like "*(404)*") { + if ($_.Exception.Message -like '*(404)*') { Submit-ToVirusTotal $url $app ($opt.scan -or $opt.s) } else { - if ($_.Exception.Message -match "\(204|429\)") { + if ($_.Exception.Message -match '\(204|429\)') { abort "$app`: VirusTotal request failed`: $($_.Exception.Message)", $exit_code } warn "$app`: VirusTotal request failed`: $($_.Exception.Message)" diff --git a/test/Scoop-Depends.Tests.ps1 b/test/Scoop-Depends.Tests.ps1 index ba54550554..4a58db2443 100644 --- a/test/Scoop-Depends.Tests.ps1 +++ b/test/Scoop-Depends.Tests.ps1 @@ -69,30 +69,30 @@ Describe 'Package Dependencies' -Tag 'Scoop' { BeforeAll { Mock Test-HelperInstalled { $false } Mock get_config { $true } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' } - Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'lessmsi' } - Mock Find-Manifest { $null, @{ url = 'test.msi' }, $null, $null } -ParameterFilter { $AppName -eq '7zip' } - Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'innounp' } + Mock Get-Manifest { 'lessmsi', @{}, $null, $null } -ParameterFilter { $app -eq 'lessmsi' } + Mock Get-Manifest { '7zip', @{ url = 'test.msi' }, $null, $null } -ParameterFilter { $app -eq '7zip' } + Mock Get-Manifest { 'innounp', @{}, $null, $null } -ParameterFilter { $app -eq 'innounp' } } It 'Resolve install dependencies' { - Mock Find-Manifest { $null, @{ url = 'test.7z' }, $null, $null } + Mock Get-Manifest { 'test', @{ url = 'test.7z' }, $null, $null } Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('lessmsi', '7zip', 'test') - Mock Find-Manifest { $null, @{ innosetup = $true }, $null, $null } + Mock Get-Manifest { 'test', @{ innosetup = $true }, $null, $null } Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('innounp', 'test') } It 'Resolve script dependencies' { - Mock Find-Manifest { $null, @{ pre_install = 'Expand-7zipArchive ' }, $null, $null } + Mock Get-Manifest { 'test', @{ pre_install = 'Expand-7zipArchive ' }, $null, $null } Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('lessmsi', '7zip', 'test') } It 'Resolve runtime dependencies' { - Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'depends' } - Mock Find-Manifest { $null, @{ depends = 'depends' }, $null, $null } + Mock Get-Manifest { 'depends', @{}, $null, $null } -ParameterFilter { $app -eq 'depends' } + Mock Get-Manifest { 'test', @{ depends = 'depends' }, $null, $null } Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('depends', 'test') } It 'Keep bucket name of app' { - Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'bucket/depends' } - Mock Find-Manifest { $null, @{ depends = 'bucket/depends' }, $null, $null } - Get-Dependency -AppName 'anotherbucket/test' -Architecture '32bit' | Should -Be @('bucket/depends', 'anotherbucket/test') + Mock Get-Manifest { 'depends', @{}, 'anotherbucket', $null } -ParameterFilter { $app -eq 'anotherbucket/depends' } + Mock Get-Manifest { 'test', @{ depends = 'anotherbucket/depends' }, 'bucket', $null } + Get-Dependency -AppName 'bucket/test' -Architecture '32bit' | Should -Be @('anotherbucket/depends', 'bucket/test') } } }