From 691c23330c45e912e1e01f071d03ed640399a14c Mon Sep 17 00:00:00 2001 From: AkariiinMKII <6019344+AkariiinMKII@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:51:19 +0800 Subject: [PATCH 01/36] fix(scoop-download): Fix function `nightly_version` not defined error (#6386) --- CHANGELOG.md | 6 ++++++ libexec/scoop-download.ps1 | 1 + 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0c15ec326..ffe2a7fbf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/v0.5.3...develop) + +### Bug Fixes + +- **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) + ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 ### Features diff --git a/libexec/scoop-download.ps1 b/libexec/scoop-download.ps1 index 996cb4e8e6..34a78ea952 100644 --- a/libexec/scoop-download.ps1 +++ b/libexec/scoop-download.ps1 @@ -25,6 +25,7 @@ . "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion' . "$PSScriptRoot\..\lib\manifest.ps1" # 'generate_user_manifest' 'Get-Manifest' . "$PSScriptRoot\..\lib\download.ps1" +. "$PSScriptRoot\..\lib\install.ps1" # 'nightly_version' if (get_config USE_SQLITE_CACHE) { . "$PSScriptRoot\..\lib\database.ps1" } From c9f0728ff7cab879fc0adecad319816c5aded95b Mon Sep 17 00:00:00 2001 From: HUMORCE Date: Wed, 20 Aug 2025 13:59:47 +0800 Subject: [PATCH 02/36] fix(autoupdate): Use origin url to handle urls with fragment in github mode (#6455) --- CHANGELOG.md | 1 + lib/autoupdate.ps1 | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe2a7fbf9..279c76d947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Bug Fixes - **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) +- **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/autoupdate.ps1 b/lib/autoupdate.ps1 index 711f2fd6e5..fbc3ebfdee 100644 --- a/lib/autoupdate.ps1 +++ b/lib/autoupdate.ps1 @@ -3,6 +3,8 @@ function format_hash([String] $hash) { $hash = $hash.toLower() + # Workaround for GitHub API: + # `"digest": "sha256:"` if ($hash -like 'sha256:*') { $hash = $hash.Substring(7) # Remove prefix 'sha256:' } @@ -209,13 +211,14 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u $hash = $null $hashmode = $config.mode + $originurl = strip_fragment $url $basename = [System.Web.HttpUtility]::UrlDecode((url_remote_filename($url))) $substitutions = $substitutions.Clone() - $substitutions.Add('$url', (strip_fragment $url)) - $substitutions.Add('$baseurl', (strip_filename (strip_fragment $url)).TrimEnd('/')) + $substitutions.Add('$url', $originurl) + $substitutions.Add('$baseurl', (strip_filename $originurl).TrimEnd('/')) $substitutions.Add('$basename', $basename) - $substitutions.Add('$urlNoExt', (strip_ext (strip_fragment $url))) + $substitutions.Add('$urlNoExt', (strip_ext $originurl)) $substitutions.Add('$basenameNoExt', (strip_ext $basename)) debug $substitutions @@ -297,7 +300,7 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u } 'github' { $hashfile_url = "https://api.github.com/repos/$($matches['owner'])/$($matches['repo'])/releases" - $hash = find_hash_in_json $hashfile_url $substitutions ("$..assets[?(@.browser_download_url == '" + $url + "')].digest") + $hash = find_hash_in_json $hashfile_url $substitutions ("$..assets[?(@.browser_download_url == '" + $originurl + "')].digest") } } From ff38652e0126d8a86b1f935dbb2e69299061e4dc Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:18:33 +0800 Subject: [PATCH 03/36] fix(buckets|scoop-info): Switch git log date format to ISO 8601 to avoid locale issues (#6446) --- CHANGELOG.md | 1 + lib/buckets.ps1 | 2 +- libexec/scoop-info.ps1 | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 279c76d947..800b03097c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) +- **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/pull/6446)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/buckets.ps1 b/lib/buckets.ps1 index 87bc02d287..08d6d0bd7e 100644 --- a/lib/buckets.ps1 +++ b/lib/buckets.ps1 @@ -108,7 +108,7 @@ function list_buckets { $path = Find-BucketDirectory $_ -Root if ((Test-Path (Join-Path $path '.git')) -and (Get-Command git -ErrorAction SilentlyContinue)) { $bucket.Source = Invoke-Git -Path $path -ArgumentList @('config', 'remote.origin.url') - $bucket.Updated = Invoke-Git -Path $path -ArgumentList @('log', '--format=%aD', '-n', '1') | Get-Date + $bucket.Updated = Invoke-Git -Path $path -ArgumentList @('log', '--format=%aI', '-n', '1') | Get-Date } else { $bucket.Source = friendly_path $path $bucket.Updated = (Get-Item "$path\bucket" -ErrorAction SilentlyContinue).LastWriteTime diff --git a/libexec/scoop-info.ps1 b/libexec/scoop-info.ps1 index 1322e33a63..1c147e17c0 100644 --- a/libexec/scoop-info.ps1 +++ b/libexec/scoop-info.ps1 @@ -122,7 +122,7 @@ if ($manifest.depends) { if (Test-Path $manifest_file) { if (Get-Command git -ErrorAction Ignore) { - $gitinfo = (Invoke-Git -Path (Split-Path $manifest_file) -ArgumentList @('log', '-1', '-s', '--format=%aD#%an', $manifest_file) 2> $null) -Split '#' + $gitinfo = (Invoke-Git -Path (Split-Path $manifest_file) -ArgumentList @('log', '-1', '-s', '--format=%aI#%an', $manifest_file) 2> $null) -Split '#' } if ($gitinfo) { $item.'Updated at' = $gitinfo[0] | Get-Date From 04b7ce79c7a1395f5db0141bf247a29d92873515 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Wed, 27 Aug 2025 05:46:16 -0400 Subject: [PATCH 04/36] fix(scoop-version): Fix logic error caused by missing brackets (#6463) --- CHANGELOG.md | 5 +++-- bin/scoop.ps1 | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 800b03097c..3795ce5dc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ ### Bug Fixes -- **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) +- **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) -- **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/pull/6446)) +- **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) +- **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/bin/scoop.ps1 b/bin/scoop.ps1 index fd2fd41fa7..036a05ba29 100644 --- a/bin/scoop.ps1 +++ b/bin/scoop.ps1 @@ -20,8 +20,8 @@ switch ($subCommand) { } ({ $subCommand -in @('-v', '--version') }) { Write-Host 'Current Scoop version:' - if (Test-GitAvailable -and (Test-Path "$PSScriptRoot\..\.git") -and (get_config SCOOP_BRANCH 'master') -ne 'master') { - Invoke-Git -Path "$PSScriptRoot\.." -ArgumentList @('log', 'HEAD', '-1', '--oneline') + if ((Test-GitAvailable) -and (Test-Path "$PSScriptRoot\..\.git") -and ((get_config SCOOP_BRANCH 'master') -ne 'master')) { + Invoke-Git -Path "$PSScriptRoot\.." -ArgumentList @('--no-pager', 'log', 'HEAD', '-1', '--oneline') } else { $version = Select-String -Pattern '^## \[(v[\d.]+)\].*?([\d-]+)$' -Path "$PSScriptRoot\..\CHANGELOG.md" Write-Host $version.Matches.Groups[1].Value -ForegroundColor Cyan -NoNewline @@ -31,9 +31,9 @@ switch ($subCommand) { Get-LocalBucket | ForEach-Object { $bucketLoc = Find-BucketDirectory $_ -Root - if (Test-GitAvailable -and (Test-Path "$bucketLoc\.git")) { + if ((Test-GitAvailable) -and (Test-Path "$bucketLoc\.git")) { Write-Host "'$_' bucket:" - Invoke-Git -Path $bucketLoc -ArgumentList @('log', 'HEAD', '-1', '--oneline') + Invoke-Git -Path $bucketLoc -ArgumentList @('--no-pager', 'log', 'HEAD', '-1', '--oneline') Write-Host '' } } From 25d35007c64141cb6df25767e92d80f65cfd77a4 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:45:01 +0800 Subject: [PATCH 05/36] fix(core|manifest): Avoid error when searching non-existent 'deprecated' directory (#6471) --- CHANGELOG.md | 1 + lib/core.ps1 | 2 +- lib/manifest.ps1 | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3795ce5dc3..55455b939c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) +- **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/core.ps1 b/lib/core.ps1 index 7ca7d121e2..2b9f8b68af 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -555,7 +555,7 @@ function app_status($app, $global) { $status.hold = ($install_info.hold -eq $true) $deprecated_dir = (Find-BucketDirectory -Name $install_info.bucket -Root) + "\deprecated" - $status.deprecated = (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse).FullName + $status.deprecated = (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse -ErrorAction Ignore).FullName $manifest = manifest $app $install_info.bucket $install_info.url $status.removed = (!$manifest) diff --git a/lib/manifest.ps1 b/lib/manifest.ps1 index 29c898b6a7..6510dd650c 100644 --- a/lib/manifest.ps1 +++ b/lib/manifest.ps1 @@ -69,7 +69,7 @@ function Get-Manifest($app) { $manifest = manifest $app $bucket if (!$manifest) { $deprecated_dir = (Find-BucketDirectory -Name $bucket -Root) + '\deprecated' - $manifest = parse_json (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse).FullName + $manifest = parse_json (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse -ErrorAction Ignore).FullName } } } From b592b38abd078b83ee6143f2b120c3cce169c8b2 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:52:03 +0800 Subject: [PATCH 06/36] feat(install): Add separator at the end of notes, highlight suggestions (#6418) --- CHANGELOG.md | 4 ++++ lib/install.ps1 | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55455b939c..b66a583370 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/v0.5.3...develop) +### Features + +- **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) + ### Bug Fixes - **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) diff --git a/lib/install.ps1 b/lib/install.ps1 index 56cfdac924..0a82331a4a 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -359,6 +359,7 @@ function show_notes($manifest, $dir, $original_dir, $persist_dir) { Write-Output 'Notes' Write-Output '-----' Write-Output (wraptext (substitute $manifest.notes @{ '$dir' = $dir; '$original_dir' = $original_dir; '$persist_dir' = $persist_dir })) + Write-Output '-----' } } @@ -419,7 +420,7 @@ function show_suggestions($suggested) { } if (!$fulfilled) { - Write-Host "'$app' suggests installing '$([string]::join("' or '", $feature_suggestions))'." + Write-Host "'$app' suggests installing '$([string]::join("' or '", $feature_suggestions))'." -ForegroundColor DarkYellow } } } From db8d554f80607ad7554bb10ada31e01a6bd0036b Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Fri, 26 Sep 2025 15:20:33 +0800 Subject: [PATCH 07/36] fix(scoop-update): Force sync tags w/ remote branch while scoop update (#6439) --- CHANGELOG.md | 1 + libexec/scoop-update.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b66a583370..f5125f77d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Bug Fixes +- **scoop-update**: Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) - **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index 9d41906eca..3a305c3dfc 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -136,7 +136,7 @@ function Sync-Scoop { # reset branch HEAD Invoke-Git -Path $currentdir -ArgumentList @('reset', '--hard', "origin/$configBranch", '-q') } else { - Invoke-Git -Path $currentdir -ArgumentList @('pull', '-q') + Invoke-Git -Path $currentdir -ArgumentList @('pull', '--tags', '--force', '-q') } $res = $lastexitcode From 4c55e7aebdd734eef7a068988d22e51a799c01fc Mon Sep 17 00:00:00 2001 From: abgox Date: Fri, 26 Sep 2025 17:14:09 +0800 Subject: [PATCH 08/36] feat(scoop-uninstall): Allow access to $bucket in uninstall scripts (#6380) --- CHANGELOG.md | 1 + libexec/scoop-uninstall.ps1 | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5125f77d2..b62c008eae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- **scoop-uninstall**: Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) - **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) ### Bug Fixes diff --git a/libexec/scoop-uninstall.ps1 b/libexec/scoop-uninstall.ps1 index 5bdd57e5d1..2d2a8e9ba9 100644 --- a/libexec/scoop-uninstall.ps1 +++ b/libexec/scoop-uninstall.ps1 @@ -58,6 +58,7 @@ if (!$apps) { exit 0 } $manifest = installed_manifest $app $version $global $install = install_info $app $version $global $architecture = $install.architecture + $bucket = $install.bucket Invoke-HookScript -HookType 'pre_uninstall' -Manifest $manifest -Arch $architecture From 2a637361ccce0c5e6970ee8a3e3bab0bde050ab6 Mon Sep 17 00:00:00 2001 From: HUMORCE Date: Fri, 26 Sep 2025 23:55:34 +0800 Subject: [PATCH 09/36] fix(scoop-uninstall): Correct `-Global` switch during uninstalling/updating (#6454) Co-authored-by: Hsiao-nan Cheung --- CHANGELOG.md | 3 ++- bin/uninstall.ps1 | 2 +- libexec/scoop-uninstall.ps1 | 2 +- libexec/scoop-update.ps1 | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b62c008eae..3d45cb1212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ ### Bug Fixes +- **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) +- **scoop-uninstall:**: Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) - **scoop-update**: Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) -- **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) diff --git a/bin/uninstall.ps1 b/bin/uninstall.ps1 index 2e2dc36ea8..9302dd988a 100644 --- a/bin/uninstall.ps1 +++ b/bin/uninstall.ps1 @@ -42,7 +42,7 @@ function do_uninstall($app, $global) { $architecture = $install.architecture Write-Output "Uninstalling '$app'" - Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Uninstall + Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Global:$global -Uninstall rm_shims $app $manifest $global $architecture # If a junction was used during install, that will have been used diff --git a/libexec/scoop-uninstall.ps1 b/libexec/scoop-uninstall.ps1 index 2d2a8e9ba9..fdb6e8770e 100644 --- a/libexec/scoop-uninstall.ps1 +++ b/libexec/scoop-uninstall.ps1 @@ -75,7 +75,7 @@ if (!$apps) { exit 0 } continue } - Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Global $global -Uninstall + Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Global:$global -Uninstall rm_shims $app $manifest $global $architecture rm_startmenu_shortcuts $manifest $global $architecture diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index 3a305c3dfc..99e6a6dddb 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -341,7 +341,7 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c Invoke-HookScript -HookType 'pre_uninstall' -Manifest $old_manifest -Arch $architecture Write-Host "Uninstalling '$app' ($old_version)" - Invoke-Installer -Path $dir -Manifest $old_manifest -ProcessorArchitecture $architecture -Uninstall + Invoke-Installer -Path $dir -Manifest $old_manifest -ProcessorArchitecture $architecture -Global:$global -Uninstall rm_shims $app $old_manifest $global $architecture # If a junction was used during install, that will have been used From ca0506cf3e26d6b1038270dc32bc4f4804dc9a01 Mon Sep 17 00:00:00 2001 From: abgox Date: Mon, 29 Sep 2025 15:12:10 +0800 Subject: [PATCH 10/36] refactor(output): Replace raw prints with functions for standardized output (#6449) Co-authored-by: Hsiao-nan Cheung --- CHANGELOG.md | 4 ++++ lib/core.ps1 | 2 +- lib/install.ps1 | 2 +- libexec/scoop-alias.ps1 | 2 +- libexec/scoop-bucket.ps1 | 8 ++++---- libexec/scoop-cache.ps1 | 2 +- libexec/scoop-cleanup.ps1 | 6 +++--- libexec/scoop-help.ps1 | 6 +++--- libexec/scoop-hold.ps1 | 2 +- libexec/scoop-install.ps1 | 2 +- libexec/scoop-list.ps1 | 4 ++-- libexec/scoop-reset.ps1 | 2 +- libexec/scoop-shim.ps1 | 5 ++--- libexec/scoop-unhold.ps1 | 2 +- libexec/scoop-update.ps1 | 4 ++-- libexec/scoop-virustotal.ps1 | 2 +- 16 files changed, 29 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d45cb1212..9875359d01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) +### Code Refactoring + +- **output**: Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) + ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 ### Features diff --git a/lib/core.ps1 b/lib/core.ps1 index 2b9f8b68af..b0e833c74b 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -90,7 +90,7 @@ function load_cfg($file) { $content = [System.IO.File]::ReadAllLines($file) return ($content | ConvertFrom-Json -ErrorAction Stop) } catch { - Write-Host "ERROR loading $file`: $($_.exception.message)" + error "loading $file`: $($_.exception.message)" } } diff --git a/lib/install.ps1 b/lib/install.ps1 index 0a82331a4a..6125697967 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -285,7 +285,7 @@ function ensure_install_dir_not_in_path($dir, $global) { $fixed, $removed = find_dir_or_subdir $path "$dir" if ($removed) { - $removed | ForEach-Object { "Installer added '$(friendly_path $_)' to path. Removing." } + $removed | ForEach-Object { Write-Output "Installer added '$(friendly_path $_)' to path. Removing." } Set-EnvVar -Name 'PATH' -Value $fixed -Global:$global } diff --git a/libexec/scoop-alias.ps1 b/libexec/scoop-alias.ps1 index 677b9337f7..2b0545abe4 100644 --- a/libexec/scoop-alias.ps1 +++ b/libexec/scoop-alias.ps1 @@ -40,7 +40,7 @@ if ($SubCommand -notin $SubCommands) { } $opt, $other, $err = getopt $Args 'v' 'verbose' -if ($err) { "scoop alias: $err"; exit 1 } +if ($err) { error "scoop alias: $err"; exit 1 } $name, $command, $description = $other $verbose = $opt.v -or $opt.verbose diff --git a/libexec/scoop-bucket.ps1 b/libexec/scoop-bucket.ps1 index d3b7728559..39d8ccf8da 100644 --- a/libexec/scoop-bucket.ps1 +++ b/libexec/scoop-bucket.ps1 @@ -34,14 +34,14 @@ $usage_rm = 'usage: scoop bucket rm ' switch ($cmd) { 'add' { if (!$name) { - ' missing' + error ' missing' $usage_add exit 1 } if (!$repo) { $repo = known_bucket_repo $name if (!$repo) { - "Unknown bucket '$name'. Try specifying ." + error "Unknown bucket '$name'. Try specifying ." $usage_add exit 1 } @@ -51,7 +51,7 @@ switch ($cmd) { } 'rm' { if (!$name) { - ' missing' + error ' missing' $usage_rm exit 1 } @@ -73,7 +73,7 @@ switch ($cmd) { exit 0 } default { - "scoop bucket: cmd '$cmd' not supported" + error "scoop bucket: cmd '$cmd' not supported" my_usage exit 1 } diff --git a/libexec/scoop-cache.ps1 b/libexec/scoop-cache.ps1 index 30e8354fca..e81a626db7 100644 --- a/libexec/scoop-cache.ps1 +++ b/libexec/scoop-cache.ps1 @@ -35,7 +35,7 @@ function cacheshow($app) { function cacheremove($app) { if (!$app) { - 'ERROR: missing' + error ' missing' my_usage exit 1 } elseif ($app -eq '*' -or $app -eq '-a' -or $app -eq '--all') { diff --git a/libexec/scoop-cleanup.ps1 b/libexec/scoop-cleanup.ps1 index 6ce40a211f..3ea5194d0f 100644 --- a/libexec/scoop-cleanup.ps1 +++ b/libexec/scoop-cleanup.ps1 @@ -16,15 +16,15 @@ . "$PSScriptRoot\..\lib\install.ps1" # persist related $opt, $apps, $err = getopt $args 'agk' 'all', 'global', 'cache' -if ($err) { "scoop cleanup: $err"; exit 1 } +if ($err) { error "scoop cleanup: $err"; exit 1 } $global = $opt.g -or $opt.global $cache = $opt.k -or $opt.cache $all = $opt.a -or $opt.all -if (!$apps -and !$all) { 'ERROR: missing'; my_usage; exit 1 } +if (!$apps -and !$all) { error ' missing'; my_usage; exit 1 } if ($global -and !(is_admin)) { - 'ERROR: you need admin rights to cleanup global apps'; exit 1 + error 'you need admin rights to cleanup global apps'; exit 1 } function cleanup($app, $global, $verbose, $cache) { diff --git a/libexec/scoop-help.ps1 b/libexec/scoop-help.ps1 index 54ed8a9319..18a67fa9b1 100644 --- a/libexec/scoop-help.ps1 +++ b/libexec/scoop-help.ps1 @@ -27,17 +27,17 @@ function print_summaries { $commands = commands -if(!($cmd)) { +if (!($cmd)) { Write-Host "Usage: scoop [] Available commands are listed below. Type 'scoop help ' to get more help for a specific command." print_summaries -} elseif($commands -contains $cmd) { +} elseif ($commands -contains $cmd) { print_help $cmd } else { - warn "scoop help: no such command '$cmd'" + error "scoop help: no such command '$cmd'" exit 1 } diff --git a/libexec/scoop-hold.ps1 b/libexec/scoop-hold.ps1 index 504f20a849..48f8304c9a 100644 --- a/libexec/scoop-hold.ps1 +++ b/libexec/scoop-hold.ps1 @@ -15,7 +15,7 @@ . "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion' $opt, $apps, $err = getopt $args 'g' 'global' -if ($err) { "scoop hold: $err"; exit 1 } +if ($err) { error "scoop hold: $err"; exit 1 } $global = $opt.g -or $opt.global diff --git a/libexec/scoop-install.ps1 b/libexec/scoop-install.ps1 index 0fadcff09d..6af199a8b8 100644 --- a/libexec/scoop-install.ps1 +++ b/libexec/scoop-install.ps1 @@ -44,7 +44,7 @@ if (get_config USE_SQLITE_CACHE) { } $opt, $apps, $err = getopt $args 'giksua:' 'global', 'independent', 'no-cache', 'skip-hash-check', 'no-update-scoop', 'arch=' -if ($err) { "scoop install: $err"; exit 1 } +if ($err) { error "scoop install: $err"; exit 1 } $global = $opt.g -or $opt.global $check_hash = !($opt.s -or $opt.'skip-hash-check') diff --git a/libexec/scoop-list.ps1 b/libexec/scoop-list.ps1 index f757146d47..aded1e5ee0 100644 --- a/libexec/scoop-list.ps1 +++ b/libexec/scoop-list.ps1 @@ -17,7 +17,7 @@ $global = installed_apps $true | ForEach-Object { @{ name = $_; global = $true } $apps = @($local) + @($global) if (-not $apps) { - Write-Host "There aren't any apps installed." + warn "There aren't any apps installed." exit 1 } @@ -48,7 +48,7 @@ $apps | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object { $item.Updated = $updated $info = @() - if ((app_status $app $global).deprecated) { $info += 'Deprecated package'} + if ((app_status $app $global).deprecated) { $info += 'Deprecated package' } if ($global) { $info += 'Global install' } if (failed $app $global) { $info += 'Install failed' } if ($install_info.hold) { $info += 'Held package' } diff --git a/libexec/scoop-reset.ps1 b/libexec/scoop-reset.ps1 index 512540e8e6..1dd000a373 100644 --- a/libexec/scoop-reset.ps1 +++ b/libexec/scoop-reset.ps1 @@ -14,7 +14,7 @@ . "$PSScriptRoot\..\lib\shortcuts.ps1" $opt, $apps, $err = getopt $args 'a' 'all' -if($err) { "scoop reset: $err"; exit 1 } +if($err) { error "scoop reset: $err"; exit 1 } $all = $opt.a -or $opt.all if(!$apps -and !$all) { error ' missing'; my_usage; exit 1 } diff --git a/libexec/scoop-shim.ps1 b/libexec/scoop-shim.ps1 index 877b65b2e9..26f394dd56 100644 --- a/libexec/scoop-shim.ps1 +++ b/libexec/scoop-shim.ps1 @@ -48,7 +48,7 @@ if ($SubCommand -notin @('add', 'rm', 'list', 'info', 'alter')) { } $opt, $other, $err = getopt $Args 'g' 'global' -if ($err) { "scoop shim: $err"; exit 1 } +if ($err) { error "scoop shim: $err"; exit 1 } $global = $opt.g -or $opt.global @@ -147,8 +147,7 @@ switch ($SubCommand) { $pattern = $_ [void][Regex]::New($pattern) } catch { - Write-Host "ERROR: Invalid pattern: " -ForegroundColor Red -NoNewline - Write-Host $pattern -ForegroundColor Magenta + error "Invalid pattern: $([char]0x1b)[35m$pattern$([char]0x1b)[0m" exit 1 } } diff --git a/libexec/scoop-unhold.ps1 b/libexec/scoop-unhold.ps1 index 4e2413a340..88a859c81c 100644 --- a/libexec/scoop-unhold.ps1 +++ b/libexec/scoop-unhold.ps1 @@ -15,7 +15,7 @@ . "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion' $opt, $apps, $err = getopt $args 'g' 'global' -if ($err) { "scoop unhold: $err"; exit 1 } +if ($err) { error "scoop unhold: $err"; exit 1 } $global = $opt.g -or $opt.global diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index 99e6a6dddb..bc590a13f6 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -30,7 +30,7 @@ if (get_config USE_SQLITE_CACHE) { } $opt, $apps, $err = getopt $args 'gfiksqa' 'global', 'force', 'independent', 'no-cache', 'skip-hash-check', 'quiet', 'all' -if ($err) { "scoop update: $err"; exit 1 } +if ($err) { error "scoop update: $err"; exit 1 } $global = $opt.g -or $opt.global $force = $opt.f -or $opt.force $check_hash = !($opt.s -or $opt.'skip-hash-check') @@ -400,7 +400,7 @@ if (-not ($apps -or $all)) { success 'Scoop was updated successfully!' } else { if ($global -and !(is_admin)) { - 'ERROR: You need admin rights to update global apps.'; exit 1 + error 'You need admin rights to update global apps.'; exit 1 } $outdated = @() diff --git a/libexec/scoop-virustotal.ps1 b/libexec/scoop-virustotal.ps1 index 8fe63359cf..d56eb6e8b4 100644 --- a/libexec/scoop-virustotal.ps1 +++ b/libexec/scoop-virustotal.ps1 @@ -36,7 +36,7 @@ . "$PSScriptRoot\..\lib\depends.ps1" # 'Get-Dependency' $opt, $apps, $err = getopt $args 'asnup' @('all', 'scan', 'no-depends', 'no-update-scoop', 'passthru') -if ($err) { "scoop virustotal: $err"; exit 1 } +if ($err) { error "scoop virustotal: $err"; exit 1 } $all = $apps -eq '*' -or $opt.a -or $opt.all if (!$apps -and !$all) { my_usage; exit 1 } $architecture = Get-DefaultArchitecture From 20a178b1f3cdd6b41efc910c77092d6bc4e7d705 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Mon, 13 Oct 2025 05:32:26 -0400 Subject: [PATCH 11/36] fix(checkver): Allow script to run when URL fetch fails but script exists (#6490) --- CHANGELOG.md | 1 + bin/checkver.ps1 | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9875359d01..920ec82676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) +- **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) ### Code Refactoring diff --git a/bin/checkver.ps1 b/bin/checkver.ps1 index 33a4449488..d5664df5f6 100644 --- a/bin/checkver.ps1 +++ b/bin/checkver.ps1 @@ -281,11 +281,16 @@ while ($in_progress -gt 0) { } $err = $ev.SourceEventArgs.Error if ($err) { - next "$($err.message)`r`nURL $url is not valid" - continue + if (!$script) { + next "$($err.message)`r`nURL $url is not valid" + continue + } else { + # Run script despite URL download failure + Write-Host "$($err.message)`r`nURL $url is not valid. Falling back to checkver.script ..." + } } - if ($url) { + if ($url -and !$err) { $ms = New-Object System.IO.MemoryStream $ms.Write($result, 0, $result.Length) $ms.Seek(0, 0) | Out-Null From 52a035b5ccaac35de8c7978f74c90ad57cd8a097 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 21 Oct 2025 11:27:15 +0800 Subject: [PATCH 12/36] fix(path): Trim ending slash when initializing paths (#6501) --- CHANGELOG.md | 11 ++++++----- lib/core.ps1 | 9 ++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 920ec82676..049a96d960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,23 +2,24 @@ ### Features -- **scoop-uninstall**: Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) +- **scoop-uninstall:** Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) - **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) ### Bug Fixes -- **scoop-download**: Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) -- **scoop-uninstall:**: Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) -- **scoop-update**: Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) +- **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) +- **scoop-uninstall:** Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) +- **scoop-update:** Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) +- **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) ### Code Refactoring -- **output**: Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) +- **output:** Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/core.ps1 b/lib/core.ps1 index b0e833c74b..a23e8dd750 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -622,7 +622,14 @@ function Get-AbsolutePath { $Path ) process { - return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) + $resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) + if ($resolvedPath -match '[\\/]$') { + $root = [System.IO.Path]::GetPathRoot($resolvedPath) + if ($resolvedPath -ine $root) { + $resolvedPath = $resolvedPath.TrimEnd([char[]]@('\', '/')) + } + } + return $resolvedPath } } From 79669717fe3e53ba642ec073a45bbe53acb77b8e Mon Sep 17 00:00:00 2001 From: abgox Date: Mon, 3 Nov 2025 16:25:29 +0800 Subject: [PATCH 13/36] fix(schema): add github to the mode of hash (#6534) Co-authored-by: z-Fng <54583083+z-Fng@users.noreply.github.com> --- CHANGELOG.md | 1 + schema.json | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 049a96d960..4a92372072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) +- **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) ### Code Refactoring diff --git a/schema.json b/schema.json index 6c24d4da20..9457c391e7 100644 --- a/schema.json +++ b/schema.json @@ -50,6 +50,7 @@ }, "mode": { "enum": [ + "github", "download", "extract", "json", From 2120c28c221dc039c986b0d9409e972576a5a957 Mon Sep 17 00:00:00 2001 From: abgox Date: Sat, 8 Nov 2025 18:26:06 +0800 Subject: [PATCH 14/36] fix(buckets): fix the filtering condition when retrieving the number of manifests (#6509) --- CHANGELOG.md | 1 + lib/buckets.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a92372072..7e6657e9d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Bug Fixes +- **buckets:** Fix the filtering condition when retrieving the number of manifests ([#6509](https://github.com/ScoopInstaller/Scoop/issues/6509)) - **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **scoop-uninstall:** Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) - **scoop-update:** Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) diff --git a/lib/buckets.ps1 b/lib/buckets.ps1 index 08d6d0bd7e..e97f2dc3fb 100644 --- a/lib/buckets.ps1 +++ b/lib/buckets.ps1 @@ -113,7 +113,7 @@ function list_buckets { $bucket.Source = friendly_path $path $bucket.Updated = (Get-Item "$path\bucket" -ErrorAction SilentlyContinue).LastWriteTime } - $bucket.Manifests = Get-ChildItem "$path\bucket" -Force -Recurse -ErrorAction SilentlyContinue | + $bucket.Manifests = Get-ChildItem -Path "$path\bucket" -Filter "*.json" -File -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count $buckets += [PSCustomObject]$bucket } From 28c51e04b118d34807414e58c20dc4ae8a6a9b50 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:27:34 +0800 Subject: [PATCH 15/36] feat(download|scoop-config): Allow disabling automatic fallback to the default downloader (#6538) --- CHANGELOG.md | 1 + lib/download.ps1 | 7 +++++++ libexec/scoop-config.ps1 | 3 +++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e6657e9d9..a262f43436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **scoop-uninstall:** Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) - **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) +- **download|scoop-config:** Allow disabling automatic fallback to the default downloader when Aria2c download fails ([#6538](https://github.com/ScoopInstaller/Scoop/issues/6538)) ### Bug Fixes diff --git a/lib/download.ps1 b/lib/download.ps1 index 70641cca7f..35c443aed6 100644 --- a/lib/download.ps1 +++ b/lib/download.ps1 @@ -454,6 +454,13 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ Write-Host '' if ($lastexitcode -gt 0) { + if (get_config ARIA2-FALLBACK-DISABLED) { + error "Download failed! (Error $lastexitcode) $(aria_exit_code $lastexitcode)" + error $urlstxt_content + error $aria2 + abort $(new_issue_msg $app $bucket 'download via aria2 failed') + } + warn "Download failed! (Error $lastexitcode) $(aria_exit_code $lastexitcode)" warn $urlstxt_content warn $aria2 diff --git a/libexec/scoop-config.ps1 b/libexec/scoop-config.ps1 index 6007bd6434..954b0b6a1c 100644 --- a/libexec/scoop-config.ps1 +++ b/libexec/scoop-config.ps1 @@ -132,6 +132,9 @@ # aria2-warning-enabled: $true|$false # Disable Aria2c warning which is shown while downloading. # +# aria2-fallback-disabled: $true|$false +# Disable automatic fallback to the default downloader when Aria2c download fails. +# # aria2-retry-wait: 2 # Number of seconds to wait between retries. # See: 'https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-retry-wait' From a8d4027a904072518ec3e8a97857b9aa0db94a89 Mon Sep 17 00:00:00 2001 From: abgox Date: Mon, 10 Nov 2025 13:57:33 +0800 Subject: [PATCH 16/36] fix(core): Fix the grep parameter in the Invoke-GitLog function (#6407) --- CHANGELOG.md | 1 + lib/core.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a262f43436..49f6dacb7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Bug Fixes +- **core:** Fix the grep parameter in the `Invoke-GitLog` function ([#6407](https://github.com/ScoopInstaller/Scoop/issues/6407)) - **buckets:** Fix the filtering condition when retrieving the number of manifests ([#6509](https://github.com/ScoopInstaller/Scoop/issues/6509)) - **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) - **scoop-uninstall:** Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) diff --git a/lib/core.ps1 b/lib/core.ps1 index a23e8dd750..f500c9cba7 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -276,7 +276,7 @@ function Invoke-GitLog { } $Name = "%Cgreen$($Name.PadRight(12, ' ').Substring(0, 12))%Creset " } - Invoke-Git -Path $Path -ArgumentList @('--no-pager', 'log', '--color', '--no-decorate', "--grep='^(chore)'", '--invert-grep', '--abbrev=12', "--format=tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s $Name%C(cyan)%cr%Creset", "$CommitHash..HEAD") + Invoke-Git -Path $Path -ArgumentList @('--no-pager', 'log', '--color', '--no-decorate', '--grep=^(chore)', '--invert-grep', '--abbrev=12', "--format=tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s $Name%C(cyan)%cr%Creset", "$CommitHash..HEAD") } } From f9c6913d67bd867c30da2202b1395c64efd766c1 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:58:10 +0800 Subject: [PATCH 17/36] feat(download|scoop-download): Add GitHub issue prompt when the default downloader fails (#6539) --- CHANGELOG.md | 1 + lib/download.ps1 | 9 +++++---- libexec/scoop-download.ps1 | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f6dacb7d..120efed4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **scoop-uninstall:** Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) - **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) +- **download|scoop-download:** Add GitHub issue prompt when the default downloader fails ([#6539](https://github.com/ScoopInstaller/Scoop/issues/6539)) - **download|scoop-config:** Allow disabling automatic fallback to the default downloader when Aria2c download fails ([#6538](https://github.com/ScoopInstaller/Scoop/issues/6538)) ### Bug Fixes diff --git a/lib/download.ps1 b/lib/download.ps1 index 35c443aed6..d4903bd846 100644 --- a/lib/download.ps1 +++ b/lib/download.ps1 @@ -23,7 +23,8 @@ function Invoke-ScoopDownload ($app, $version, $manifest, $bucket, $architecture Invoke-CachedDownload $app $version $url "$dir\$fname" $cookies $use_cache } catch { Write-Host -ForegroundColor DarkRed $_ - abort "URL $url is not valid" + error "URL $url is not valid" + abort $(new_issue_msg $app $bucket 'download failed') } if ($check_hash) { @@ -464,9 +465,8 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ warn "Download failed! (Error $lastexitcode) $(aria_exit_code $lastexitcode)" warn $urlstxt_content warn $aria2 - warn $(new_issue_msg $app $bucket "download via aria2 failed") - Write-Host "Fallback to default downloader ..." + Write-Host 'Fallback to default downloader ...' try { foreach ($url in $urls) { @@ -474,7 +474,8 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ } } catch { Write-Host $_ -ForegroundColor DarkRed - abort "URL $url is not valid" + error "URL $url is not valid" + abort $(new_issue_msg $app $bucket 'download failed') } } diff --git a/libexec/scoop-download.ps1 b/libexec/scoop-download.ps1 index 34a78ea952..1deba8a808 100644 --- a/libexec/scoop-download.ps1 +++ b/libexec/scoop-download.ps1 @@ -109,6 +109,7 @@ foreach ($curr_app in $apps) { } catch { write-host -f darkred $_ error "URL $url is not valid" + error $(new_issue_msg $app $bucket 'download failed') $dl_failure = $true continue } From f0cd3e19772f047a10e77e863c682160b1cef81a Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:38:34 +0800 Subject: [PATCH 18/36] fix(core): Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function (#6541) --- CHANGELOG.md | 1 + lib/core.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 120efed4c0..649a6232c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) +- **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) ### Code Refactoring diff --git a/lib/core.ps1 b/lib/core.ps1 index f500c9cba7..91a4e6c287 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -353,7 +353,7 @@ function appdir($app, $global) { "$(appsdir $global)\$app" } function versiondir($app, $version, $global) { "$(appdir $app $global)\$version" } function currentdir($app, $global) { - if (get_config NO_JUNCTION) { + if ((get_config NO_JUNCTION) -and ($app -ne 'scoop')) { $version = Select-CurrentVersion -App $app -Global:$global } else { $version = 'current' From 7e86336a42971b289078a8dd4f1a95ecc9d7c5d2 Mon Sep 17 00:00:00 2001 From: abgox Date: Mon, 10 Nov 2025 16:38:07 +0800 Subject: [PATCH 19/36] feat(install): Add output for the setting and removal of environment variables (#6460) Co-authored-by: Hsiao-nan Cheung --- CHANGELOG.md | 9 +++++---- lib/install.ps1 | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 649a6232c8..6f1347290e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- **install:** Add output for the setting and removal of environment variables ([#6460](https://github.com/ScoopInstaller/Scoop/issues/6460)) - **scoop-uninstall:** Allow access to `$bucket` in uninstall scripts ([#6380](https://github.com/ScoopInstaller/Scoop/issues/6380)) - **install:** Add separator at the end of notes, highlight suggestions ([#6418](https://github.com/ScoopInstaller/Scoop/issues/6418)) - **download|scoop-download:** Add GitHub issue prompt when the default downloader fails ([#6539](https://github.com/ScoopInstaller/Scoop/issues/6539)) @@ -31,14 +32,14 @@ ### Features -**autoupdate:** GitHub predefined hashes support ([#6416](https://github.com/ScoopInstaller/Scoop/issues/6416), [#6435](https://github.com/ScoopInstaller/Scoop/issues/6435)) +- **autoupdate:** GitHub predefined hashes support ([#6416](https://github.com/ScoopInstaller/Scoop/issues/6416), [#6435](https://github.com/ScoopInstaller/Scoop/issues/6435)) ### Bug Fixes - **scoop-download|install|update:** Fallback to default downloader when aria2 fails ([#4292](https://github.com/ScoopInstaller/Scoop/issues/4292)) -- **decompress**: `Expand-7zipArchive` only delete temp dir / `$extractDir` if it is empty ([#6092](https://github.com/ScoopInstaller/Scoop/issues/6092)) -- **decompress**: Replace deprecated 7ZIPEXTRACT_USE_EXTERNAL config with USE_EXTERNAL_7ZIP ([#6327](https://github.com/ScoopInstaller/Scoop/issues/6327)) -- **commands**: Handling broken aliases ([#6141](https://github.com/ScoopInstaller/Scoop/issues/6141)) +- **decompress:** `Expand-7zipArchive` only delete temp dir / `$extractDir` if it is empty ([#6092](https://github.com/ScoopInstaller/Scoop/issues/6092)) +- **decompress:** Replace deprecated 7ZIPEXTRACT_USE_EXTERNAL config with USE_EXTERNAL_7ZIP ([#6327](https://github.com/ScoopInstaller/Scoop/issues/6327)) +- **commands:** Handling broken aliases ([#6141](https://github.com/ScoopInstaller/Scoop/issues/6141)) - **shim:** Do not suppress `stderr`, properly check `wslpath`/`cygpath` command first ([#6114](https://github.com/ScoopInstaller/Scoop/issues/6114)) - **scoop-bucket:** Add missing import for `no_junction` envs ([#6181](https://github.com/ScoopInstaller/Scoop/issues/6181)) - **scoop-uninstall:** Fix uninstaller does not gain Global state ([#6430](https://github.com/ScoopInstaller/Scoop/issues/6430)) diff --git a/lib/install.ps1 b/lib/install.ps1 index 6125697967..f2dae3886e 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -338,6 +338,7 @@ function env_set($manifest, $global, $arch) { $env_set | Get-Member -MemberType NoteProperty | ForEach-Object { $name = $_.Name $val = $ExecutionContext.InvokeCommand.ExpandString($env_set.$($name)) + Write-Output "Setting $(if ($global) {'system'} else {'user'}) environment variable: $([char]0x1b)[34m$name$([char]0x1b)[0m = $([char]0x1b)[35m$val$([char]0x1b)[0m" Set-EnvVar -Name $name -Value $val -Global:$global Set-Content env:\$name $val } @@ -348,6 +349,7 @@ function env_rm($manifest, $global, $arch) { if ($env_set) { $env_set | Get-Member -MemberType NoteProperty | ForEach-Object { $name = $_.Name + Write-Output "Removing $(if ($global) {'system'} else {'user'}) environment variable: $([char]0x1b)[34m$name$([char]0x1b)[0m" Set-EnvVar -Name $name -Value $null -Global:$global if (Test-Path env:\$name) { Remove-Item env:\$name } } From 739994550216e0b5aca287883697b561d5956da0 Mon Sep 17 00:00:00 2001 From: MadDogOwner Date: Tue, 11 Nov 2025 11:20:40 +0800 Subject: [PATCH 20/36] fix(uninstall): Import url_filename from download.ps1 (#6530) --- CHANGELOG.md | 1 + libexec/scoop-uninstall.ps1 | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f1347290e..0b830d45f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) +- **uninstall:** Import `url_filename` from `download.ps1` ([#6530](https://github.com/ScoopInstaller/Scoop/issues/6530)) - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) - **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) diff --git a/libexec/scoop-uninstall.ps1 b/libexec/scoop-uninstall.ps1 index fdb6e8770e..7beb0d260e 100644 --- a/libexec/scoop-uninstall.ps1 +++ b/libexec/scoop-uninstall.ps1 @@ -10,6 +10,7 @@ . "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' 'Select-CurrentVersion' (indirectly) . "$PSScriptRoot\..\lib\system.ps1" . "$PSScriptRoot\..\lib\install.ps1" +. "$PSScriptRoot\..\lib\download.ps1" # url_filename . "$PSScriptRoot\..\lib\shortcuts.ps1" . "$PSScriptRoot\..\lib\psmodules.ps1" . "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion' From 0e698ccbd51b752ed60b929d509fe48bd86b7b74 Mon Sep 17 00:00:00 2001 From: abgox Date: Tue, 11 Nov 2025 20:48:03 +0800 Subject: [PATCH 21/36] refactor(output): Combine the separated outputs into a single output (#6545) Co-authored-by: Hsiao-nan Cheung --- CHANGELOG.md | 1 + lib/buckets.ps1 | 2 +- lib/core.ps1 | 8 ++++---- lib/database.ps1 | 4 ++-- lib/decompress.ps1 | 6 ++---- lib/download.ps1 | 14 +++++--------- lib/install.ps1 | 4 ++-- lib/manifest.ps1 | 4 ++-- libexec/scoop-search.ps1 | 3 +-- libexec/scoop-shim.ps1 | 42 ++++++++++++---------------------------- 10 files changed, 32 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b830d45f3..4422869443 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ ### Code Refactoring - **output:** Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) +- **output:** Combine the separated outputs into a single output ([#6545](https://github.com/ScoopInstaller/Scoop/issues/6545)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/buckets.ps1 b/lib/buckets.ps1 index e97f2dc3fb..a6035d7876 100644 --- a/lib/buckets.ps1 +++ b/lib/buckets.ps1 @@ -160,7 +160,7 @@ function add_bucket($name, $repo) { Remove-Item $dir -Recurse -Force -ErrorAction SilentlyContinue return 1 } - Write-Host 'OK' + Write-Host 'OK.' if (get_config USE_SQLITE_CACHE) { info 'Updating cache...' Set-ScoopDB -Path (Get-ChildItem (Find-BucketDirectory $name) -Filter '*.json' -Recurse).FullName diff --git a/lib/core.ps1 b/lib/core.ps1 index 91a4e6c287..d0ec3ccae4 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -750,7 +750,7 @@ function Invoke-ExternalCommand { [void]$Process.Start() } catch { if ($Activity) { - Write-Host "error." -ForegroundColor DarkRed + Write-Host "Error." -ForegroundColor DarkRed } error $_.Exception.Message return $false @@ -769,20 +769,20 @@ function Invoke-ExternalCommand { if ($Process.ExitCode -ne 0) { if ($ContinueExitCodes -and ($ContinueExitCodes.ContainsKey($Process.ExitCode))) { if ($Activity) { - Write-Host "done." -ForegroundColor DarkYellow + Write-Host "Done." -ForegroundColor DarkYellow } warn $ContinueExitCodes[$Process.ExitCode] return $true } else { if ($Activity) { - Write-Host "error." -ForegroundColor DarkRed + Write-Host "Error." -ForegroundColor DarkRed } error "Exit code was $($Process.ExitCode)!" return $false } } if ($Activity) { - Write-Host "done." -ForegroundColor Green + Write-Host "Done." -ForegroundColor Green } return $true } diff --git a/lib/database.ps1 b/lib/database.ps1 index 912db11c31..007abb90b4 100644 --- a/lib/database.ps1 +++ b/lib/database.ps1 @@ -25,12 +25,12 @@ function Get-SQLite { $sqliteTempPath = "$env:TEMP\sqlite" $sqlitePath = "$PSScriptRoot\..\supporting\sqlite" Invoke-WebRequest -Uri "https://api.nuget.org/v3-flatcontainer/stub.system.data.sqlite.core.netframework/$version/stub.system.data.sqlite.core.netframework.$version.nupkg" -OutFile $sqlitePkgPath - Write-Host "Extracting SQLite $Version..." -ForegroundColor DarkYellow -NoNewline + Write-Host "Extracting SQLite $Version... " -ForegroundColor DarkYellow -NoNewline Expand-Archive -Path $sqlitePkgPath -DestinationPath $sqliteTempPath -Force New-Item -Path $sqlitePath -ItemType Directory -Force | Out-Null Move-Item -Path "$sqliteTempPath\build\net451\*", "$sqliteTempPath\lib\net451\System.Data.SQLite.dll" -Destination $sqlitePath -Force Remove-Item -Path $sqlitePkgPath, $sqliteTempPath -Recurse -Force - Write-Host ' Done' -ForegroundColor DarkYellow + Write-Host 'Done.' -ForegroundColor DarkYellow return $true } catch { return $false diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 3f174bf0c3..c25e46f5e3 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -52,11 +52,9 @@ function Invoke-Extraction { 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 + Write-Host "Extracting $([char]0x1b)[36m$(url_remote_filename $uri[$i])$([char]0x1b)[0m... " -NoNewline & $extractFn @fnArgs -Removal - Write-Host 'done.' -ForegroundColor Green + Write-Host 'Done.' -ForegroundColor Green $extracted++ } } diff --git a/lib/download.ps1 b/lib/download.ps1 index d4903bd846..ab74d92652 100644 --- a/lib/download.ps1 +++ b/lib/download.ps1 @@ -391,9 +391,7 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ } if ((Test-Path $data.$url.source) -and -not((Test-Path "$($data.$url.source).aria2") -or (Test-Path $urlstxt)) -and $use_cache) { - Write-Host 'Loading ' -NoNewline - Write-Host $(url_remote_filename $url) -ForegroundColor Cyan -NoNewline - Write-Host ' from cache.' + Write-Host "Loading $([char]0x1b)[36m$(url_remote_filename $url)$([char]0x1b)[0m from cache." } else { $download_finished = $false # create aria2 input file content @@ -425,7 +423,7 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ $aria2 = "& '$(Get-HelperPath -Helper Aria2)' $($options -join ' ')" # handle aria2 console output - Write-Host 'Starting download with aria2 ...' + Write-Host 'Starting download with aria2...' # Set console output encoding to UTF8 for non-ASCII characters printing $oriConsoleEncoding = [Console]::OutputEncoding @@ -466,7 +464,7 @@ function Invoke-CachedAria2Download ($app, $version, $manifest, $architecture, $ warn $urlstxt_content warn $aria2 - Write-Host 'Fallback to default downloader ...' + Write-Host 'Fallback to default downloader...' try { foreach ($url in $urls) { @@ -731,9 +729,7 @@ function check_hash($file, $hash, $app_name) { return $true, $null } - Write-Host 'Checking hash of ' -NoNewline - Write-Host $(url_remote_filename $url) -ForegroundColor Cyan -NoNewline - Write-Host ' ... ' -NoNewline + Write-Host "Checking hash of $([char]0x1b)[36m$(url_remote_filename $url)$([char]0x1b)[0m... " -NoNewline $algorithm, $expected = get_hash $hash if ($null -eq $algorithm) { return $false, "Hash type '$algorithm' isn't supported." @@ -755,7 +751,7 @@ function check_hash($file, $hash, $app_name) { } return $false, $msg } - Write-Host 'ok.' -f Green + Write-Host 'OK.' -f Green return $true, $null } diff --git a/lib/install.ps1 b/lib/install.ps1 index f2dae3886e..1741461bc3 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -165,9 +165,9 @@ function Invoke-HookScript { $script = $script.script } if ($script) { - Write-Host "Running $HookType script..." -NoNewline + Write-Host "Running $HookType script... " -NoNewline Invoke-Command ([scriptblock]::Create($script -join "`r`n")) - Write-Host 'done.' -ForegroundColor Green + Write-Host 'Done.' -ForegroundColor Green } } diff --git a/lib/manifest.ps1 b/lib/manifest.ps1 index 6510dd650c..59e2bd6019 100644 --- a/lib/manifest.ps1 +++ b/lib/manifest.ps1 @@ -18,8 +18,8 @@ function url_manifest($url) { $wc.Headers.Add('User-Agent', (Get-UserAgent)) $data = $wc.DownloadData($url) $str = (Get-Encoding($wc)).GetString($data) - } catch [system.management.automation.methodinvocationexception] { - warn "error: $($_.exception.innerexception.message)" + } catch [System.Management.Automation.MethodInvocationException] { + error $_.Exception.InnerException.Message } catch { throw } diff --git a/libexec/scoop-search.ps1 b/libexec/scoop-search.ps1 index d94b18660d..c38143e528 100644 --- a/libexec/scoop-search.ps1 +++ b/libexec/scoop-search.ps1 @@ -140,8 +140,7 @@ function search_remotes($query) { } | Where-Object { $_.results } if ($results.count -gt 0) { - Write-Host "Results from other known buckets... -(add them using 'scoop bucket add ')" + Write-Host "Results from other known buckets...`n(add them using 'scoop bucket add ')" } $remote_list = @() diff --git a/libexec/scoop-shim.ps1 b/libexec/scoop-shim.ps1 index 26f394dd56..6ceb1af0af 100644 --- a/libexec/scoop-shim.ps1 +++ b/libexec/scoop-shim.ps1 @@ -112,13 +112,10 @@ switch ($SubCommand) { } } if ($commandPath -and (Test-Path $commandPath)) { - Write-Host "Adding $(if ($global) { 'global' } else { 'local' }) shim " -NoNewline - Write-Host $shimName -ForegroundColor Cyan -NoNewline - Write-Host '...' + Write-Host "Adding $(if ($global) { 'global' } else { 'local' }) shim $([char]0x1b)[36m$shimName$([char]0x1b)[0m..." shim $commandPath $global $shimName $commandArgs } else { - Write-Host "ERROR: Command path does not exist: " -ForegroundColor Red -NoNewline - Write-Host $($other[1]) -ForegroundColor Cyan + error "Command path does not exist: $([char]0x1b)[36m$($other[1])$([char]0x1b)[31m" exit 3 } } @@ -133,8 +130,7 @@ switch ($SubCommand) { } if ($failed) { $failed | ForEach-Object { - Write-Host "ERROR: $(if ($global) { 'Global' } else {'Local' }) shim not found: " -ForegroundColor Red -NoNewline - Write-Host $_ -ForegroundColor Cyan + error "$(if ($global) { 'Global' } else { 'Local' }) shim not found: $([char]0x1b)[36m$_$([char]0x1b)[31m" } exit 3 } @@ -147,7 +143,7 @@ switch ($SubCommand) { $pattern = $_ [void][Regex]::New($pattern) } catch { - error "Invalid pattern: $([char]0x1b)[35m$pattern$([char]0x1b)[0m" + error "Invalid pattern: $([char]0x1b)[35m$pattern$([char]0x1b)[31m" exit 1 } } @@ -171,11 +167,9 @@ switch ($SubCommand) { if ($shimPath) { Get-ShimInfo $shimPath } else { - Write-Host "ERROR: $(if ($global) { 'Global' } else { 'Local' }) shim not found: " -ForegroundColor Red -NoNewline - Write-Host $shimName -ForegroundColor Cyan + error "$(if ($global) { 'Global' } else { 'Local' }) shim not found: $([char]0x1b)[36m$shimName$([char]0x1b)[31m" if (Get-ShimPath $shimName (!$global)) { - Write-Host "But a $(if ($global) { 'local' } else {'global' }) shim exists, " -NoNewline - Write-Host "run 'scoop shim info $shimName$(if (!$global) { ' --global' })' to show its info" + Write-Host "But a $(if ($global) { 'local' } else { 'global' }) shim exists, run 'scoop shim info $shimName$(if (!$global) { ' --global' })' to show its info." exit 2 } exit 3 @@ -187,9 +181,7 @@ switch ($SubCommand) { if ($shimPath) { $shimInfo = Get-ShimInfo $shimPath if ($null -eq $shimInfo.Alternatives) { - Write-Host 'ERROR: No alternatives of ' -ForegroundColor Red -NoNewline - Write-Host $shimName -ForegroundColor Cyan -NoNewline - Write-Host ' found.' -ForegroundColor Red + error "No alternatives of $([char]0x1b)[36m$shimName$([char]0x1b)[31m found." exit 2 } $shimInfo.Alternatives = $shimInfo.Alternatives.Split(' ') @@ -198,18 +190,10 @@ switch ($SubCommand) { } $selected = $Host.UI.PromptForChoice("Alternatives of '$shimName' command", "Please choose one that provides '$shimName' as default:", $altApps, 0) if ($selected -eq 0) { - Write-Host 'INFO: ' -ForegroundColor Blue -NoNewline - Write-Host $shimName -ForegroundColor Cyan -NoNewline - Write-Host ' is already from ' -NoNewline - Write-Host $shimInfo.Source -ForegroundColor DarkYellow -NoNewline - Write-Host ', nothing changed.' + Write-Host "$([char]0x1b)[36m$shimName$([char]0x1b)[0m is already from $([char]0x1b)[33m$($shimInfo.Source)$([char]0x1b)[0m, nothing changed." } else { $newApp = $shimInfo.Alternatives[$selected] - Write-Host 'Use ' -NoNewline - Write-Host $shimName -ForegroundColor Cyan -NoNewline - Write-Host ' from ' -NoNewline - Write-Host $newApp -ForegroundColor DarkYellow -NoNewline - Write-Host ' as default...' -NoNewline + Write-Host "Use $([char]0x1b)[36m$shimName$([char]0x1b)[0m from $([char]0x1b)[33m$newApp$([char]0x1b)[0m as default... " -NoNewline $pathNoExt = strip_ext $shimPath '', '.shim', '.cmd', '.ps1' | ForEach-Object { $oldShimPath = "$pathNoExt$_" @@ -221,14 +205,12 @@ switch ($SubCommand) { } } } - Write-Host 'done.' + Write-Host 'Done.' } } else { - Write-Host "ERROR: $(if ($global) { 'Global' } else { 'Local' }) shim not found: " -ForegroundColor Red -NoNewline - Write-Host $shimName -ForegroundColor Cyan + error "$(if ($global) { 'Global' } else { 'Local' }) shim not found: $([char]0x1b)[36m$shimName$([char]0x1b)[31m" if (Get-ShimPath $shimName (!$global)) { - Write-Host "But a $(if ($global) { 'local' } else {'global' }) shim exists, " -NoNewline - Write-Host "run 'scoop shim alter $shimName$(if (!$global) { ' --global' })' to alternate its source" + Write-Host "But a $(if ($global) { 'local' } else { 'global' }) shim exists, run 'scoop shim alter $shimName$(if (!$global) { ' --global' })' to alternate its source." exit 2 } exit 3 From 98765812d4e2b28ba8c45b8b2f4ec689d139ef11 Mon Sep 17 00:00:00 2001 From: Philippe GRANET Date: Wed, 12 Nov 2025 20:37:05 +0100 Subject: [PATCH 22/36] Implement NO_PROXY for git proxy settings Add support for NO_PROXY environment variable in git operations. --- lib/core.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/core.ps1 b/lib/core.ps1 index 7ca7d121e2..b59b655dbe 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -232,6 +232,7 @@ function Invoke-Git { ) $proxy = get_config PROXY + $no_proxy = get_config NO_PROXY $git = Get-HelperPath -Helper Git if ($WorkingDirectory) { @@ -246,11 +247,15 @@ function Invoke-Git { $j = Start-Job -ScriptBlock { # convert proxy setting for git $proxy = $using:proxy + $no_proxy = $using:no_proxy if ($proxy -and $proxy.StartsWith('currentuser@')) { $proxy = $proxy.Replace('currentuser@', ':@') } $env:HTTPS_PROXY = $proxy $env:HTTP_PROXY = $proxy + if ($no_proxy) { + $env:NO_PROXY = $no_proxy + } & $using:git @using:ArgumentList } $o = $j | Receive-Job -Wait -AutoRemoveJob From 69dd3ded6ec959270eefa4c64d96ceed829a78bc Mon Sep 17 00:00:00 2001 From: Philippe GRANET Date: Wed, 12 Nov 2025 20:43:01 +0100 Subject: [PATCH 23/36] Enhance setup_proxy to handle no_proxy settings Add support for no_proxy configuration in setup_proxy function. --- lib/download.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/download.ps1 b/lib/download.ps1 index 70641cca7f..a29053d7f0 100644 --- a/lib/download.ps1 +++ b/lib/download.ps1 @@ -551,6 +551,7 @@ function Get-UserAgent() { function setup_proxy() { # note: '@' and ':' in password must be escaped, e.g. 'p@ssword' -> p\@ssword' $proxy = get_config PROXY + $no_proxy = get_config NO_PROXY if (!$proxy) { return } @@ -572,6 +573,10 @@ function setup_proxy() { $username, $password = $credentials -split '(? Date: Wed, 12 Nov 2025 21:09:20 +0100 Subject: [PATCH 24/36] Trim whitespace from no_proxy before splitting Trimmed whitespace from no_proxy variable before splitting, as reported by @coderabbitai --- lib/download.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/download.ps1 b/lib/download.ps1 index a29053d7f0..23f7a0f5c6 100644 --- a/lib/download.ps1 +++ b/lib/download.ps1 @@ -574,7 +574,7 @@ function setup_proxy() { [net.webrequest]::defaultwebproxy.credentials = New-Object net.networkcredential($username, $password) } if ($no_proxy) { - $bypass_list = $no_proxy -split "\s*,\s*" + $bypass_list = $no_proxy.Trim() -split "\s*,\s*" | Where-Object { $_ -ne '' } [net.webrequest]::defaultwebproxy.BypassList = $bypass_list } } catch { From f2ee3f902fce8e152e7ab55753af9df287d5832c Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Wed, 12 Nov 2025 22:16:10 -0500 Subject: [PATCH 25/36] fix(getopt): Teach getopt to respect the `--%` token (#6477) --- CHANGELOG.md | 1 + lib/getopt.ps1 | 10 +++++----- libexec/scoop-shim.ps1 | 16 ++++++++++------ test/Scoop-GetOpts.Tests.ps1 | 25 ++++++++++++++++++++++--- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4422869443..ae682fd657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) +- **getopt:** Teach getopt to respect the `--%` token ([#6477](https://github.com/ScoopInstaller/Scoop/issues/6477)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) diff --git a/lib/getopt.ps1 b/lib/getopt.ps1 index 2de3ac6c0a..0ba80965ea 100644 --- a/lib/getopt.ps1 +++ b/lib/getopt.ps1 @@ -9,10 +9,10 @@ # a parameter should end with '=' # returns @(opts hash, remaining_args array, error string) # NOTES: -# The first "--" in $argv, if any, will terminate all options; any -# following arguments are treated as non-option arguments, even if -# they begin with a hyphen. The "--" itself will not be included in -# the returned $opts. (POSIX-compatible) +# The first "--" or "--%" in $argv, if any, will terminate all options; any +# following arguments are treated as non-option arguments, even if +# they begin with a hyphen. The terminator token itself ("--" or "--%") +# will not be included. (POSIX-compatible) function getopt([String[]]$argv, [String]$shortopts, [String[]]$longopts) { $opts = @{}; $rem = @() @@ -32,7 +32,7 @@ function getopt([String[]]$argv, [String]$shortopts, [String[]]$longopts) { if ($arg -is [Int]) { $rem += $arg; continue } if ($arg -is [Decimal]) { $rem += $arg; continue } - if ($arg -eq '--') { + if ($arg -eq '--' -or $arg -eq '--%') { if ($i -lt $argv.Length - 1) { $rem += $argv[($i + 1)..($argv.Length - 1)] } diff --git a/libexec/scoop-shim.ps1 b/libexec/scoop-shim.ps1 index 6ceb1af0af..35314e069c 100644 --- a/libexec/scoop-shim.ps1 +++ b/libexec/scoop-shim.ps1 @@ -4,7 +4,7 @@ # # To add a custom shim, use the 'add' subcommand: # -# scoop shim add [...] +# scoop shim add [[--|--%] ...] # # To remove shims, use the 'rm' subcommand: (CAUTION: this could remove shims added by an app manifest) # @@ -25,11 +25,15 @@ # Options: # -g, --global Manipulate global shim(s) # -# HINT: The FIRST double-hyphen '--', if any, will be treated as the POSIX-style command option terminator -# and will NOT be included in arguments, so if you want to pass arguments like '-g' or '--global' to -# the shim, put them after a '--'. Note that in PowerShell, you must use a QUOTED '--', e.g., -# -# scoop shim add myapp 'D:\path\myapp.exe' '--' myapp_args --global +# HINT: The FIRST terminator token ('--' or PowerShell '--%'), if any, is treated as the option +# terminator and will NOT be included; everything after it is passed to the shim. +# So if you want to pass arguments like '-g' or '--global' to the shim, put them after a '--' or '--%'. +# Examples: +# POSIX-style: scoop shim add myapp 'D:\path\myapp.exe' '--' myapp_args --global +# PowerShell: scoop shim add myapp D:\path\myapp.exe --% myapp_args --global +# Notes: +# - In PowerShell, '--' should be quoted to avoid parsing. +# - '--%' disables PowerShell parsing of the remainder; pass literals as needed. param($SubCommand) diff --git a/test/Scoop-GetOpts.Tests.ps1 b/test/Scoop-GetOpts.Tests.ps1 index c55781ecbf..5608cb73ca 100644 --- a/test/Scoop-GetOpts.Tests.ps1 +++ b/test/Scoop-GetOpts.Tests.ps1 @@ -81,13 +81,32 @@ Describe 'getopt' -Tag 'Scoop' { $opt, $rem, $err = getopt '--long-arg', '--' '' 'long-arg' $err | Should -BeNullOrEmpty $opt.'long-arg' | Should -BeTrue - $rem[0] | Should -BeNullOrEmpty + $rem | Should -BeNullOrEmpty + } + + It 'handles remainder args after the option terminator' { $opt, $rem, $err = getopt '--long-arg', '--', '-x', '-y' 'xy' 'long-arg' $err | Should -BeNullOrEmpty $opt.'long-arg' | Should -BeTrue - $opt.'x' | Should -BeNullOrEmpty - $opt.'y' | Should -BeNullOrEmpty + $opt.Keys | Should -Not -Contain 'x' + $opt.Keys | Should -Not -Contain 'y' $rem[0] | Should -Be '-x' $rem[1] | Should -Be '-y' } + + It 'handles PowerShell stop-parsing token' { + $opt, $rem, $err = getopt '--long-arg', '--%' '' 'long-arg' + $err | Should -BeNullOrEmpty + $opt.'long-arg' | Should -BeTrue + $rem | Should -BeNullOrEmpty + } + + It 'handles remainder args after PowerShell stop-parsing token' { + $opt, $rem, $err = getopt @('--long-arg', '--%', '--from', 'there', '--to', 'here') '' 'long-arg' + $err | Should -BeNullOrEmpty + $opt.Keys | Should -Not -Contain 'from' + $opt.Keys | Should -Not -Contain 'to' + $rem | Should -Be @('--from', 'there', '--to', 'here') + } + } From 874e8e6fa129116b33e1e49bba13006b89de5a63 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:09:33 +0800 Subject: [PATCH 26/36] fix(checkver): Fix incorrect version returned when script fails without output (#6547) --- CHANGELOG.md | 1 + bin/checkver.ps1 | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae682fd657..e8ee3e0a4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) +- **checkver:** Fix incorrect version returned when script fails without output ([#6547](https://github.com/ScoopInstaller/Scoop/issues/6547)) - **uninstall:** Import `url_filename` from `download.ps1` ([#6530](https://github.com/ScoopInstaller/Scoop/issues/6530)) - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) - **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) diff --git a/bin/checkver.ps1 b/bin/checkver.ps1 index d5664df5f6..8d6f52df08 100644 --- a/bin/checkver.ps1 +++ b/bin/checkver.ps1 @@ -274,6 +274,8 @@ while ($in_progress -gt 0) { $expected_ver = $json.version $ver = $Version + $matchesHashtable = @{} + if (!$ver) { if (!$regexp -and $replace) { next "'replace' requires 're' or 'regex'" @@ -305,6 +307,11 @@ while ($in_progress -gt 0) { $source = 'the output of script' } + if ($null -eq $page) { + next "couldn't retrieve content from $source" + continue + } + if ($jsonpath) { # Return only a single value if regex is absent $noregex = [String]::IsNullOrEmpty($regexp) @@ -363,7 +370,6 @@ while ($in_progress -gt 0) { } if ($match -and $match.Success) { - $matchesHashtable = @{} $re.GetGroupNames() | ForEach-Object { $matchesHashtable.Add($_, $match.Groups[$_].Value) } $ver = $matchesHashtable['1'] if ($replace) { From 03d831d9a09c78445b8e0eb9e6aabd159c63c945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olav=20R=C3=B8nnestad=20Birkeland?= <6450056+o-l-a-v@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:12:42 +0000 Subject: [PATCH 27/36] fix(install): Don't add to `$Error` when checking for service `cexecsvc` (#6520) --- CHANGELOG.md | 1 + lib/install.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8ee3e0a4c..15dcae7f20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) - **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) +- **install:** Don't add to `$Error` when checking for service `cexecsvc` ([#6520](https://github.com/ScoopInstaller/Scoop/issues/6520)) - **checkver:** Fix incorrect version returned when script fails without output ([#6547](https://github.com/ScoopInstaller/Scoop/issues/6547)) - **uninstall:** Import `url_filename` from `download.ps1` ([#6530](https://github.com/ScoopInstaller/Scoop/issues/6530)) - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) diff --git a/lib/install.ps1 b/lib/install.ps1 index 1741461bc3..78acdd252b 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -557,7 +557,7 @@ function test_running_process($app, $global) { # Required to handle docker/for-win#12240 function New-DirectoryJunction($source, $target) { # test if this script is being executed inside a docker container - if (Get-Service -Name cexecsvc -ErrorAction SilentlyContinue) { + if (Get-Service -Name cexecsvc -ErrorAction Ignore) { cmd.exe /d /c "mklink /j `"$source`" `"$target`"" } else { New-Item -Path $source -ItemType Junction -Value $target From aa499a140af53610446d0c9f1a0a5f87f1f19528 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 18 Nov 2025 10:22:07 +0800 Subject: [PATCH 28/36] builds(sqlite): Update System.Data.SQLite to 2.0.2 (#6555) --- CHANGELOG.md | 4 ++++ lib/database.ps1 | 24 ++++++++++++++---------- libexec/scoop-search.ps1 | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15dcae7f20..95528a541b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,10 @@ - **output:** Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) - **output:** Combine the separated outputs into a single output ([#6545](https://github.com/ScoopInstaller/Scoop/issues/6545)) +### Builds + +- **supporting:** Update System.Data.SQLite to 2.0.2 ([#6555](https://github.com/ScoopInstaller/Scoop/issues/6555)) + ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 ### Features diff --git a/lib/database.ps1 b/lib/database.ps1 index 007abb90b4..e2a52ac379 100644 --- a/lib/database.ps1 +++ b/lib/database.ps1 @@ -16,19 +16,19 @@ #> function Get-SQLite { param ( - [string]$Version = '1.0.118' + [string]$Version = '2.0.2' ) # Install SQLite try { - Write-Host "Downloading SQLite $Version..." -ForegroundColor DarkYellow + Write-Host "Downloading System.Data.SQLite $Version..." -ForegroundColor DarkYellow $sqlitePkgPath = "$env:TEMP\sqlite.zip" $sqliteTempPath = "$env:TEMP\sqlite" $sqlitePath = "$PSScriptRoot\..\supporting\sqlite" - Invoke-WebRequest -Uri "https://api.nuget.org/v3-flatcontainer/stub.system.data.sqlite.core.netframework/$version/stub.system.data.sqlite.core.netframework.$version.nupkg" -OutFile $sqlitePkgPath - Write-Host "Extracting SQLite $Version... " -ForegroundColor DarkYellow -NoNewline + Invoke-WebRequest -Uri "https://globalcdn.nuget.org/packages/system.data.sqlite.$version.nupkg" -OutFile $sqlitePkgPath + Write-Host "Extracting System.Data.SQLite $Version... " -ForegroundColor DarkYellow -NoNewline Expand-Archive -Path $sqlitePkgPath -DestinationPath $sqliteTempPath -Force New-Item -Path $sqlitePath -ItemType Directory -Force | Out-Null - Move-Item -Path "$sqliteTempPath\build\net451\*", "$sqliteTempPath\lib\net451\System.Data.SQLite.dll" -Destination $sqlitePath -Force + Move-Item -Path "$sqliteTempPath\lib\netstandard2.0\System.Data.SQLite.dll" -Destination $sqlitePath -Force Remove-Item -Path $sqlitePkgPath, $sqliteTempPath -Recurse -Force Write-Host 'Done.' -ForegroundColor DarkYellow return $true @@ -219,9 +219,9 @@ function Set-ScoopDB { <# .SYNOPSIS - Select Scoop database item(s). + Find Scoop database item(s). .DESCRIPTION - Select item(s) from the Scoop SQLite database. + Find item(s) from the Scoop SQLite database. The pattern is matched against the name, binaries, and shortcuts columns for apps. .PARAMETER Pattern System.String @@ -233,9 +233,9 @@ function Set-ScoopDB { System.String .OUTPUTS System.Data.DataTable - The selected database item(s). + The found database item(s). #> -function Select-ScoopDBItem { +function Find-ScoopDBItem { [CmdletBinding()] param ( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] @@ -264,6 +264,7 @@ function Select-ScoopDBItem { [void]$dbAdapter.Fill($result) } end { + $dbCommand.Dispose() $dbAdapter.Dispose() $db.Dispose() return $result @@ -322,10 +323,13 @@ function Get-ScoopDBItem { process { $dbCommand.Parameters.AddWithValue('@Name', $Name) | Out-Null $dbCommand.Parameters.AddWithValue('@Bucket', $Bucket) | Out-Null - $dbCommand.Parameters.AddWithValue('@Version', $Version) | Out-Null + if ($Version) { + $dbCommand.Parameters.AddWithValue('@Version', $Version) | Out-Null + } [void]$dbAdapter.Fill($result) } end { + $dbCommand.Dispose() $dbAdapter.Dispose() $db.Dispose() return $result diff --git a/libexec/scoop-search.ps1 b/libexec/scoop-search.ps1 index c38143e528..0698c7a441 100644 --- a/libexec/scoop-search.ps1 +++ b/libexec/scoop-search.ps1 @@ -158,7 +158,7 @@ function search_remotes($query) { if (get_config USE_SQLITE_CACHE) { . "$PSScriptRoot\..\lib\database.ps1" - Select-ScoopDBItem $query -From @('name', 'binary', 'shortcut') | + Find-ScoopDBItem $query -From @('name', 'binary', 'shortcut') | Select-Object -Property name, version, bucket, binary | ForEach-Object { $list.Add([PSCustomObject]@{ From 3a79532d5f85fe526a65c278125cebfdc80ac19e Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:24:39 +0800 Subject: [PATCH 29/36] fix(checkver): Prevent $page from carrying over between iterations (#6556) --- CHANGELOG.md | 2 +- bin/checkver.ps1 | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95528a541b..0da36218d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ - **getopt:** Teach getopt to respect the `--%` token ([#6477](https://github.com/ScoopInstaller/Scoop/issues/6477)) - **core|manifest:** Avoid error messages when searching non-existent 'deprecated' directory ([#6471](https://github.com/ScoopInstaller/Scoop/issues/6471)) - **path:** Trim ending slash when initializing paths ([#6501](https://github.com/ScoopInstaller/Scoop/issues/6501)) -- **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490)) +- **checkver:** Allow script to run when URL fetch fails but script exists ([#6490](https://github.com/ScoopInstaller/Scoop/issues/6490), [#6556](https://github.com/ScoopInstaller/Scoop/issues/6556)) - **install:** Don't add to `$Error` when checking for service `cexecsvc` ([#6520](https://github.com/ScoopInstaller/Scoop/issues/6520)) - **checkver:** Fix incorrect version returned when script fails without output ([#6547](https://github.com/ScoopInstaller/Scoop/issues/6547)) - **uninstall:** Import `url_filename` from `download.ps1` ([#6530](https://github.com/ScoopInstaller/Scoop/issues/6530)) diff --git a/bin/checkver.ps1 b/bin/checkver.ps1 index 8d6f52df08..8b499ad64e 100644 --- a/bin/checkver.ps1 +++ b/bin/checkver.ps1 @@ -292,6 +292,9 @@ while ($in_progress -gt 0) { } } + $page = $null + $source = $url + if ($url -and !$err) { $ms = New-Object System.IO.MemoryStream $ms.Write($result, 0, $result.Length) @@ -301,7 +304,7 @@ while ($in_progress -gt 0) { } $page = (New-Object System.IO.StreamReader($ms, (Get-Encoding $wc))).ReadToEnd() } - $source = $url + if ($script) { $page = Invoke-Command ([scriptblock]::Create($script -join "`r`n")) $source = 'the output of script' From 8468c8cc20e43dfd599d2b4b0d57d5e1e3e43500 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Wed, 26 Nov 2025 23:29:17 +0800 Subject: [PATCH 30/36] fix(sqlite): Add e_sqlite.dll downloading (#6560) --- CHANGELOG.md | 2 +- lib/core.ps1 | 3 --- lib/database.ps1 | 44 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0da36218d3..745b888b32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,7 @@ ### Builds -- **supporting:** Update System.Data.SQLite to 2.0.2 ([#6555](https://github.com/ScoopInstaller/Scoop/issues/6555)) +- **supporting:** Update System.Data.SQLite to 2.0.2 ([#6555](https://github.com/ScoopInstaller/Scoop/issues/6555), [#6560](https://github.com/ScoopInstaller/Scoop/issues/6560)) ## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11 diff --git a/lib/core.ps1 b/lib/core.ps1 index d0ec3ccae4..71f025df54 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -206,9 +206,6 @@ function Complete-ConfigChange { } if ($Name -eq 'use_sqlite_cache' -and $Value -eq $true) { - if ((Get-DefaultArchitecture) -eq 'arm64') { - abort 'SQLite cache is not supported on ARM64 platform.' - } . "$PSScriptRoot\..\lib\database.ps1" . "$PSScriptRoot\..\lib\manifest.ps1" info 'Initializing SQLite cache in progress... This may take a while, please wait.' diff --git a/lib/database.ps1 b/lib/database.ps1 index e2a52ac379..cbe8ec8c18 100644 --- a/lib/database.ps1 +++ b/lib/database.ps1 @@ -4,10 +4,11 @@ .SYNOPSIS Get SQLite .NET driver .DESCRIPTION - Download and extract the SQLite .NET driver from NuGet. + Download and extract the SQLite .NET driver and SQLite precompiled binaries. + The SQLite version is automatically detected from the download page. .PARAMETER Version System.String - The version of the SQLite .NET driver to download. + The version of the System.Data.SQLite NuGet package to download. (require version 2.0.0 or higher) .INPUTS None .OUTPUTS @@ -18,18 +19,41 @@ function Get-SQLite { param ( [string]$Version = '2.0.2' ) - # Install SQLite try { - Write-Host "Downloading System.Data.SQLite $Version..." -ForegroundColor DarkYellow - $sqlitePkgPath = "$env:TEMP\sqlite.zip" + $sqliteNetPath = "$env:TEMP\sqlite.net.zip" + $sqliteDllPath = "$env:TEMP\sqlite.dll.zip" $sqliteTempPath = "$env:TEMP\sqlite" $sqlitePath = "$PSScriptRoot\..\supporting\sqlite" - Invoke-WebRequest -Uri "https://globalcdn.nuget.org/packages/system.data.sqlite.$version.nupkg" -OutFile $sqlitePkgPath - Write-Host "Extracting System.Data.SQLite $Version... " -ForegroundColor DarkYellow -NoNewline - Expand-Archive -Path $sqlitePkgPath -DestinationPath $sqliteTempPath -Force - New-Item -Path $sqlitePath -ItemType Directory -Force | Out-Null + + $arch = switch (Get-DefaultArchitecture) { + '32bit' { 'x86' } + '64bit' { 'x64' } + 'arm64' { 'arm64' } + default { Write-Warning "Unknown architecture, using x64 as fallback"; 'x64' } + } + + Write-Host "Downloading System.Data.SQLite $Version..." -ForegroundColor DarkYellow + Invoke-WebRequest -Uri "https://globalcdn.nuget.org/packages/system.data.sqlite.$Version.nupkg" -OutFile $sqliteNetPath + + $downloadPage = Invoke-WebRequest -Uri 'https://sqlite.org/download.html' -UseBasicParsing + if ($downloadPage.Content -match '(?s)') { + $productData = $Matches[1] | ConvertFrom-Csv + } else { + throw "Failed to parse SQLite download page product data" + } + $matchRow = $productData | Where-Object { $_.'RELATIVE-URL' -match "sqlite-dll-win-$arch-" } + if (-not $matchRow) { + throw "SQLite DLL for architecture $arch not found" + } + Write-Host "Downloading SQLite DLL $($matchRow.VERSION)..." -ForegroundColor DarkYellow + Invoke-WebRequest -Uri "https://sqlite.org/$($matchRow.'RELATIVE-URL')" -OutFile $sqliteDllPath + + Write-Host "Extracting libraries... " -ForegroundColor DarkYellow -NoNewline + $sqliteNetPath, $sqliteDllPath | Expand-Archive -DestinationPath $sqliteTempPath -Force + $null = New-Item -Path "$sqlitePath\$arch" -ItemType Directory -Force Move-Item -Path "$sqliteTempPath\lib\netstandard2.0\System.Data.SQLite.dll" -Destination $sqlitePath -Force - Remove-Item -Path $sqlitePkgPath, $sqliteTempPath -Recurse -Force + Move-Item -Path "$sqliteTempPath\sqlite3.dll" -Destination "$sqlitePath\$arch\e_sqlite3.dll" -Force + Remove-Item -Path $sqliteNetPath, $sqliteDllPath, $sqliteTempPath -Recurse -Force Write-Host 'Done.' -ForegroundColor DarkYellow return $true } catch { From 3bee8159e068a7779697b474cc63518bf85a512d Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Thu, 18 Dec 2025 18:26:01 +0800 Subject: [PATCH 31/36] fix(core): Fix substitute handling of substring keys (#6561) --- CHANGELOG.md | 1 + lib/core.ps1 | 9 +++++---- test/Scoop-Core.Tests.ps1 | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 745b888b32..8720581fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - **uninstall:** Import `url_filename` from `download.ps1` ([#6530](https://github.com/ScoopInstaller/Scoop/issues/6530)) - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) - **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) +- **core:** Fix substitute handling of substring keys ([#6561](https://github.com/ScoopInstaller/Scoop/issues/6561)) ### Code Refactoring diff --git a/lib/core.ps1 b/lib/core.ps1 index 71f025df54..f36ca7a839 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -1209,11 +1209,12 @@ function substitute($entity, [Hashtable] $params, [Bool]$regexEscape = $false) { $newentity = $entity.PSObject.Copy() switch ($entity.GetType().Name) { 'String' { - $params.GetEnumerator() | ForEach-Object { - if ($regexEscape -eq $false -or $null -eq $_.Value) { - $newentity = $newentity.Replace($_.Name, $_.Value) + $params.Keys | Sort-Object Length -Descending | ForEach-Object { + $value = $params[$_] + if ($regexEscape -eq $false -or $null -eq $value) { + $newentity = $newentity.Replace($_, $value) } else { - $newentity = $newentity.Replace($_.Name, [Regex]::Escape($_.Value)) + $newentity = $newentity.Replace($_, [Regex]::Escape($value)) } } } diff --git a/test/Scoop-Core.Tests.ps1 b/test/Scoop-Core.Tests.ps1 index d1cc9defe3..a857ec47e4 100644 --- a/test/Scoop-Core.Tests.ps1 +++ b/test/Scoop-Core.Tests.ps1 @@ -393,3 +393,17 @@ Describe 'Format Architecture String' -Tag 'Scoop' { { Format-ArchitectureString 'PPC' } | Should -Throw "Invalid architecture: 'ppc'" } } + +Describe 'substitute' -Tag 'Scoop' { + It 'should properly handle keys that are substrings of other keys' { + $params = @{} + + # Run repeatedly (10 times) to reduce the likelihood of accidental correct ordering. + 1 .. 10 | ForEach-Object { + $params["`$name$($_)"] = "$($_).exe" + $params["`$name$($_)NoExt"] = "$_" + + substitute ("`$name$($_)NoExt") $params $false | Should -Be "$_" + } + } +} From bdf6344423c92bbd0f5ccc7f90cdb17f109d1366 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Tue, 30 Dec 2025 11:15:44 +0800 Subject: [PATCH 32/36] fix(checkver): Remove redundant always-true condition in GitHub checkver logic (#6571) --- CHANGELOG.md | 1 + bin/checkver.ps1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8720581fbf..8c53cd6b67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) - **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) - **core:** Fix substitute handling of substring keys ([#6561](https://github.com/ScoopInstaller/Scoop/issues/6561)) +- **checkver:** Remove redundant always-true condition in GitHub checkver logic ([#6571](https://github.com/ScoopInstaller/Scoop/issues/6571)) ### Code Refactoring diff --git a/bin/checkver.ps1 b/bin/checkver.ps1 index 8b499ad64e..823d7ce979 100644 --- a/bin/checkver.ps1 +++ b/bin/checkver.ps1 @@ -159,7 +159,7 @@ $Queue | ForEach-Object { if ($json.checkver.github) { $url = $json.checkver.github.TrimEnd('/') + '/releases/latest' $regex = $githubRegex - if ($json.checkver.PSObject.Properties.Count -eq 1) { $useGithubAPI = $true } + $useGithubAPI = $true } # SourceForge From 309fb0273ecc24104c22f5c90dcf95d76a1726b0 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Tue, 30 Dec 2025 11:19:04 +0800 Subject: [PATCH 33/36] fix(scoop-download): Fix incorrect download success state (#6473) --- CHANGELOG.md | 1 + libexec/scoop-download.ps1 | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c53cd6b67..ef6a1a06d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - **core:** Fix the grep parameter in the `Invoke-GitLog` function ([#6407](https://github.com/ScoopInstaller/Scoop/issues/6407)) - **buckets:** Fix the filtering condition when retrieving the number of manifests ([#6509](https://github.com/ScoopInstaller/Scoop/issues/6509)) - **scoop-download:** Fix function `nightly_version` not defined error ([#6386](https://github.com/ScoopInstaller/Scoop/issues/6386)) +- **scoop-download:** Fix incorrect download success state ([#6473](https://github.com/ScoopInstaller/Scoop/issues/6473)) - **scoop-uninstall:** Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) - **scoop-update:** Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) diff --git a/libexec/scoop-download.ps1 b/libexec/scoop-download.ps1 index 1deba8a808..76c894834b 100644 --- a/libexec/scoop-download.ps1 +++ b/libexec/scoop-download.ps1 @@ -42,6 +42,8 @@ try { abort "ERROR: $_" } +$apps = $apps | Select-Object -Unique + if (!$apps) { error ' missing'; my_usage; exit 1 } if (is_scoop_outdated) { @@ -100,6 +102,8 @@ foreach ($curr_app in $apps) { continue } + $dl_failure = $false + if(Test-Aria2Enabled) { Invoke-CachedAria2Download $app $version $manifest $architecture $cachedir $manifest.cookie $use_cache $curr_check_hash } else { @@ -129,6 +133,7 @@ foreach ($curr_app in $apps) { warn 'SourceForge.net is known for causing hash validation fails. Please try again before opening a ticket.' } error (new_issue_msg $app $bucket "hash check failed") + $dl_failure = $true continue } } else { From aa3f9aa983c0180b99065fac4946a17c4a410307 Mon Sep 17 00:00:00 2001 From: abgox Date: Tue, 30 Dec 2025 11:23:28 +0800 Subject: [PATCH 34/36] fix(core): check $deprecated_dir exists before accessing it (#6574) --- CHANGELOG.md | 1 + lib/core.ps1 | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef6a1a06d0..2e756db525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - **schema:** Add missing `hash.mode` value `github` ([#6533](https://github.com/ScoopInstaller/Scoop/issues/6533)) - **core:** Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir` function ([#6541](https://github.com/ScoopInstaller/Scoop/issues/6541)) - **core:** Fix substitute handling of substring keys ([#6561](https://github.com/ScoopInstaller/Scoop/issues/6561)) +- **core:** Check `$deprecated_dir` exists before accessing it ([#6574](https://github.com/ScoopInstaller/Scoop/issues/6574)) - **checkver:** Remove redundant always-true condition in GitHub checkver logic ([#6571](https://github.com/ScoopInstaller/Scoop/issues/6571)) ### Code Refactoring diff --git a/lib/core.ps1 b/lib/core.ps1 index f36ca7a839..11daac73f5 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -552,7 +552,9 @@ function app_status($app, $global) { $status.hold = ($install_info.hold -eq $true) $deprecated_dir = (Find-BucketDirectory -Name $install_info.bucket -Root) + "\deprecated" - $status.deprecated = (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse -ErrorAction Ignore).FullName + if (Test-Path $deprecated_dir) { + $status.deprecated = (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse).FullName + } $manifest = manifest $app $install_info.bucket $install_info.url $status.removed = (!$manifest) From bd2e93df635de0538ff2afc3dd3bb5a792e956a2 Mon Sep 17 00:00:00 2001 From: z-Fng <54583083+z-Fng@users.noreply.github.com> Date: Tue, 6 Jan 2026 00:31:19 -0500 Subject: [PATCH 35/36] fix(autoupdate): Ensure GitHub API requests use token (#6535) --- CHANGELOG.md | 1 + lib/autoupdate.ps1 | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e756db525..dc60da8539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - **scoop-uninstall:** Correct `-Global` Switch ([#6454](https://github.com/ScoopInstaller/Scoop/issues/6454)) - **scoop-update:** Force sync tags w/ remote branch while scoop update ([#6439](https://github.com/ScoopInstaller/Scoop/issues/6439)) - **autoupdate:** Use origin URL to handle URLs with fragment in GitHub mode ([#6455](https://github.com/ScoopInstaller/Scoop/issues/6455)) +- **autoupdate:** Ensure GitHub API requests use token ([#6535](https://github.com/ScoopInstaller/Scoop/issues/6535)) - **buckets|scoop-info:** Switch git log date format to ISO 8601 to avoid locale issues ([#6446](https://github.com/ScoopInstaller/Scoop/issues/6446)) - **scoop-version:** Fix logic error caused by missing brackets ([#6463](https://github.com/ScoopInstaller/Scoop/issues/6463)) - **getopt:** Teach getopt to respect the `--%` token ([#6477](https://github.com/ScoopInstaller/Scoop/issues/6477)) diff --git a/lib/autoupdate.ps1 b/lib/autoupdate.ps1 index fbc3ebfdee..5ed0387b1d 100644 --- a/lib/autoupdate.ps1 +++ b/lib/autoupdate.ps1 @@ -118,6 +118,12 @@ function find_hash_in_json([String] $url, [Hashtable] $substitutions, [String] $ $wc = New-Object Net.Webclient $wc.Headers.Add('Referer', (strip_filename $url)) $wc.Headers.Add('User-Agent', (Get-UserAgent)) + + if (($url -match '^https?://api\.github\.com/.*') -and (Get-GitHubToken)) { + $wc.Headers.Add('Authorization', "Bearer $(Get-GitHubToken)") + $wc.Headers.Add('X-GitHub-Api-Version', '2022-11-28') + } + $data = $wc.DownloadData($url) $ms = New-Object System.IO.MemoryStream $ms.Write($data, 0, $data.Length) From 0d0334ccf2e86d4cfaa4da38efe240098868b5c5 Mon Sep 17 00:00:00 2001 From: abgox Date: Sat, 28 Feb 2026 14:51:50 +0800 Subject: [PATCH 36/36] perf(scoop-list): use simpler method to check the deprecated status of the manifest (#6599) * perf(scoop-list): use simpler method to check the deprecated status of the manifest to improve performance * style: remove blank lines --- CHANGELOG.md | 1 + libexec/scoop-list.ps1 | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc60da8539..1b5933ca2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - **output:** Replace raw prints with functions for standardized output ([#6449](https://github.com/ScoopInstaller/Scoop/issues/6449)) - **output:** Combine the separated outputs into a single output ([#6545](https://github.com/ScoopInstaller/Scoop/issues/6545)) +- **scoop-list:** Use simpler method to check the deprecated status of the manifest to improve performance ([#6599](https://github.com/ScoopInstaller/Scoop/issues/6599)) ### Builds diff --git a/libexec/scoop-list.ps1 b/libexec/scoop-list.ps1 index aded1e5ee0..b257823f0a 100644 --- a/libexec/scoop-list.ps1 +++ b/libexec/scoop-list.ps1 @@ -48,7 +48,10 @@ $apps | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object { $item.Updated = $updated $info = @() - if ((app_status $app $global).deprecated) { $info += 'Deprecated package' } + $deprecated_dir = (Find-BucketDirectory -Name $install_info.bucket -Root) + "\deprecated" + if ((Test-Path $deprecated_dir) -and (Get-ChildItem $deprecated_dir -Filter "$(sanitary_path $app).json" -Recurse)) { + $info += 'Deprecated package' + } if ($global) { $info += 'Global install' } if (failed $app $global) { $info += 'Install failed' } if ($install_info.hold) { $info += 'Held package' }