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:
2026-03-11 01:36:54 +09:00
parent fa9bc70b39
commit 887edcbe48
5 changed files with 350 additions and 101 deletions

View File

@@ -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
}