6 Commits

2 changed files with 247 additions and 237 deletions

View File

@@ -202,7 +202,7 @@ function Get-RelativePathCompat($from, $to) {
return $relativePath -replace '/', '\'
}
function Get-HistoricalManifestFromDB($app, $bucket, $requestedVersion) {
function Find-HistoricalManifestInCache($app, $bucket, $requestedVersion) {
if (!(get_config USE_SQLITE_CACHE)) {
return $null
}
@@ -217,26 +217,25 @@ function Get-HistoricalManifestFromDB($app, $bucket, $requestedVersion) {
. "$PSScriptRoot\database.ps1"
}
# First try exact match
$dbResult = Get-ScoopDBItem -Name $app -Bucket $bucket -Version $requestedVersion
if ($dbResult.Rows.Count -gt 0) {
$row = $dbResult.Rows[0]
ensure (usermanifestsdir) | Out-Null
$tempManifestPath = "$(usermanifestsdir)\$app.json"
$row.manifest | Out-UTF8File -FilePath $tempManifestPath
# Parse the manifest to get its actual version
$manifest = $row.manifest | ConvertFrom-Json
$manifestVersion = if ($manifest.version) { $manifest.version } else { $requestedVersion }
return @{ path = $tempManifestPath; version = $manifestVersion; source = "sqlite_exact_match" }
}
# Strictly follow DB contract: must be DataTable with at least one row
if (-not ($dbResult -is [System.Data.DataTable])) { return $null }
if ($dbResult.Rows.Count -eq 0) { return $null }
# No exact match found, return null (no compatibility matching)
$manifestText = $dbResult.Rows[0]['manifest']
if ([string]::IsNullOrWhiteSpace($manifestText)) { return $null }
$manifestObj = $null
try { $manifestObj = $manifestText | ConvertFrom-Json -ErrorAction Stop } catch {}
$manifestVersion = if ($manifestObj -and $manifestObj.version) { $manifestObj.version } else { $requestedVersion }
return @{ ManifestText = $manifestText; version = $manifestVersion; source = "sqlite_exact_match" }
return $null
}
function Get-HistoricalManifestFromGitHistory($app, $bucket, $requestedVersion) {
function Find-HistoricalManifestInGit($app, $bucket, $requestedVersion) {
# Only proceed if git history is enabled
if (!(get_config USE_GIT_HISTORY $true)) {
return $null
@@ -263,153 +262,81 @@ function Get-HistoricalManifestFromGitHistory($app, $bucket, $requestedVersion)
$relativeManifestPath = $relativeManifestPath -replace '\\', '/'
try {
$gitLogOutput = Invoke-Git -Path $bucketDir -ArgumentList @('log', '--follow', '--format=format:%H%n%s', '--', $relativeManifestPath) # Removed 2>$null to see git errors
# Prefer precise regex match on version line, fallback to -S literal
$pattern = '"version"\s*:\s*"' + [regex]::Escape($requestedVersion) + '"'
$commits = @()
$outG = Invoke-Git -Path $bucketDir -ArgumentList @('log','--follow','-n','1','--format=%H','-G',$pattern,'--',$relativeManifestPath)
if ($outG) { $commits = @($outG | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) }
if (!$gitLogOutput) {
warn "No git history found for '$app' in bucket '$bucket' (file: $relativeManifestPath)."
return $null
if ($commits.Count -eq 0) {
$searchLiteral = '"version": "' + $requestedVersion + '"'
$outS = Invoke-Git -Path $bucketDir -ArgumentList @('log','--follow','-n','1','--format=%H','-S',$searchLiteral,'--',$relativeManifestPath)
if ($outS) { $commits = @($outS | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) }
}
$foundVersions = [System.Collections.Generic.List[hashtable]]::new()
$processedHashes = [System.Collections.Generic.HashSet[string]]::new()
if ($commits.Count -eq 0) { return $null }
$versionsFoundForPreviousMinor = @{}
$limitPreviousMinorCount = 5
$requestedVersionParts = $requestedVersion -split '\.'
$previousMinorVersionString = ''
if ($requestedVersionParts.Count -ge 2 -and $requestedVersionParts[1] -match '^\d+$') {
$currentMinor = [int]$requestedVersionParts[1]
if ($currentMinor -gt 0) {
$previousMinorVersionString = "$($requestedVersionParts[0]).$($currentMinor - 1)"
$h = $commits[0]
# First try parent snapshot (latest state before change), then the change itself
foreach ($spec in @("$h^","$h")) {
$content = Invoke-Git -Path $bucketDir -ArgumentList @('show', "$spec`:$relativeManifestPath")
if (-not $content -or ($LASTEXITCODE -ne 0)) { continue }
if ($content -is [Array]) { $content = $content -join "`n" }
try {
$obj = $content | ConvertFrom-Json -ErrorAction Stop
} catch { continue }
if ($obj -and $obj.version -eq $requestedVersion) {
return @{ ManifestText = $content; version = $requestedVersion; source = "git_manifest:$spec" }
}
}
$maxCommitsToProcess = 200 # Hard cap to prevent excessive runtimes
# Fallback: iterate recent commits that touched the version string and validate
$outAll = Invoke-Git -Path $bucketDir -ArgumentList @('log','--follow','--format=%H','-G',$pattern,'--',$relativeManifestPath)
$allCommits = @()
if ($outAll) { $allCommits = @($outAll | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) }
for ($i = 0; $i -lt $gitLogOutput.Count; $i += 2) {
if ($processedHashes.Count -ge $maxCommitsToProcess) {
info "Processed $maxCommitsToProcess commits for $app. Stopping search to prevent excessive runtime."
break
}
$hash = $gitLogOutput[$i]
$subject = if (($i + 1) -lt $gitLogOutput.Count) { $gitLogOutput[$i + 1] } else { '' }
if ([string]::IsNullOrWhiteSpace($hash) -or !$processedHashes.Add($hash)) {
continue
}
$versionFromMessage = $null
if ($subject -match "(?:'$app': Update to version |Update to |Release |Tag |v)($([char]34)?([0-9]+\.[0-9]+(?:\.[0-9]+){0,2}(?:[a-zA-Z0-9._+-]*))\1?)") {
$versionFromMessage = $Matches[2]
}
if ($versionFromMessage -eq $requestedVersion) {
info "Potential exact match '$versionFromMessage' found in commit message for $app (hash $hash). Verifying manifest..."
$manifestContent = Invoke-Git -Path $bucketDir -ArgumentList @('show', "$hash`:$relativeManifestPath")
if ($manifestContent -and ($LASTEXITCODE -eq 0)) {
if ($manifestContent -is [Array]) {
$manifestContent = $manifestContent -join "`n"
}
$manifestObj = $null; try { $manifestObj = $manifestContent | ConvertFrom-Json -ErrorAction Stop } catch {}
if ($manifestObj -and $manifestObj.version -eq $requestedVersion) {
info "Exact version '$requestedVersion' for '$app' confirmed from manifest in commit $hash."
ensure (usermanifestsdir) | Out-Null
$tempManifestPath = "$(usermanifestsdir)\$app.json"
$manifestContent | Out-UTF8File -FilePath $tempManifestPath
return @{ path = $tempManifestPath; version = $requestedVersion; source = "git_commit_message:$hash" }
}
}
}
$manifestContent = Invoke-Git -Path $bucketDir -ArgumentList @('show', "$hash`:$relativeManifestPath")
if ($manifestContent -and ($LASTEXITCODE -eq 0)) {
if ($manifestContent -is [Array]) {
$manifestContent = $manifestContent -join "`n"
}
$manifestObj = $null;
try {
$manifestObj = $manifestContent | ConvertFrom-Json -ErrorAction Stop
} catch {
warn "Failed to parse manifest content from commit $hash for app $app. Skipping this commit."
# Consider logging $manifestContent if debugging is needed
continue # Skip to the next commit
}
if ($manifestObj -and $manifestObj.version) {
if ($manifestObj.version -eq $requestedVersion) {
info "Exact version '$requestedVersion' for '$app' found in manifest (commit $hash)."
ensure (usermanifestsdir) | Out-Null
$tempManifestPath = "$(usermanifestsdir)\$app.json"
if ($PSVersionTable.PSVersion.Major -ge 6) {
$utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($false)
Set-Content -Path $tempManifestPath -Value $manifestContent -Encoding $utf8NoBomEncoding -NoNewline:$false
} else {
# PowerShell 5 compatibility
$manifestContent | Out-UTF8File -FilePath $tempManifestPath
}
return @{ path = $tempManifestPath; version = $requestedVersion; source = "git_manifest:$hash" }
}
$foundVersions.Add(@{
version = $manifestObj.version
hash = $hash
manifest = $manifestContent
})
if ($previousMinorVersionString -ne '' -and $manifestObj.version.StartsWith($previousMinorVersionString)) {
if (!$versionsFoundForPreviousMinor.ContainsKey($previousMinorVersionString)) {
$versionsFoundForPreviousMinor[$previousMinorVersionString] = 0
}
$versionsFoundForPreviousMinor[$previousMinorVersionString]++
if ($versionsFoundForPreviousMinor[$previousMinorVersionString] -ge $limitPreviousMinorCount) {
info "Reached limit of $limitPreviousMinorCount versions for previous minor '$previousMinorVersionString' while checking $app. Stopping search."
break
}
}
if ($foundVersions.Count % 20 -eq 0 -and $foundVersions.Count -gt 0) {
info "Found $($foundVersions.Count) historical versions for $app so far..."
}
}
} elseif ($LASTEXITCODE -ne 0) {
warn "git show $hash`:$relativeManifestPath failed for $app."
foreach ($c in $allCommits) {
$content = Invoke-Git -Path $bucketDir -ArgumentList @('show', "$c`:$relativeManifestPath")
if (-not $content -or ($LASTEXITCODE -ne 0)) { continue }
if ($content -is [Array]) { $content = $content -join "`n" }
try { $obj = $content | ConvertFrom-Json -ErrorAction Stop } catch { continue }
if ($obj -and $obj.version -eq $requestedVersion) {
return @{ ManifestText = $content; version = $requestedVersion; source = "git_manifest:$c" }
}
}
if ($foundVersions.Count -eq 0) {
warn "No valid historical versions found for '$app' in bucket '$bucket'."
return $null
}
# No exact match found - display all available versions to help user choose
$allAvailableVersions = ($foundVersions | Sort-Object {
try { [version]($_.version -replace '[^\d\.].*$', '') } catch { $_.version }
} -Descending).version
Write-Host ""
Write-Host "No exact match found for version '$requestedVersion' for app '$app'."
Write-Host "Available versions in git history (newest to oldest):"
Write-Host ""
# Group versions for better display
$displayCount = [Math]::Min(50, $allAvailableVersions.Count) # Show up to 50 versions
for ($i = 0; $i -lt $displayCount; $i++) {
Write-Host " $($allAvailableVersions[$i])"
}
if ($allAvailableVersions.Count -gt $displayCount) {
Write-Host " ... and $($allAvailableVersions.Count - $displayCount) more versions"
}
Write-Host ""
Write-Host "To install a specific version, use: scoop install $app@<version>"
Write-Host ""
return $null
} catch { return $null }
}
} catch {
warn "Error searching git history for '$app': $($_.Exception.Message)"
return $null
function Find-HistoricalManifest($app, $bucket, $version) {
# Orchestrates historical manifest lookup using available providers (DB → Git)
$result = $null
if (get_config USE_SQLITE_CACHE) {
$result = Find-HistoricalManifestInCache $app $bucket $version
if ($result) {
if ($result.ManifestText) {
$path = Write-ManifestToUserCache -App $app -ManifestText $result.ManifestText
return @{ path = $path; version = $result.version; source = $result.source }
}
return $result
}
}
if (get_config USE_GIT_HISTORY $true) {
$result = Find-HistoricalManifestInGit $app $bucket $version
if ($result) {
if ($result.ManifestText) {
$path = Write-ManifestToUserCache -App $app -ManifestText $result.ManifestText
return @{ path = $path; version = $result.version; source = $result.source }
}
return $result
}
}
return $null
}
@@ -420,106 +347,25 @@ function generate_user_manifest($app, $bucket, $version) {
return manifest_path $app $bucket
}
warn "Given version ($version) does not match manifest ($($manifest.version))"
# Try historical providers via orchestrator
$historicalResult = Find-HistoricalManifest $app $bucket $version
if ($historicalResult) { return $historicalResult.path }
$historicalResult = $null
# Try SQLite cache first if enabled
if (get_config USE_SQLITE_CACHE) {
info "Searching for version '$version' in cache..."
$historicalResult = Get-HistoricalManifestFromDB $app $bucket $version
if ($historicalResult) {
info "Found version '$($historicalResult.version)' for '$app' in cache."
return $historicalResult.path
}
# No historical manifest; try autoupdate if available
if (!($manifest.autoupdate)) {
abort "Could not find manifest for '$app@$version' and no autoupdate is available"
}
# Try git history if cache didn't find it
if (!$historicalResult) {
info "Searching for version '$version' in git history..."
$historicalResult = Get-HistoricalManifestFromGitHistory $app $bucket $version
if ($historicalResult) {
return $historicalResult.path
}
}
# If no historical version found, provide helpful guidance
if (!$historicalResult) {
# Try to provide additional context about what versions are available
$currentVersion = $manifest.version
if ($currentVersion) {
info "Current version available: $currentVersion"
info "To install the current version, use: scoop install $app"
}
# Check if we have autoupdate capability for fallback
if ($manifest.autoupdate) {
info "This app supports autoupdate - attempting to generate manifest for version $version"
} else {
warn "'$app' does not have autoupdate capability."
Write-Host "Available options:"
Write-Host " 1. Install current version: scoop install $app"
Write-Host " 2. Check if the requested version exists in other buckets"
Write-Host " 3. Contact the bucket maintainer to add historical version support"
Write-Host ""
abort "Could not find manifest for '$app@$version' and no autoupdate available"
}
}
# Fallback to autoupdate generation
warn "No historical version found. Attempting to generate manifest for '$app' ($version)"
ensure (usermanifestsdir) | Out-Null
$manifest_path = "$(usermanifestsdir)\$app.json"
# Check SQLite cache for exact cached manifest (this is different from historical search)
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 and no historical version found`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"
Write-Host -ForegroundColor Yellow "Autoupdate failed for version $version"
# Provide helpful guidance when autoupdate fails
Write-Host "Possible reasons:"
Write-Host " - Version $version may not exist or be available for download"
Write-Host " - Download URLs may have changed or be inaccessible"
Write-Host " - The version format may be incompatible with autoupdate patterns"
Write-Host ""
Write-Host "Suggestions:"
Write-Host " 1. Install current version: scoop install $app"
Write-Host " 2. Try a different version that was shown in the available list"
Write-Host " 3. Check the app's official releases or download page"
Write-Host ""
# If autoupdate fails and we haven't tried git history yet, try it as final fallback
if (!$historicalResult -and !(get_config USE_SQLITE_CACHE)) {
warn 'Autoupdate failed. Trying git history as final fallback...'
$fallbackResult = Get-HistoricalManifestFromGitHistory $app $bucket $version
if ($fallbackResult) {
warn "Using historical manifest as fallback for '$app' version '$($fallbackResult.version)'"
return $fallbackResult.path
}
}
# Final failure - provide comprehensive guidance
Write-Host -ForegroundColor Red "All attempts to find or generate manifest for '$app@$version' failed."
warn "Autoupdate failed for '$app@$version'"
abort "Installation of '$app@$version' is not possible"
}
return $null
}
function url($manifest, $arch) { arch_specific 'url' $manifest $arch }
@@ -528,3 +374,16 @@ function uninstaller($manifest, $arch) { arch_specific 'uninstaller' $manifest $
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 }
# Helper: write manifest text to user manifests cache directory and return path
function Write-ManifestToUserCache {
param(
[Parameter(Mandatory=$true, Position=0)][string]$App,
[Parameter(Mandatory=$true, Position=1)][string]$ManifestText
)
ensure (usermanifestsdir) | Out-Null
$tempManifestPath = "$(usermanifestsdir)\$App.json"
$ManifestText | Out-UTF8File -FilePath $tempManifestPath
return $tempManifestPath
}

View File

@@ -1,15 +1,25 @@
BeforeAll {
. "$PSScriptRoot\..\lib\json.ps1"
. "$PSScriptRoot\..\lib\core.ps1"
. "$PSScriptRoot\..\lib\manifest.ps1"
. "$PSScriptRoot\..\lib\buckets.ps1"
. "$PSScriptRoot\..\lib\database.ps1"
. "$PSScriptRoot\..\lib\autoupdate.ps1"
}
Describe 'JSON parse and beautify' -Tag 'Scoop' {
Context 'Parse JSON' {
It 'success with valid json' {
{ parse_json "$PSScriptRoot\fixtures\manifest\wget.json" } | Should -Not -Throw
$parsed = parse_json "$PSScriptRoot\fixtures\manifest\wget.json"
$parsed | Should -Not -Be $null
}
It 'fails with invalid json' {
{ parse_json "$PSScriptRoot\fixtures\manifest\broken_wget.json" } | Should -Throw
It 'returns null and warns with invalid json' {
Mock warn {}
{ parse_json "$PSScriptRoot\fixtures\manifest\broken_wget.json" } | Should -Not -Throw
$parsed = parse_json "$PSScriptRoot\fixtures\manifest\broken_wget.json"
$parsed | Should -Be $null
Should -Invoke -CommandName warn -Times 1
}
}
Context 'Beautify JSON' {
@@ -84,3 +94,144 @@ Describe 'Manifest Validator' -Tag 'Validator' {
$validator.Errors | Select-Object -Last 1 | Should -Match 'Required properties are missing from object: version\.'
}
}
Describe 'Get-RelativePathCompat' -Tag 'Scoop' {
It 'returns relative path for child path' {
$from = 'C:\root\bucket'
$to = 'C:\root\bucket\foo\bar.json'
Get-RelativePathCompat $from $to | Should -Be 'foo\bar.json'
}
It 'returns original when different drive/scheme' {
$from = 'C:\root\bucket'
$to = 'D:\other\file.json'
Get-RelativePathCompat $from $to | Should -Be $to
}
}
Describe 'Find-HistoricalManifestInCache' -Tag 'Scoop' {
It 'returns $null when sqlite cache disabled' {
Mock get_config -ParameterFilter { $name -eq 'use_sqlite_cache' } { $false }
$result = Find-HistoricalManifestInCache 'foo' 'main' '1.0.0'
$result | Should -Be $null
}
It 'returns manifest text and version when cache has exact match' {
$tempUM = Join-Path $env:TEMP 'ScoopTestsUM'
Mock get_config -ParameterFilter { $name -in @('use_sqlite_cache','use_git_history') } { $true }
Mock Get-ScoopDBItem {
$dt = New-Object System.Data.DataTable
[void]$dt.Columns.Add('manifest')
$row = $dt.NewRow()
$row['manifest'] = '{"version":"1.2.3"}'
[void]$dt.Rows.Add($row)
Write-Output $dt -NoEnumerate
}
Mock ensure {}
$result = Find-HistoricalManifestInCache 'foo' 'main' '1.2.3'
$result | Should -Not -BeNullOrEmpty
$result.version | Should -Be '1.2.3'
$result.ManifestText | Should -Match '"version":"1.2.3"'
}
}
Describe 'Find-HistoricalManifestInGit' -Tag 'Scoop' {
It 'returns $null when git history search disabled' {
Mock get_config -ParameterFilter { $name -eq 'use_git_history' } { $false }
$result = Find-HistoricalManifestInGit 'foo' 'main' '1.0.0'
$result | Should -Be $null
}
It 'returns manifest text on version match' {
$bucketRoot = 'C:\b\root'
$innerBucket = 'C:\b\root\bucket'
$umdir = Join-Path $env:TEMP 'ScoopTestsUM'
Mock get_config -ParameterFilter { $name -eq 'use_git_history' } { $true }
Mock Find-BucketDirectory -ParameterFilter { $Root } { $bucketRoot }
Mock Find-BucketDirectory -ParameterFilter { -not $Root } { $innerBucket }
Mock Test-Path -ParameterFilter { $Path -eq (Join-Path $bucketRoot '.git') } { $true }
Mock Test-Path -ParameterFilter { $Path -eq $innerBucket -and $PathType -eq 'Container' } { $true }
# Behavior-oriented mocks: using HEAD should yield a wrong version
Mock Invoke-Git -ParameterFilter { $ArgumentList[0] -eq 'show' -and $ArgumentList[1] -like 'HEAD*' } { $global:LASTEXITCODE = 0; return '{"version":"2.0.0"}' }
Mock Invoke-Git -ParameterFilter { $ArgumentList[0] -eq 'show' } { $global:LASTEXITCODE = 0; return '{"version":"1.0.0"}' }
Mock Invoke-Git -ParameterFilter { $ArgumentList[0] -eq 'log' } { @('abcdef0123456789') }
$result = Find-HistoricalManifestInGit 'foo' 'main' '1.0.0'
$result | Should -Not -BeNullOrEmpty
$result.version | Should -Be '1.0.0'
$result.ManifestText | Should -Match '"version":"1.0.0"'
}
}
Describe 'generate_user_manifest (history-aware)' -Tag 'Scoop' {
It 'returns manifest_path when versions match' {
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='1.0.0' }, 'main', $null }
Mock manifest_path { 'C:\path\foo.json' }
$p = generate_user_manifest 'foo' 'main' '1.0.0'
$p | Should -Be 'C:\path\foo.json'
}
It 'prefers history orchestrator hit (cache) when enabled' {
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='2.0.0' }, 'main', $null }
Mock get_config -ParameterFilter { $name -in @('use_sqlite_cache','use_git_history') } { $true }
Mock Find-HistoricalManifest { @{ path = 'C:\cache\foo.json'; version = '1.0.0'; source='sqlite_exact_match' } }
Mock info {}
Mock warn {}
$p = generate_user_manifest 'foo' 'main' '1.0.0'
$p | Should -Be 'C:\cache\foo.json'
Should -Invoke -CommandName Find-HistoricalManifest -Times 1
}
It 'falls back to git history when cache misses' {
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='2.0.0' }, 'main', $null }
Mock get_config -ParameterFilter { $name -in @('use_sqlite_cache','use_git_history') } { $true }
Mock Find-HistoricalManifest { @{ path = 'C:\git\foo.json'; version = '1.0.0'; source='git_manifest:hash' } }
Mock info {}
Mock warn {}
$p = generate_user_manifest 'foo' 'main' '1.0.0'
$p | Should -Be 'C:\git\foo.json'
Should -Invoke -CommandName Find-HistoricalManifest -Times 1
}
It 'uses autoupdate when no history found and autoupdate exists' {
$umdir = Join-Path $env:TEMP 'ScoopTestsUM'
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='2.0.0'; autoupdate=@{} }, 'main', $null }
Mock get_config -ParameterFilter { $name -eq 'use_sqlite_cache' } { $false }
Mock Find-HistoricalManifest { $null }
Mock ensure {}
Mock usermanifestsdir { $umdir }
Mock Invoke-AutoUpdate {}
$p = generate_user_manifest 'foo' 'main' '1.0.0'
$p | Should -Be (Join-Path $umdir 'foo.json')
}
It 'on autoupdate failure aborts with concise message' {
$umdir = Join-Path $env:TEMP 'ScoopTestsUM'
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='2.0.0'; autoupdate=@{} }, 'main', $null }
Mock get_config -ParameterFilter { $name -eq 'use_sqlite_cache' } { $false }
Mock Find-HistoricalManifest { $null }
Mock ensure {}
Mock usermanifestsdir { $umdir }
Mock Invoke-AutoUpdate { throw 'fail' }
Mock warn {}
Mock info {}
Mock Write-Host {}
Mock abort { throw 'aborted' }
{ generate_user_manifest 'foo' 'main' '1.0.0' } | Should -Throw
}
It 'aborts when no history and no autoupdate' {
Mock Get-Manifest -ParameterFilter { $app -eq 'main/foo' } { 'foo', [pscustomobject]@{ version='2.0.0' }, 'main', $null }
Mock get_config -ParameterFilter { $name -eq 'use_sqlite_cache' } { $false }
Mock Find-HistoricalManifest { $null }
Mock warn {}
Mock info {}
Mock abort { throw 'aborted' }
{ generate_user_manifest 'foo' 'main' '1.0.0' } | Should -Throw
}
}