diff options
| author | mae <mae@maestoso.online> | 2026-03-04 22:50:58 -0600 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-05-02 05:05:56 +0900 |
| commit | 1d5d063d6a443c9d4a1206d2743e4824411da956 (patch) | |
| tree | b32105cf3896f394be91099cfbfb67785de39385 /cmd/mbf/internal/pkgserver/index.go | |
| parent | e61628a34ecccae0feb5e059a2f808977261fa0e (diff) | |
cmd/mbf: package status dashboard
This displays package metadata with optional status from a report.
Diffstat (limited to 'cmd/mbf/internal/pkgserver/index.go')
| -rw-r--r-- | cmd/mbf/internal/pkgserver/index.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/cmd/mbf/internal/pkgserver/index.go b/cmd/mbf/internal/pkgserver/index.go new file mode 100644 index 00000000..911183da --- /dev/null +++ b/cmd/mbf/internal/pkgserver/index.go @@ -0,0 +1,106 @@ +package pkgserver + +import ( + "cmp" + "errors" + "slices" + "strings" + + "hakurei.app/internal/pkg" + "hakurei.app/internal/rosa" +) + +const ( + declarationAscending = iota + declarationDescending + nameAscending + nameDescending + sizeAscending + sizeDescending + + 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 + search searchCache + // Taken from [rosa.Report] if available. + handleAccess func(*error) func() +} + +// 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"` + // Output data size, available if present in report. + Size int64 `json:"size,omitempty"` + // Whether the underlying [pkg.Artifact] is present in the report. + HasReport bool `json:"report"` + + // Ident string encoded ahead of time. + ids string + // Backed by [rosa.Report], access must be prepared by HandleAccess. + status []byte +} + +// populate deterministically populates packageIndex, optionally with a report. +func (index *packageIndex) populate(report *rosa.Report) (err error) { + if report != nil { + defer report.HandleAccess(&err)() + index.handleAccess = report.HandleAccess + } + + var work [rosa.PresetUnexportedStart]*metadata + index.names = make(map[string]*metadata) + ir := pkg.NewIR() + 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 report != nil { + id := ir.Ident(rosa.Std.Load(p)) + m.ids = pkg.Encode(id.Value()) + m.status, m.Size = report.ArtifactOf(id) + m.HasReport = m.Size >= 0 + } + + 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][:]) + + index.sorts[sizeAscending] = work + slices.SortFunc(index.sorts[sizeAscending][:], func(a, b *metadata) int { + return cmp.Compare(a.Size, b.Size) + }) + index.sorts[sizeDescending] = index.sorts[sizeAscending] + slices.Reverse(index.sorts[sizeDescending][:]) + + return +} |
