10 Commits

Author SHA1 Message Date
Hsiao-nan Cheung
9f62e55862 Merge branch 'develop' into feature/install_via_git_history 2025-08-12 18:29:52 +08:00
Hsiao-nan Cheung
b588a06e41 chore(release): Bump to version 0.5.3 (resync) (#6436) 2025-08-12 18:18:31 +08:00
Hsiao-nan Cheung
9246250808 Merge branch 'master' into develop 2025-08-12 15:21:48 +08:00
Hsiao-nan Cheung
8c51a50856 fix(autoupdate): Check hash file before use GitHub SHA256 (#6435) 2025-08-12 14:36:30 +08:00
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
HUMORCE
ed6101a2ab docs(CHANGELOG): Update to 0.5.3 (#6432)
* docs(CHANGELOG): Update to 0.5.3

* 6416
2025-08-11 00:34:50 +00:00
Wordless Echo
26a03e2404 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
2025-08-11 00:11:46 +00:00
HUMORCE
f9c4f9e175 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
2025-08-10 23:49:22 +00:00
HUMORCE
3321b969a4 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
2025-08-10 23:04:34 +00:00
HUMORCE
22f1672fcb fix(scoop-uninstall): Fix uninstaller does not gain Global state (#6430)
* global arg

* changelog
2025-08-10 22:48:06 +00:00
14 changed files with 171 additions and 44 deletions

View File

@@ -1,8 +1,14 @@
## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/master...develop)
## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/v0.5.3...develop)
### Features
- **install:** Add support for historical manifests ([#6370](https://github.com/ScoopInstaller/Scoop/issues/6370))
## [v0.5.3](https://github.com/ScoopInstaller/Scoop/compare/v0.5.2...v0.5.3) - 2024-12-31
## [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))
### Bug Fixes
@@ -12,10 +18,13 @@
- **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))
- **scoop-depends-tests:** Mocking `USE_EXTERNAL_7ZIP` as $false to avoding error when it is $true ([#6431](https://github.com/ScoopInstaller/Scoop/issues/6431))
### Code Refactoring
- **download:** Move download-related functions to 'download.ps1' ([#6095](https://github.com/ScoopInstaller/Scoop/issues/6095))
- **Get-Manifest:** Select actual source for manifest ([#6142](https://github.com/ScoopInstaller/Scoop/issues/6142))
### Performance Improvements

View File

@@ -2,6 +2,11 @@
function format_hash([String] $hash) {
$hash = $hash.toLower()
if ($hash -like 'sha256:*') {
$hash = $hash.Substring(7) # Remove prefix 'sha256:'
}
switch ($hash.Length) {
32 { $hash = "md5:$hash" } # md5
40 { $hash = "sha1:$hash" } # sha1
@@ -259,6 +264,10 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u
$hashmode = 'sourceforge'
}
if (!$hashfile_url -and $url -match 'https:\/\/github\.com\/(?<owner>[^\/]+)\/(?<repo>[^\/]+)\/releases\/download\/[^\/]+\/[^\/]+') {
$hashmode = 'github'
}
switch ($hashmode) {
'extract' {
$hash = find_hash_in_textfile $hashfile_url $substitutions $regex
@@ -286,6 +295,10 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u
$hashfile_url = (strip_filename (strip_fragment "https://sourceforge.net/projects/$($matches['project'])/files/$($matches['file'])")).TrimEnd('/')
$hash = find_hash_in_textfile $hashfile_url $substitutions '"$basename":.*?"sha1":\s*"([a-fA-F0-9]{40})"'
}
'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")
}
}
if ($hash) {

View File

@@ -554,6 +554,9 @@ function app_status($app, $global) {
$status.failed = failed $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
$manifest = manifest $app $install_info.bucket $install_info.url
$status.removed = (!$manifest)
if ($manifest.version) {
@@ -581,7 +584,6 @@ function app_status($app, $global) {
if ($deps) {
$status.missing_deps += , $deps
}
return $status
}

View File

@@ -40,30 +40,74 @@ function Get-Manifest($app) {
$app = appname_from_url $url
$manifest = url_manifest $url
} else {
$app, $bucket, $version = parse_app $app
if ($bucket) {
$manifest = manifest $app $bucket
# 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 {
foreach ($tekcub in Get-LocalBucket) {
$manifest = manifest $app $tekcub
if ($manifest) {
$bucket = $tekcub
break
$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 (!$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 = url_manifest $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
}

View File

@@ -7,7 +7,9 @@
param($app)
. "$PSScriptRoot\..\lib\json.ps1" # 'ConvertToPrettyJson'
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest'
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-UserAgent'
if (!$app) { error '<app> missing'; my_usage; exit 1 }

View File

@@ -3,7 +3,9 @@
. "$PSScriptRoot\..\lib\getopt.ps1"
. "$PSScriptRoot\..\lib\depends.ps1" # 'Get-Dependency'
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest' (indirectly)
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-UserAgent'
$opt, $apps, $err = getopt $args 'a:' 'arch='
$app = $apps[0]
@@ -20,7 +22,14 @@ try {
$deps = @()
Get-Dependency $app $architecture | ForEach-Object {
$dep = [ordered]@{}
$dep.Source, $dep.Name = $_ -split '/'
$app, $null, $bucket, $url = Get-Manifest $_
if (!$url) {
$bucket, $app = $_ -split '/'
}
$dep.Source = if ($url) { $url } else { $bucket }
$dep.Name = $app
$deps += [PSCustomObject]$dep
}
$deps

View File

@@ -22,6 +22,7 @@
. "$PSScriptRoot\..\lib\getopt.ps1"
. "$PSScriptRoot\..\lib\json.ps1" # 'autoupdate.ps1' (indirectly)
. "$PSScriptRoot\..\lib\autoupdate.ps1" # 'generate_user_manifest' (indirectly)
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'generate_user_manifest' 'Get-Manifest'
. "$PSScriptRoot\..\lib\download.ps1"
if (get_config USE_SQLITE_CACHE) {

View File

@@ -2,7 +2,9 @@
# Summary: Opens the app homepage
param($app)
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest'
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-UserAgent'
if ($app) {
$null, $manifest, $bucket, $null = Get-Manifest $app

View File

@@ -5,10 +5,11 @@
. "$PSScriptRoot\..\lib\getopt.ps1"
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest'
. "$PSScriptRoot\..\lib\versions.ps1" # 'Get-InstalledVersion'
. "$PSScriptRoot\..\lib\versions.ps1" # 'Get-InstalledVersion', 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-RemoteFileSize'
$opt, $app, $err = getopt $args 'v' 'verbose'
$original_app = $app
if ($err) { error "scoop info: $err"; exit 1 }
$verbose = $opt.v -or $opt.verbose
@@ -23,7 +24,7 @@ if (!$manifest) {
$global = installed $app $true
$status = app_status $app $global
$install = install_info $app $status.version $global
$status.installed = $bucket -and $install.bucket -eq $bucket
$status.installed = ($bucket -and $install.bucket -eq $bucket) -or (installed $app)
$version_output = $manifest.version
$manifest_file = if ($bucket) {
manifest_path $app $bucket
@@ -31,12 +32,30 @@ $manifest_file = if ($bucket) {
$url
}
# Standalone and Source detection
if ((Test-Path $original_app) -or ($original_app -match '^(ht|f)tps?://|\\\\')) {
$standalone = $true
if (Test-Path $original_app) {
$original_app = (Get-AbsolutePath "$original_app")
}
if ($install.url) {
if (Test-Path $install.url) {
$install_url = (Get-AbsolutePath $install.url)
} else {
$install_url = $install.url
}
}
if ($original_app -eq $install_url) {
$same_source = $true
}
}
if ($verbose) {
$dir = currentdir $app $global
$original_dir = versiondir $app $manifest.version $global
$persist_dir = persistdir $app $global
} else {
$dir, $original_dir, $persist_dir = "<root>", "<root>", "<root>"
$dir, $original_dir, $persist_dir = '<root>', '<root>', '<root>'
}
if ($status.installed) {
@@ -44,21 +63,39 @@ if ($status.installed) {
if ($install.url) {
$manifest_file = $install.url
}
if ($status.version -eq $manifest.version) {
if ($status.deprecated) {
$manifest_file = $status.deprecated
} elseif ($standalone -and !$same_source) {
$version_output = $manifest.version
} elseif ($status.version -eq $manifest.version) {
$version_output = $status.version
} else {
$version_output = "$($status.version) (Update to $($manifest.version) available)"
}
}
$item = [ordered]@{ Name = $app }
if ($status.deprecated) {
$item.Name += ' (DEPRECATED)'
}
if ($manifest.description) {
$item.Description = $manifest.description
}
$item.Version = $version_output
if ($bucket) {
$item.Bucket = $bucket
$item.Source = if ($standalone) {
$original_app
} else {
if ($install.bucket) {
$install.bucket
} elseif ($install.url) {
$install.url
} else {
$bucket
}
}
if ($manifest.homepage) {
$item.Website = $manifest.homepage.TrimEnd('/')
}
@@ -70,7 +107,7 @@ if ($manifest.license) {
$manifest.license
} elseif ($manifest.license -match '[|,]') {
if ($verbose) {
"$($manifest.license) ($(($manifest.license -Split "\||," | ForEach-Object { "https://spdx.org/licenses/$_.html" }) -join ', '))"
"$($manifest.license) ($(($manifest.license -Split '\||,' | ForEach-Object { "https://spdx.org/licenses/$_.html" }) -join ', '))"
} else {
$manifest.license
}
@@ -101,11 +138,13 @@ if ($verbose) { $item.Manifest = $manifest_file }
if ($status.installed) {
# Show installed versions
$installed_output = @()
Get-InstalledVersion -AppName $app -Global:$global | ForEach-Object {
$installed_output += if ($verbose) { versiondir $app $_ $global } else { "$_$(if ($global) { " *global*" })" }
if (!$standalone -or $same_source) {
$installed_output = @()
Get-InstalledVersion -AppName $app -Global:$global | ForEach-Object {
$installed_output += if ($verbose) { versiondir $app $_ $global } else { "$_$(if ($global) { ' *global*' })" }
}
$item.Installed = $installed_output -join "`n"
}
$item.Installed = $installed_output -join "`n"
if ($verbose) {
# Show size of installation
@@ -162,7 +201,7 @@ if ($status.installed) {
foreach ($url in @(url $manifest (Get-DefaultArchitecture))) {
try {
if (Test-Path (cache_path $app $manifest.version $url)) {
$cached = " (latest version is cached)"
$cached = ' (latest version is cached)'
} else {
$cached = $null
}
@@ -197,7 +236,7 @@ if ($binaries) {
$binary_output += $_
}
}
$item.Binaries = $binary_output -join " | "
$item.Binaries = $binary_output -join ' | '
}
$shortcuts = @(arch_specific 'shortcuts' $manifest $install.architecture)
if ($shortcuts) {
@@ -205,7 +244,7 @@ if ($shortcuts) {
$shortcuts | ForEach-Object {
$shortcut_output += $_[1]
}
$item.Shortcuts = $shortcut_output -join " | "
$item.Shortcuts = $shortcut_output -join ' | '
}
$env_set = arch_specific 'env_set' $manifest $install.architecture
if ($env_set) {

View File

@@ -5,8 +5,9 @@ param($query)
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'parse_json' 'Select-CurrentVersion' (indirectly)
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-UserAgent'
$def_arch = Get-DefaultArchitecture
$defaultArchitecture = Get-DefaultArchitecture
if (-not (Get-FormatData ScoopApps)) {
Update-FormatData "$PSScriptRoot\..\supporting\formats\ScoopTypes.Format.ps1xml"
}
@@ -47,10 +48,11 @@ $apps | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
$item.Updated = $updated
$info = @()
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' }
if ($install_info.architecture -and $def_arch -ne $install_info.architecture) {
if ($install_info.architecture -and $defaultArchitecture -ne $install_info.architecture) {
$info += $install_info.architecture
}
$item.Info = $info -join ', '

View File

@@ -6,6 +6,7 @@
. "$PSScriptRoot\..\lib\manifest.ps1" # 'manifest' 'parse_json' "install_info"
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\download.ps1" # 'Get-UserAgent'
# check if scoop needs updating
$currentdir = versiondir 'scoop' 'current'
@@ -58,7 +59,7 @@ $true, $false | ForEach-Object { # local and global apps
Get-ChildItem $dir | Where-Object name -NE 'scoop' | ForEach-Object {
$app = $_.name
$status = app_status $app $global
if (!$status.outdated -and !$status.failed -and !$status.removed -and !$status.missing_deps) { return }
if (!$status.outdated -and !$status.failed -and !$status.deprecated -and !$status.removed -and !$status.missing_deps) { return }
$item = [ordered]@{}
$item.Name = $app
@@ -66,9 +67,10 @@ $true, $false | ForEach-Object { # local and global apps
$item.'Latest Version' = if ($status.outdated) { $status.latest_version } else { "" }
$item.'Missing Dependencies' = $status.missing_deps -Split ' ' -Join ' | '
$info = @()
if ($status.failed) { $info += 'Install failed' }
if ($status.hold) { $info += 'Held package' }
if ($status.removed) { $info += 'Manifest removed' }
if ($status.failed) { $info += 'Install failed' }
if ($status.hold) { $info += 'Held package' }
if ($status.deprecated) { $info += 'Deprecated' }
if ($status.removed) { $info += 'Manifest removed' }
$item.Info = $info -join ', '
$list += [PSCustomObject]$item
}

View File

@@ -74,7 +74,7 @@ if (!$apps) { exit 0 }
continue
}
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
rm_startmenu_shortcuts $manifest $global $architecture

View File

@@ -29,6 +29,7 @@
# -p, --passthru Return reports as objects
. "$PSScriptRoot\..\lib\getopt.ps1"
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Get-Manifest'
. "$PSScriptRoot\..\lib\json.ps1" # 'json_path'
. "$PSScriptRoot\..\lib\download.ps1" # 'hash_for_url'

View File

@@ -65,6 +65,7 @@ Describe 'Package Dependencies' -Tag 'Scoop' {
BeforeAll {
Mock Test-HelperInstalled { $false }
Mock get_config { $true } -ParameterFilter { $name -eq 'USE_LESSMSI' }
Mock get_config { $false } -ParameterFilter { $name -eq 'USE_EXTERNAL_7ZIP' }
Mock Get-Manifest { 'lessmsi', @{}, $null, $null } -ParameterFilter { $app -eq 'lessmsi' }
Mock Get-Manifest { '7zip', @{ url = 'test.msi' }, $null, $null } -ParameterFilter { $app -eq '7zip' }
Mock Get-Manifest { 'innounp', @{}, $null, $null } -ParameterFilter { $app -eq 'innounp' }