Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
691c233
fix(scoop-download): Fix function `nightly_version` not defined error…
AkariiinMKII Aug 14, 2025
c9f0728
fix(autoupdate): Use origin url to handle urls with fragment in githu…
HUMORCE Aug 20, 2025
ff38652
fix(buckets|scoop-info): Switch git log date format to ISO 8601 to av…
z-Fng Aug 21, 2025
04b7ce7
fix(scoop-version): Fix logic error caused by missing brackets (#6463)
z-Fng Aug 27, 2025
25d3500
fix(core|manifest): Avoid error when searching non-existent 'deprecat…
z-Fng Sep 24, 2025
b592b38
feat(install): Add separator at the end of notes, highlight suggestio…
z-Fng Sep 24, 2025
db8d554
fix(scoop-update): Force sync tags w/ remote branch while scoop updat…
niheaven Sep 26, 2025
4c55e7a
feat(scoop-uninstall): Allow access to $bucket in uninstall scripts (…
abgox Sep 26, 2025
2a63736
fix(scoop-uninstall): Correct `-Global` switch during uninstalling/up…
HUMORCE Sep 26, 2025
ca0506c
refactor(output): Replace raw prints with functions for standardized …
abgox Sep 29, 2025
20a178b
fix(checkver): Allow script to run when URL fetch fails but script ex…
z-Fng Oct 13, 2025
52a035b
fix(path): Trim ending slash when initializing paths (#6501)
niheaven Oct 21, 2025
7966971
fix(schema): add github to the mode of hash (#6534)
abgox Nov 3, 2025
2120c28
fix(buckets): fix the filtering condition when retrieving the number …
abgox Nov 8, 2025
28c51e0
feat(download|scoop-config): Allow disabling automatic fallback to th…
z-Fng Nov 8, 2025
a8d4027
fix(core): Fix the grep parameter in the Invoke-GitLog function (#6407)
abgox Nov 10, 2025
f9c6913
feat(download|scoop-download): Add GitHub issue prompt when the defau…
z-Fng Nov 10, 2025
f0cd3e1
fix(core): Skip NO_JUNCTION logic when $app is 'scoop' in `currentdir…
z-Fng Nov 10, 2025
7e86336
feat(install): Add output for the setting and removal of environment …
abgox Nov 10, 2025
7399945
fix(uninstall): Import url_filename from download.ps1 (#6530)
xrgzs Nov 11, 2025
0e698cc
refactor(output): Combine the separated outputs into a single output …
abgox Nov 11, 2025
f2ee3f9
fix(getopt): Teach getopt to respect the `--%` token (#6477)
refack Nov 13, 2025
874e8e6
fix(checkver): Fix incorrect version returned when script fails witho…
z-Fng Nov 15, 2025
03d831d
fix(install): Don't add to `$Error` when checking for service `cexecs…
o-l-a-v Nov 16, 2025
aa499a1
builds(sqlite): Update System.Data.SQLite to 2.0.2 (#6555)
niheaven Nov 18, 2025
3a79532
fix(checkver): Prevent $page from carrying over between iterations (#…
z-Fng Nov 18, 2025
8468c8c
fix(sqlite): Add e_sqlite.dll downloading (#6560)
niheaven Nov 26, 2025
3bee815
fix(core): Fix substitute handling of substring keys (#6561)
z-Fng Dec 18, 2025
bdf6344
fix(checkver): Remove redundant always-true condition in GitHub check…
z-Fng Dec 30, 2025
309fb02
fix(scoop-download): Fix incorrect download success state (#6473)
z-Fng Dec 30, 2025
aa3f9aa
fix(core): check $deprecated_dir exists before accessing it (#6574)
abgox Dec 30, 2025
bd2e93d
fix(autoupdate): Ensure GitHub API requests use token (#6535)
z-Fng Jan 6, 2026
0d0334c
perf(scoop-list): use simpler method to check the deprecated status o…
abgox Feb 28, 2026
3cc2fe7
ci: refactor ci workflow (#6626)
chawyehsu Apr 3, 2026
a5c3b58
fix(buckets): Skip Git invocation if unavailable in `new_issue_msg` (…
z-Fng Apr 3, 2026
befdb20
fix(core): Give `dark` higher priority when use `Extract-DarkArchive`…
niheaven Apr 13, 2026
2106908
fix(core): add null checks before closing BinaryReader/FileStream in …
mertemr Apr 20, 2026
cc8d7ca
docs: remove gitter from README (#6640)
deevus Apr 20, 2026
3533442
fix(checkver): Harden github checkver (#6641)
chawyehsu Apr 24, 2026
a7a7d34
fix(scoop-search): Select latest search result semantically (#6643)
B67687 Apr 27, 2026
cbd7c64
feat(checkver)!: Set GitHub mode default jsonpath and regex (#6653)
chawyehsu May 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 16 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
name: Scoop Core CI Tests
name: CI

on:
pull_request:
workflow_dispatch:

jobs:
test_powershell:
name: WindowsPowerShell
test:
name: Test
runs-on: windows-latest
strategy:
matrix:
shell: [powershell, pwsh]
defaults:
run:
shell: ${{ matrix.shell }}
steps:
- name: Checkout
uses: actions/checkout@main
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# Need at least 2 commits to properly gather changed files for linting
fetch-depth: 2
- name: Init Test Suite
uses: potatoqualitee/psmodulecache@main
- name: Install and cache test dependencies
uses: potatoqualitee/psmodulecache@ee5e9494714abf56f6efbfa51527b2aec5c761b8 # v6.2.1
with:
modules-to-cache: BuildHelpers
shell: powershell
- name: Test Scoop Core
shell: powershell
run: ./test/bin/test.ps1
test_pwsh:
name: PowerShell
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@main
with:
fetch-depth: 2
- name: Init Test Suite
uses: potatoqualitee/psmodulecache@main
with:
modules-to-cache: BuildHelpers
shell: pwsh
- name: Test Scoop Core
shell: pwsh
modules-to-cache: PSScriptAnalyzer, BuildHelpers, Pester
shell: ${{ matrix.shell }}
- name: Run tests
run: ./test/bin/test.ps1
62 changes: 58 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,69 @@
## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/v0.5.3...develop)

### 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))
- **download|scoop-config:** Allow disabling automatic fallback to the default downloader when Aria2c download fails ([#6538](https://github.com/ScoopInstaller/Scoop/issues/6538))
- **checkver:** Set GitHub mode default jsonpath and regex ([#6653](https://github.com/ScoopInstaller/Scoop/issues/6653))

### Bug Fixes

- **core:** Fix the grep parameter in the `Invoke-GitLog` function ([#6407](https://github.com/ScoopInstaller/Scoop/issues/6407))
- **buckets:** Skip Git invocation if unavailable in `new_issue_msg` ([#6591](https://github.com/ScoopInstaller/Scoop/issues/6591))
- **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))
- **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))
- **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), [#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))
- **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))
- **core:** Give `dark` higher priority when use `Extract-DarkArchive` ([#6637](https://github.com/ScoopInstaller/Scoop/issues/6637))
- **checkver:** Harden github checkver ([#6641](https://github.com/ScoopInstaller/Scoop/issues/6641))
- **scoop-search:** Select latest search result semantically ([#6643](https://github.com/ScoopInstaller/Scoop/issues/6643))

### 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))
- **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

- **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))

### Continuous Integration

- **workflow:** Drop Appveyor support and refactor GitHub Actions workflow ([#6626](https://github.com/ScoopInstaller/Scoop/issues/6626))

## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2025-08-11

### 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))
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
<a href="https://discord.gg/s9yRQHt">
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
</a>
<a href="https://gitter.im/lukesampson/scoop">
<img src="https://badges.gitter.im/lukesampson/scoop.png" alt="Gitter Chat" />
</a>
<a href="./LICENSE">
<img src="https://img.shields.io/badge/license-UNLICENSE%20or%20MIT-blue" alt="License" />
</a>
Expand Down
35 changes: 0 additions & 35 deletions appveyor.yml

This file was deleted.

113 changes: 74 additions & 39 deletions bin/checkver.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Get-Event | Remove-Event
Get-EventSubscriber | Unregister-Event

# start all downloads
$in_progress = 0
$Queue | ForEach-Object {
$name, $json, $file = $_

Expand All @@ -119,47 +120,73 @@ $Queue | ForEach-Object {
} else {
$wc.Headers.Add('User-Agent', (Get-UserAgent))
}
Register-ObjectEvent $wc downloadDataCompleted -ErrorAction Stop | Out-Null

# Not Specified
$url = $json.homepage
$regex = ''
$jsonpath = ''
$xpath = ''
$replace = ''

if ($json.checkver.url) {
$url = $json.checkver.url
} else {
$url = $json.homepage
}

if ($json.checkver.re) {
$regex = $json.checkver.re
} elseif ($json.checkver.regex) {
$regex = $json.checkver.regex
} else {
$regex = ''
}

$jsonpath = ''
$xpath = ''
$replace = ''
$useGithubAPI = $false
## GitHub
#
# ```json
# "homepage": "<valid-repository-url>",
# "checkver": "github"
# ```
#
# or
#
# ```json
# "checkver": {
# "github": "<valid-repository-url-or-repository-api-url>"
# }
# ```
if (($json.checkver -eq 'github') -or $json.checkver.github) {
$githubUrlPattern = '^https://((www\.)?github\.com/[\w.-]+/[\w.-]+/?|api\.github\.com/repos/[\w.-]+/[\w.-]+/.+)$'

$inputGithubUrl = $json.homepage
$fieldUsed = 'homepage'
if ($json.checkver.github) {
$inputGithubUrl = $json.checkver.github
$fieldUsed = 'checkver.github'
}

# GitHub
if ($regex) {
$githubRegex = $regex
} else {
$githubRegex = '/releases/tag/(?:v|V)?([\d.]+)'
}
if ($json.checkver -eq 'github') {
if (!$json.homepage.StartsWith('https://github.com/')) {
error "$name checkver expects the homepage to be a github repository"
if ($inputGithubUrl -notmatch $githubUrlPattern) {
error "$name checkver expects $fieldUsed to be a valid GitHub repository URL"
return
}

$url = $inputGithubUrl.TrimEnd('/')
if ($url -notlike 'https://api.github.com*') {
$url = $url + '/releases/latest'
}

if ($GitHubToken) {
$url = $url -replace '//(www\.)?github\.com/', '//api.github.com/repos/'
$wc.Headers.Add('Authorization', "token $GitHubToken")
}
$url = $json.homepage.TrimEnd('/') + '/releases/latest'
$regex = $githubRegex
$useGithubAPI = $true
}

if ($json.checkver.github) {
$url = $json.checkver.github.TrimEnd('/') + '/releases/latest'
$regex = $githubRegex
if ($json.checkver.PSObject.Properties.Count -eq 1) { $useGithubAPI = $true }
if ($url -like 'https://api.github.com*') {
# Default jsonpath/regex in GitHub API mode
$jsonpath = '$.tag_name'
if (-not $regex) {
$regex = '(?:v|V)?([\d.-]+)'
}
} elseif (-not $regex) {
# Default regex in GitHub HTML mode
$regex = '/releases/tag/(?:v|V)?([\d.-]+)'
}
}

# SourceForge
Expand Down Expand Up @@ -216,13 +243,6 @@ $Queue | ForEach-Object {

$reverse = $json.checkver.reverse -and $json.checkver.reverse -eq 'true'

if ($url -like '*api.github.com/*') { $useGithubAPI = $true }

if ($useGithubAPI -and ($null -ne $GitHubToken)) {
$url = $url -replace '//(www\.)?github.com/', '//api.github.com/repos/'
$wc.Headers.Add('Authorization', "token $GitHubToken")
}

$url = substitute $url $substitutions

$state = New-Object psobject @{
Expand All @@ -244,7 +264,9 @@ $Queue | ForEach-Object {
}

$wc.Headers.Add('Referer', (strip_filename $url))
Register-ObjectEvent $wc downloadDataCompleted -ErrorAction Stop | Out-Null
$wc.DownloadDataAsync($url, $state)
$in_progress++
}

function next($er) {
Expand All @@ -253,7 +275,6 @@ function next($er) {
}

# wait for all to complete
$in_progress = $Queue.length
while ($in_progress -gt 0) {
$ev = Wait-Event
Remove-Event $ev.SourceIdentifier
Expand All @@ -274,18 +295,28 @@ while ($in_progress -gt 0) {
$expected_ver = $json.version
$ver = $Version

$matchesHashtable = @{}

if (!$ver) {
if (!$regexp -and $replace) {
next "'replace' requires 're' or 'regex'"
continue
}
$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) {
$page = $null
$source = $url

if ($url -and !$err) {
$ms = New-Object System.IO.MemoryStream
$ms.Write($result, 0, $result.Length)
$ms.Seek(0, 0) | Out-Null
Expand All @@ -294,12 +325,17 @@ 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'
}

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)
Expand Down Expand Up @@ -358,7 +394,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) {
Expand Down
8 changes: 4 additions & 4 deletions bin/scoop.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ''
}
}
Expand Down
Loading
Loading