diff --git a/lib/manifest.ps1 b/lib/manifest.ps1 index 54438ed19e..84c25074e8 100644 --- a/lib/manifest.ps1 +++ b/lib/manifest.ps1 @@ -127,7 +127,7 @@ function New-VersionedManifest { throw [ScoopException] "Invalid manifest '$Path'" } - $name = "$($Path.BaseName)-$(Get-Random)-$(Get-Random)$($Path.Extension)" + $name = "$($Path.BaseName)-$_localAdditionalSeed$(Get-Random)-$(Get-Random)$($Path.Extension)" $outPath = Confirm-DirectoryExistence -LiteralPath $SHOVEL_GENERAL_MANIFESTS_DIRECTORY | Join-Path -ChildPath $name try { @@ -256,6 +256,88 @@ function Get-RemoteManifest { } } } + +function Get-ManifestFromLookup { + <# + .SYNOPSIS + Lookup for manifest in all local buckets and return required information. + .PARAMETER Query + Specifies the lookup query. + #> + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param([Parameter(Mandatory, ValueFromPipeline)] [String] $Query) + + process { + # Get all requested information + $requestedBucket, $requestedName = $Query -split '/' + if ($null -eq $requestedName) { + $requestedName = $requestedBucket + $requestedBucket = $null + } + $requestedName, $requestedVersion = $requestedName -split '@' + + # Local manifest with specific name in all buckets + $found = @() + $buckets = Get-LocalBucket + + if ($requestedBucket -and ($requestedBucket -notin $buckets)) { throw [ScoopException] "'$requestedBucket' cannot be found" } + + foreach ($b in $buckets) { + $really = manifest_path $requestedName $b + if ($really) { + $found += @{ + 'Bucket' = $b + 'Path' = $really + } + } + } + + # Pick the first one (as vanilla implementation) + # TODO: Let user pick which bucket if there are more + $valid = $found[0] + if ($requestedBucket) { $valid = $found | Where-Object -Property 'Bucket' -EQ -Value $requestedBucket } + + if (!$valid) { throw [ScoopException] "No manifest found for '$Query'" } + + $manifestBucket = $valid.Bucket + $manifestPath = $valid.Path + + # Select versioned manifest or generate it + if ($requestedVersion) { + try { + $path = manifest_path -app $requestedName -bucket $requestedBucket -version $requestedVersion + if ($null -eq $path) { throw 'trigger' } + $manifestPath = $path + } catch { + $mess = if ($requestedBucket) { " in '$requestedBucket'" } else { '' } + Write-UserMessage -Message "There is no archived version of manifest '$requestedName'$mes. Trying to generate the manifest" -Warning + + $generated = $null + try { + $generated = New-VersionedManifest -Path $manifestPath -Version $requestedVersion + } catch { + throw [ScoopException] $_.Exception.Message + } + + # This should not happen. + if (!(Test-Path -LiteralPath $generated)) { throw [ScoopException] 'Generated manifest cannot be found' } + + $manifestPath = $generated + } + } + + $name = $requestedName + $manifest = ConvertFrom-Manifest -LiteralPath $manifestPath + + return @{ + 'Name' = $name + 'Bucket' = $manifestBucket + 'Manifest' = $manifest + 'Path' = (Get-Item -LiteralPath $manifestPath) + } + } +} #endregion Resolve Helpers function Resolve-ManifestInformation { @@ -297,6 +379,13 @@ function Resolve-ManifestInformation { $manifest = $res.Manifest $localPath = $res.Path $url = $ApplicationQuery + } elseif ($ApplicationQuery -match $_lookupRegex) { + $res = Get-ManifestFromLookup -Query $ApplicationQuery + $applicationName = $res.Name + $applicationVersion = $res.Manifest.version + $manifest = $res.Manifest + $localPath = $res.Path + $bucket = $res.Bucket } else { throw 'Not supported way how to provide manifest' } diff --git a/test/Shovel-Manifest.Tests.ps1 b/test/Shovel-Manifest.Tests.ps1 index bcbaf25650..56bfee004e 100644 --- a/test/Shovel-Manifest.Tests.ps1 +++ b/test/Shovel-Manifest.Tests.ps1 @@ -175,6 +175,122 @@ Describe 'Manifests operations' -Tag 'Scoop' { } } + Describe 'Get-ManifestFromLookup' { + It 'Simple lookup' { + $result = Resolve-ManifestInformation 'pwsh' + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '7.1.3' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result.Bucket | Should -Be 'ash258.ash258' + $result = $null + + $result = Resolve-ManifestInformation 'cosi' + $result.ApplicationName | Should -Be 'cosi' + $result.Version | Should -Be '7.1.3' + $result.ManifestObject.checkver | Should -Be 'github' + $result = $null + } + + It 'Simple versioned lookup' { + $result = Resolve-ManifestInformation 'pwsh@6.2.3' + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '6.2.3' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result = $null + + $result = Resolve-ManifestInformation 'cosi@7.1.0' + $result.ApplicationName | Should -Be 'cosi' + $result.Bucket | Should -Be 'ash258.ash258' + $result.Version | Should -Be '7.1.0' + $result.ManifestObject.homepage | Should -Be 'https://github.com/PowerShell/PowerShell' + $result = $null + + { Resolve-ManifestInformation 'tryharder' } | Should -Throw 'No manifest found for ''tryharder''' + } + + It 'Specific bucket lookup' { + $result = Resolve-ManifestInformation 'main/pwsh' + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '7.1.3' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result.Bucket | Should -Be 'main' + $result = $null + + $result = Resolve-ManifestInformation 'ash258.ash258/cosi' + $result.ApplicationName | Should -Be 'cosi' + $result.Bucket | Should -Be 'ash258.ash258' + $result.Version | Should -Be '7.1.3' + $result.ManifestObject.checkver | Should -Be 'github' + $result = $null + + { Resolve-ManifestInformation 'nonexistent/cosi' } | Should -Throw '''nonexistent'' cannot be found' + { Resolve-ManifestInformation 'main/tryharder' } | Should -Throw 'No manifest found for ''main/tryharder''' + } + + It 'Specific bucket lookup with existing versioned manifest' { + $result = Resolve-ManifestInformation 'ash258.ash258/pwsh@6.2.3' + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '6.2.3' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result.Bucket | Should -Be 'ash258.ash258' + $result = $null + + $result = Resolve-ManifestInformation 'main/cosi@7.1.0' + $result.ApplicationName | Should -Be 'cosi' + $result.Bucket | Should -Be 'main' + $result.Version | Should -Be '7.1.0' + $result.ManifestObject.homepage | Should -Be 'https://github.com/PowerShell/PowerShell' + $result = $null + + { Resolve-ManifestInformation 'main/pwsh@6.8.0' 6>$null } | Should -Throw 'Cannot generate manifest with version ''6.8.0''' + { Resolve-ManifestInformation 'ash258.ash258/cosi@8' 6>$null } | Should -Throw 'Cannot generate manifest with version ''8''' + } + + It 'Simple lookup with version generation' { + $result = Resolve-ManifestInformation 'pwsh@7.0.6' 6>$null + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '7.0.6' + $result.Bucket | Should -Be 'ash258.ash258' + $result.LocalPath.Extension | Should -BeLike '.json' + $result.LocalPath.BaseName | Should -BeLike 'pwsh-258258--*' + $result.LocalPath.Directory.BaseName | Should -BeLike 'manifests' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result = $null + + $result = Resolve-ManifestInformation 'cosi@6.2.3' 6>$null + $result.ApplicationName | Should -Be 'cosi' + $result.Bucket | Should -Be 'ash258.ash258' + $result.LocalPath.Extension | Should -BeLike '.yaml' + $result.LocalPath.BaseName | Should -BeLike 'cosi-258258--*' + $result.LocalPath.Directory.BaseName | Should -BeLike 'manifests' + $result.Version | Should -Be '6.2.3' + $result.ManifestObject.homepage | Should -Be 'https://github.com/PowerShell/PowerShell' + $result = $null + } + + It 'Specific bucket lookup with version generation' { + $result = Resolve-ManifestInformation 'main/pwsh@7.0.6' 6>$null + $result.ApplicationName | Should -Be 'pwsh' + $result.Version | Should -Be '7.0.6' + $result.Bucket | Should -Be 'main' + $result.LocalPath.Extension | Should -BeLike '.json' + $result.LocalPath.BaseName | Should -BeLike 'pwsh-258258--*' + $result.LocalPath.Directory.BaseName | Should -BeLike 'manifests' + $result.ManifestObject.bin | Should -Be 'pwsh.exe' + $result = $null + + $result = Resolve-ManifestInformation 'ash258.ash258/pwsh@7.0.6' 6>$null + $result.ApplicationName | Should -Be 'pwsh' + $result.Bucket | Should -Be 'ash258.ash258' + $result.LocalPath.Extension | Should -BeLike '.json' + $result.LocalPath.BaseName | Should -BeLike 'pwsh-258258--*' + $result.LocalPath.Directory.BaseName | Should -BeLike 'manifests' + $result.Version | Should -Be '7.0.6' + $result.ManifestObject.homepage | Should -Be 'https://github.com/PowerShell/PowerShell' + $result = $null + } + } + It 'Not supported query' { { Resolve-ManifestInformation '@@cosi@@' } | Should -Throw 'Not supported way how to provide manifest' { Resolve-ManifestInformation '@1.2.5.8' } | Should -Throw 'Not supported way how to provide manifest'