9 Commits

Author SHA1 Message Date
mae
b255f07b0f Merge remote-tracking branch 'origin/pkgserver' into pkgserver 2026-03-05 02:06:27 -06:00
mae
dec4cdd068 cmd/pkgserver: replace favicon 2026-03-05 02:06:07 -06:00
mae
73c620ecd5 cmd/pkgserver: pagination 2026-03-05 02:06:07 -06:00
mae
69467a1542 cmd/pkgserver: basic web ui 2026-03-05 02:06:07 -06:00
ebdf9dcecc cmd/mbf: preset status command
This exposes the new OpenStatus cache method.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-05 16:59:47 +09:00
8ea2a56d5b internal/pkg: expose status file
This is useful for external tooling.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-05 16:58:52 +09:00
159a45c027 internal/rosa: export preset bounds
These are useful for external tooling.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-05 16:34:25 +09:00
0eb2bfa12e internal/rosa/zlib: 1.3.1 to 1.3.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-05 15:49:18 +09:00
e19a98244a internal/rosa: zlib use stable archive url
These do not get removed on new release.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-05 15:46:10 +09:00
5 changed files with 61 additions and 23 deletions

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"os/signal" "os/signal"
@@ -260,6 +261,30 @@ func main() {
) )
} }
c.NewCommand(
"status",
"Display the status file of an artifact",
func(args []string) error {
if len(args) != 1 {
return errors.New("status requires 1 argument")
}
if p, ok := rosa.ResolveName(args[0]); !ok {
return fmt.Errorf("unknown artifact %q", args[0])
} else {
r, err := cache.OpenStatus(rosa.Std.Load(p))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return errors.New(args[0] + " was never cured")
}
return err
}
_, err = io.Copy(os.Stdout, r)
return errors.Join(err, r.Close())
}
},
)
{ {
var ( var (
flagNet bool flagNet bool

View File

@@ -1790,6 +1790,18 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
pending.errsMu.Unlock() pending.errsMu.Unlock()
} }
// OpenStatus attempts to open the status file associated to an [Artifact]. If
// err is nil, the caller must close the resulting reader.
func (c *Cache) OpenStatus(a Artifact) (r io.ReadSeekCloser, err error) {
c.identMu.RLock()
r, err = os.Open(c.base.Append(
dirStatus,
Encode(c.Ident(a).Value())).String(),
)
c.identMu.RUnlock()
return
}
// Close cancels all pending cures and waits for them to clean up. // Close cancels all pending cures and waits for them to clean up.
func (c *Cache) Close() { func (c *Cache) Close() {
c.closeOnce.Do(func() { c.closeOnce.Do(func() {

View File

@@ -120,8 +120,8 @@ const (
Zlib Zlib
Zstd Zstd
// _presetUnexportedStart is the first unexported preset. // PresetUnexportedStart is the first unexported preset.
_presetUnexportedStart PresetUnexportedStart
buildcatrust = iota - 1 buildcatrust = iota - 1
utilMacros utilMacros
@@ -137,8 +137,8 @@ const (
// part of the [Std] toolchain. // part of the [Std] toolchain.
Stage0 Stage0
// _presetEnd is the total number of presets and does not denote a preset. // PresetEnd is the total number of presets and does not denote a preset.
_presetEnd PresetEnd
) )
// Metadata is stage-agnostic information of a [PArtifact] not directly // Metadata is stage-agnostic information of a [PArtifact] not directly
@@ -159,7 +159,7 @@ const Unversioned = "\x00"
var ( var (
// artifactsM is an array of [PArtifact] metadata. // artifactsM is an array of [PArtifact] metadata.
artifactsM [_presetEnd]Metadata artifactsM [PresetEnd]Metadata
// artifacts stores the result of Metadata.f. // artifacts stores the result of Metadata.f.
artifacts [_toolchainEnd][len(artifactsM)]pkg.Artifact artifacts [_toolchainEnd][len(artifactsM)]pkg.Artifact
@@ -190,7 +190,7 @@ func (t Toolchain) Version(p PArtifact) string {
// ResolveName returns a [PArtifact] by name. // ResolveName returns a [PArtifact] by name.
func ResolveName(name string) (p PArtifact, ok bool) { func ResolveName(name string) (p PArtifact, ok bool) {
for i := range _presetUnexportedStart { for i := range PresetUnexportedStart {
if name == artifactsM[i].Name { if name == artifactsM[i].Name {
return i, true return i, true
} }

View File

@@ -1,19 +1,20 @@
package rosa package rosa_test
import "testing" import (
"testing"
// PresetEnd is the total PArtifact count exported for testing. "hakurei.app/internal/rosa"
const PresetEnd = _presetEnd )
func TestLoad(t *testing.T) { func TestLoad(t *testing.T) {
t.Parallel() t.Parallel()
for i := range _presetEnd { for i := range rosa.PresetEnd {
p := PArtifact(i) p := rosa.PArtifact(i)
t.Run(GetMetadata(p).Name, func(t *testing.T) { t.Run(rosa.GetMetadata(p).Name, func(t *testing.T) {
t.Parallel() t.Parallel()
Std.Load(p) rosa.Std.Load(p)
}) })
} }
} }
@@ -21,13 +22,13 @@ func TestLoad(t *testing.T) {
func TestResolveName(t *testing.T) { func TestResolveName(t *testing.T) {
t.Parallel() t.Parallel()
for i := range _presetUnexportedStart { for i := range rosa.PresetUnexportedStart {
p := i p := i
name := GetMetadata(p).Name name := rosa.GetMetadata(p).Name
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
if got, ok := ResolveName(name); !ok { if got, ok := rosa.ResolveName(name); !ok {
t.Fatal("ResolveName: ok = false") t.Fatal("ResolveName: ok = false")
} else if got != p { } else if got != p {
t.Fatalf("ResolveName: %d, want %d", got, p) t.Fatalf("ResolveName: %d, want %d", got, p)
@@ -38,13 +39,13 @@ func TestResolveName(t *testing.T) {
func TestResolveNameUnexported(t *testing.T) { func TestResolveNameUnexported(t *testing.T) {
t.Parallel() t.Parallel()
for i := _presetUnexportedStart; i < _presetEnd; i++ { for i := rosa.PresetUnexportedStart; i < rosa.PresetEnd; i++ {
p := i p := i
name := GetMetadata(p).Name name := rosa.GetMetadata(p).Name
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
if got, ok := ResolveName(name); ok { if got, ok := rosa.ResolveName(name); ok {
t.Fatalf("ResolveName: resolved unexported preset %d", got) t.Fatalf("ResolveName: resolved unexported preset %d", got)
} }
}) })

View File

@@ -4,11 +4,11 @@ import "hakurei.app/internal/pkg"
func (t Toolchain) newZlib() (pkg.Artifact, string) { func (t Toolchain) newZlib() (pkg.Artifact, string) {
const ( const (
version = "1.3.1" version = "1.3.2"
checksum = "E-eIpNzE8oJ5DsqH4UuA_0GDKuQF5csqI8ooDx2w7Vx-woJ2mb-YtSbEyIMN44mH" checksum = "KHZrePe42vL2XvOUE3KlJkp1UgWhWkl0jjT_BOvFhuM4GzieEH9S7CioepOFVGYB"
) )
return t.NewPackage("zlib", version, pkg.NewHTTPGetTar( return t.NewPackage("zlib", version, pkg.NewHTTPGetTar(
nil, "https://zlib.net/zlib-"+version+".tar.gz", nil, "https://www.zlib.net/fossils/zlib-"+version+".tar.gz",
mustDecode(checksum), mustDecode(checksum),
pkg.TarGzip, pkg.TarGzip,
), &PackageAttr{ ), &PackageAttr{