Files
Scoop/lib/manifest.ps1
Hsiao-nan Cheung ebd8c036fa chore(release): Bump to version 0.5.3 (#6257)
* fix (decompress): `Expand-7zipArchive` only delete temp dir / `$extractDir` if it is empty (#6092)

Co-authored-by: Hsiao-nan Cheung <niheaven@gmail.com>

* refactor(download): Move download-related functions to 'download.ps1' (#6095)

* fix(download): Fallback to default downloader when aria2 fails (#4292)

* fix(commands): Handling broken aliases (#6141)

* fix(shim): properly check `wslpath`/`cygpath` command first (#6114)

Co-authored-by: Hsiao-nan Cheung <niheaven@gmail.com>

* fix(scoop-bucket): Add missing import for `no_junction` envs (#6181)

Signed-off-by: Chawye Hsu <su+git@chawyehsu.com>

* docs(chglog): Update to 0.5.3 (#6258)

* perf(shim): Update kiennq-shim to v3.1.2 (#6261)

* fix(decompress): Replace deprecated 7ZIPEXTRACT_USE_EXTERNAL config (#6327)

Co-authored-by: Hsiao-nan Cheung <niheaven@gmail.com>

* fix(scoop-uninstall): Fix uninstaller does not gain Global state (#6430)

* global arg

* changelog

* refactor(Get-Manifest): Select actual source for manifest (#6142)

* first step

* Revert "first step"

This reverts commit c5907c3e25.

* refactor(Get-Manifest): Select actual source for installed manifest

* rework sub-commands, `scoop-depends` is NOT working at this stage

* URI manifest

* opt

* deprecated manifest

* source of manifests

* source of manifest pt2

- Mark URI(path/URL/UNC/etc.) query as standalone manifest
- Drop `installed` and `available update` items for [query] and [installed] are different sources.

* remove variable preventing I forget it

* scoop-info: fix source of manifest on bucket

* fix `scoop-depends`

* Fix Standalone and Source detection

* fix global install

* Fix scoop-cat, scoop-home

- Query for remote manifest

* scoop-list: info +deprecated

* manifest: Fix first selected manifest

* gramma..

* Fix 61b3259

* length

* fix(scoop-depends-tests): Mocking `USE_EXTERNAL_7ZIP` as $false (#6431)

* fix(scoop-depends-tests): Mocking `USE_EXTERNAL_7ZIP` as $false to avoding error when it is $true

* CHANGELOG

* feat(autoupdate): GitHub predefined hashes support (#6416)

* feat(autoupdate): predefined hash case for GitHub

- Remove `sha256:` prefix in `format_hash()`
- Add GitHub support in `get_hash_for_app()`

Close #6381

* doc(chglog): GitHub auto hash update

* fix(autoupdate): remove prefix only

* docs(CHANGELOG): Update to 0.5.3 (#6432)

* docs(CHANGELOG): Update to 0.5.3

* 6416

---------

Signed-off-by: Chawye Hsu <su+git@chawyehsu.com>
Co-authored-by: Olav Rønnestad Birkeland <6450056+o-l-a-v@users.noreply.github.com>
Co-authored-by: kiennq <kien.n.quang@gmail.com>
Co-authored-by: HUMORCE <humorce@outlook.com>
Co-authored-by: Ryan <sitiom@proton.me>
Co-authored-by: Chawye Hsu <su+git@chawyehsu.com>
Co-authored-by: Bassel Rachid <101208715+basselworkforce@users.noreply.github.com>
Co-authored-by: Wordless Echo <wordless@echo.moe>
2025-08-11 00:38:38 +00:00

215 lines
7.8 KiB
PowerShell

function manifest_path($app, $bucket) {
(Get-ChildItem (Find-BucketDirectory $bucket) -Filter "$(sanitary_path $app).json" -Recurse).FullName
}
function parse_json($path) {
if ($null -eq $path -or !(Test-Path $path)) { return $null }
try {
Get-Content $path -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
} catch {
warn "Error parsing JSON at '$path'."
}
}
function url_manifest($url) {
$str = $null
try {
$wc = New-Object Net.Webclient
$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 {
throw
}
if (!$str) { return $null }
try {
$str | ConvertFrom-Json -ErrorAction Stop
} catch {
warn "Error parsing JSON at '$url'."
}
}
function Get-Manifest($app) {
$bucket, $manifest, $url = $null
$app = $app.TrimStart('/')
# check if app is a URL or UNC path
if ($app -match '^(ht|f)tps?://|\\\\') {
$url = $app
$app = appname_from_url $url
$manifest = url_manifest $url
} else {
# Check if the manifest is already installed
if (installed $app) {
$global = installed $app $true
$ver = Select-CurrentVersion -AppName $app -Global:$global
if (!$ver) {
$app, $bucket, $ver = parse_app $app
$ver = Select-CurrentVersion -AppName $app -Global:$global
}
$install_info_path = "$(versiondir $app $ver $global)\install.json"
if (Test-Path $install_info_path) {
$install_info = parse_json $install_info_path
$bucket = $install_info.bucket
if (!$bucket) {
$url = $install_info.url
if ($url -match '^(ht|f)tps?://|\\\\') {
$manifest = url_manifest $url
}
if (!$manifest) {
if (Test-Path $url) {
$manifest = parse_json $url
} else {
# Fallback to installed manifest
$manifest = installed_manifest $app $ver $global
}
}
} else {
$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
}
}
}
} else {
$app, $bucket, $version = parse_app $app
if ($bucket) {
$manifest = manifest $app $bucket
} else {
$matched_buckets = @()
foreach ($tekcub in Get-LocalBucket) {
$current_manifest = manifest $app $tekcub
if (!$manifest -and $current_manifest) {
$manifest = $current_manifest
$bucket = $tekcub
}
if ($current_manifest) {
$matched_buckets += $tekcub
}
}
}
if (!$manifest) {
# couldn't find app in buckets: check if it's a local path
if (Test-Path $app) {
$url = Convert-Path $app
$app = appname_from_url $url
$manifest = parse_json $url
} else {
if (($app -match '\\/') -or $app.EndsWith('.json')) { $url = $app }
$app = appname_from_url $app
}
}
}
}
if ($matched_buckets.Length -gt 1) {
warn "Multiple buckets contain manifest '$app', the current selection is '$bucket/$app'."
}
return $app, $manifest, $bucket, $url
}
function manifest($app, $bucket, $url) {
if ($url) { return url_manifest $url }
parse_json (manifest_path $app $bucket)
}
function save_installed_manifest($app, $bucket, $dir, $url) {
if ($url) {
$wc = New-Object Net.Webclient
$wc.Headers.Add('User-Agent', (Get-UserAgent))
$data = $wc.DownloadData($url)
(Get-Encoding($wc)).GetString($data) | Out-UTF8File "$dir\manifest.json"
} else {
Copy-Item (manifest_path $app $bucket) "$dir\manifest.json"
}
}
function installed_manifest($app, $version, $global) {
parse_json "$(versiondir $app $version $global)\manifest.json"
}
function save_install_info($info, $dir) {
$nulls = $info.keys | Where-Object { $null -eq $info[$_] }
$nulls | ForEach-Object { $info.remove($_) } # strip null-valued
$file_content = $info | ConvertToPrettyJson # in 'json.ps1'
[System.IO.File]::WriteAllLines("$dir\install.json", $file_content)
}
function install_info($app, $version, $global) {
$path = "$(versiondir $app $version $global)\install.json"
if (!(Test-Path $path)) { return $null }
parse_json $path
}
function arch_specific($prop, $manifest, $architecture) {
if ($manifest.architecture) {
$val = $manifest.architecture.$architecture.$prop
if ($val) { return $val } # else fallback to generic prop
}
if ($manifest.$prop) { return $manifest.$prop }
}
function Get-SupportedArchitecture($manifest, $architecture) {
if ($architecture -eq 'arm64' -and ($manifest | ConvertToPrettyJson) -notmatch '[''"]arm64["'']') {
# Windows 10 enables existing unmodified x86 apps to run on Arm devices.
# Windows 11 adds the ability to run unmodified x64 Windows apps on Arm devices!
# Ref: https://learn.microsoft.com/en-us/windows/arm/overview
if ($WindowsBuild -ge 22000) {
# Windows 11
$architecture = '64bit'
} else {
# Windows 10
$architecture = '32bit'
}
}
if (![String]::IsNullOrEmpty((arch_specific 'url' $manifest $architecture))) {
return $architecture
}
}
function generate_user_manifest($app, $bucket, $version) {
# 'autoupdate.ps1' 'buckets.ps1' 'manifest.ps1'
$app, $manifest, $bucket, $null = Get-Manifest "$bucket/$app"
if ("$($manifest.version)" -eq "$version") {
return manifest_path $app $bucket
}
warn "Given version ($version) does not match manifest ($($manifest.version))"
warn "Attempting to generate manifest for '$app' ($version)"
ensure (usermanifestsdir) | Out-Null
$manifest_path = "$(usermanifestsdir)\$app.json"
if (get_config USE_SQLITE_CACHE) {
$cached_manifest = (Get-ScoopDBItem -Name $app -Bucket $bucket -Version $version).manifest
if ($cached_manifest) {
$cached_manifest | Out-UTF8File $manifest_path
return $manifest_path
}
}
if (!($manifest.autoupdate)) {
abort "'$app' does not have autoupdate capability`r`ncouldn't find manifest for '$app@$version'"
}
try {
Invoke-AutoUpdate $app $manifest_path $manifest $version $(@{ })
return $manifest_path
} catch {
Write-Host -ForegroundColor DarkRed "Could not install $app@$version"
}
return $null
}
function url($manifest, $arch) { arch_specific 'url' $manifest $arch }
function installer($manifest, $arch) { arch_specific 'installer' $manifest $arch }
function uninstaller($manifest, $arch) { arch_specific 'uninstaller' $manifest $arch }
function hash($manifest, $arch) { arch_specific 'hash' $manifest $arch }
function extract_dir($manifest, $arch) { arch_specific 'extract_dir' $manifest $arch }
function extract_to($manifest, $arch) { arch_specific 'extract_to' $manifest $arch }