forked from security/hakurei
This enables referencing back to internal/rosa through an entry obtained via the index. Signed-off-by: Ophestra <cat@gensokyo.uk>
93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
"strings"
|
|
"unique"
|
|
|
|
"hakurei.app/internal/pkg"
|
|
"hakurei.app/internal/rosa"
|
|
)
|
|
|
|
const (
|
|
declarationAscending = iota
|
|
declarationDescending
|
|
nameAscending
|
|
nameDescending
|
|
|
|
sortOrderEnd = iota - 1
|
|
)
|
|
|
|
// packageIndex refers to metadata by name and various sort orders.
|
|
type packageIndex struct {
|
|
sorts [sortOrderEnd + 1][rosa.PresetUnexportedStart]*metadata
|
|
names map[string]*metadata
|
|
}
|
|
|
|
// metadata holds [rosa.Metadata] extended with additional information.
|
|
type metadata struct {
|
|
p rosa.PArtifact
|
|
*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"`
|
|
|
|
// Ident resolved from underlying [pkg.Artifact].
|
|
ident unique.Handle[pkg.ID]
|
|
// Backed by [rosa.Report], access must be prepared by HandleAccess.
|
|
status []byte
|
|
}
|
|
|
|
// 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 := metadata{
|
|
p: p,
|
|
|
|
Metadata: rosa.GetMetadata(p),
|
|
Version: rosa.Std.Version(p),
|
|
}
|
|
if m.Version == "" {
|
|
return errors.New("invalid version from " + m.Name)
|
|
}
|
|
if m.Version == rosa.Unversioned {
|
|
m.Version = ""
|
|
}
|
|
|
|
if cache != nil && report != nil {
|
|
m.ident = cache.Ident(rosa.Std.Load(p))
|
|
status, n := report.ArtifactOf(m.ident)
|
|
if n >= 0 {
|
|
m.HasReport = true
|
|
m.status = status
|
|
}
|
|
}
|
|
|
|
work[p] = &m
|
|
index.names[m.Name] = &m
|
|
}
|
|
|
|
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)
|
|
})
|
|
index.sorts[nameDescending] = index.sorts[nameAscending]
|
|
slices.Reverse(index.sorts[nameDescending][:])
|
|
|
|
return
|
|
}
|