forked from security/hakurei
cmd/pkgserver: embed internal/rosa metadata
This change also cleans up and reduces some unnecessary copies. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -1,86 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
"strings"
|
||||
"unique"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/internal/rosa"
|
||||
)
|
||||
|
||||
type SortOrders int
|
||||
|
||||
const (
|
||||
DeclarationAscending SortOrders = iota
|
||||
DeclarationDescending
|
||||
NameAscending
|
||||
NameDescending
|
||||
limitSortOrders
|
||||
declarationAscending = iota
|
||||
declarationDescending
|
||||
nameAscending
|
||||
nameDescending
|
||||
|
||||
sortOrderEnd = iota - 1
|
||||
)
|
||||
|
||||
type PackageIndex struct {
|
||||
sorts [limitSortOrders][rosa.PresetUnexportedStart]*PackageIndexEntry
|
||||
names map[string]*PackageIndexEntry
|
||||
// packageIndex refers to metadata by name and various sort orders.
|
||||
type packageIndex struct {
|
||||
sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata
|
||||
names map[string]*metadata
|
||||
}
|
||||
|
||||
type PackageIndexEntry struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Website string `json:"website,omitempty"`
|
||||
Version string `json:"version"`
|
||||
HasReport bool `json:"report,omitempty"`
|
||||
ident unique.Handle[pkg.ID] `json:"-"`
|
||||
status []byte `json:"-"`
|
||||
// metadata holds [rosa.Metadata] extended with additional information.
|
||||
type metadata struct {
|
||||
*rosa.Metadata
|
||||
|
||||
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
|
||||
// to the zero value. Otherwise, the zero value is invalid.
|
||||
Version string `json:"version,omitempty"`
|
||||
// Whether the underlying [pkg.Artifact] is present in the report.
|
||||
HasReport bool `json:"report,omitempty"`
|
||||
|
||||
// Ident resolved from underlying [pkg.Artifact].
|
||||
ident unique.Handle[pkg.ID]
|
||||
// Backed by [rosa.Report], access must be prepared by HandleAccess.
|
||||
status []byte
|
||||
}
|
||||
|
||||
func createPackageIndex(cache *pkg.Cache, report *rosa.Report) (index *PackageIndex, err error) {
|
||||
index = new(PackageIndex)
|
||||
index.names = make(map[string]*PackageIndexEntry, rosa.PresetUnexportedStart)
|
||||
work := make([]PackageIndexEntry, rosa.PresetUnexportedStart)
|
||||
// populate deterministically populates packageIndex, optionally with a report.
|
||||
func (index *packageIndex) populate(cache *pkg.Cache, report *rosa.Report) (err error) {
|
||||
if report != nil {
|
||||
defer report.HandleAccess(&err)()
|
||||
}
|
||||
|
||||
var work [rosa.PresetUnexportedStart]*metadata
|
||||
index.names = make(map[string]*metadata)
|
||||
for p := range rosa.PresetUnexportedStart {
|
||||
m := rosa.GetMetadata(p)
|
||||
v := rosa.Std.Version(p)
|
||||
a := rosa.Std.Load(p)
|
||||
entry := PackageIndexEntry{
|
||||
Name: m.Name,
|
||||
Description: m.Description,
|
||||
Website: m.Website,
|
||||
Version: v,
|
||||
m := metadata{
|
||||
Metadata: rosa.GetMetadata(p),
|
||||
Version: rosa.Std.Version(p),
|
||||
}
|
||||
|
||||
if cache != nil && report != nil {
|
||||
entry.ident = cache.Ident(a)
|
||||
status, n := report.ArtifactOf(entry.ident)
|
||||
m.ident = cache.Ident(rosa.Std.Load(p))
|
||||
status, n := report.ArtifactOf(m.ident)
|
||||
if n >= 0 {
|
||||
entry.HasReport = true
|
||||
entry.status = status
|
||||
m.HasReport = true
|
||||
m.status = status
|
||||
}
|
||||
}
|
||||
|
||||
work[p] = entry
|
||||
index.names[m.Name] = &entry
|
||||
work[p] = &m
|
||||
index.names[m.Name] = &m
|
||||
}
|
||||
for i, p := range work {
|
||||
index.sorts[DeclarationAscending][i] = &p
|
||||
}
|
||||
slices.Reverse(work)
|
||||
for i, p := range work {
|
||||
index.sorts[DeclarationDescending][i] = &p
|
||||
}
|
||||
slices.SortFunc(work, func(a PackageIndexEntry, b PackageIndexEntry) int {
|
||||
return cmp.Compare(a.Name, b.Name)
|
||||
|
||||
index.sorts[declarationAscending] = work
|
||||
index.sorts[declarationDescending] = work
|
||||
slices.Reverse(index.sorts[declarationDescending][:])
|
||||
|
||||
index.sorts[nameAscending] = work
|
||||
slices.SortFunc(index.sorts[nameAscending][:], func(a, b *metadata) int {
|
||||
return strings.Compare(a.Name, b.Name)
|
||||
})
|
||||
for i, p := range work {
|
||||
index.sorts[NameAscending][i] = &p
|
||||
}
|
||||
slices.Reverse(work)
|
||||
for i, p := range work {
|
||||
index.sorts[NameDescending][i] = &p
|
||||
}
|
||||
index.sorts[nameDescending] = index.sorts[nameAscending]
|
||||
slices.Reverse(index.sorts[nameDescending][:])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user