internal/rosa: evaluate packages from fs
All checks were successful
Test / Create distribution (push) Successful in 1m6s
Test / Sandbox (push) Successful in 2m48s
Test / ShareFS (push) Successful in 3m43s
Test / Hakurei (push) Successful in 3m52s
Test / Sandbox (race detector) (push) Successful in 5m23s
Test / Hakurei (race detector) (push) Successful in 6m31s
Test / Flake checks (push) Successful in 1m22s

This migrates GNU sed to azalea, and resulting IR matches.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-05-18 17:53:48 +09:00
parent 0360e779f3
commit 37df040d85
5 changed files with 133 additions and 30 deletions

View File

@@ -64,11 +64,11 @@ func main() {
return return
} }
h, ok := r.(rosa.HandleError) e, ok := r.(rosa.LoadError)
if !ok { if !ok {
panic(r) panic(r)
} }
log.Fatal(h) log.Fatal(e)
}() }()
ctx, stop := signal.NotifyContext(context.Background(), ctx, stop := signal.NotifyContext(context.Background(),

View File

@@ -109,33 +109,6 @@ func init() {
}) })
} }
func (t Toolchain) newSed() (pkg.Artifact, string) {
const (
version = "4.10"
checksum = "TXTRFQJCyflb-bpBRI2S5Y1DpplwvT7-KfXtpqN4AdZgZ5OtI6yStn1-bkhDKx51"
)
return t.NewPackage("sed", version, newTar(
"https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz",
checksum,
pkg.TarGzip,
), nil, (*MakeHelper)(nil),
Diffutils,
KernelHeaders,
), version
}
func init() {
native.MustRegister(&Artifact{
f: Toolchain.newSed,
Name: "sed",
Description: "a non-interactive command-line text editor",
Website: "https://www.gnu.org/software/sed/",
ID: 4789,
})
}
func (t Toolchain) newAutoconf() (pkg.Artifact, string) { func (t Toolchain) newAutoconf() (pkg.Artifact, string) {
const ( const (
version = "2.73" version = "2.73"

View File

@@ -0,0 +1,22 @@
// GNU software with trivial packaging.
package sed {
description = "a non-interactive command-line text editor";
website = "https://www.gnu.org/software/sed";
anitya = 4789;
version* = "4.10";
source = remoteTar {
url = "https://ftpmirror.gnu.org/gnu/sed/sed-"+version+".tar.gz";
checksum = "TXTRFQJCyflb-bpBRI2S5Y1DpplwvT7-KfXtpqN4AdZgZ5OtI6yStn1-bkhDKx51";
compress = gzip;
};
exec = make {};
inputs = [
diffutils,
kernel-headers,
];
}

View File

@@ -2,6 +2,9 @@
package rosa package rosa
import ( import (
"embed"
"io/fs"
"os"
"path" "path"
"slices" "slices"
"strconv" "strconv"
@@ -608,3 +611,20 @@ var native S
// Native returns the global [S]. // Native returns the global [S].
func Native() *S { return &native } func Native() *S { return &native }
// nativeB is the backing directory of built-in azalea-based [Artifact]
// implementations.
//
//go:embed package
var nativeB embed.FS
func init() {
sub, err := fs.Sub(nativeB, "package")
if err != nil {
panic(err)
}
if err = native.EvaluateFS(sub); err != nil {
println(err)
os.Exit(1)
}
}

View File

@@ -52,7 +52,7 @@ func (handle *ArtifactH) UnmarshalJSON(data []byte) error {
type HandleError ArtifactH type HandleError ArtifactH
func (e HandleError) Error() string { func (e HandleError) Error() string {
return "artifact " + strconv.Quote(ArtifactH(e).String()) + " not available" return "package " + strconv.Quote(ArtifactH(e).String()) + " not available"
} }
type ( type (
@@ -268,8 +268,38 @@ func (s *S) New(stage Stage) Toolchain {
// Std is a convenience method that returns a [Toolchain] for the [Std] stage. // Std is a convenience method that returns a [Toolchain] for the [Std] stage.
func (s *S) Std() Toolchain { return s.New(Std) } func (s *S) Std() Toolchain { return s.New(Std) }
// LoadError wraps panicked errors reaching [Toolchain.Load].
type LoadError struct {
// Offending artifact handle.
Handle ArtifactH
// Recovered error.
Err error
}
func (e LoadError) Unwrap() error { return e.Err }
func (e LoadError) Error() string {
return "cannot load " + strconv.Quote(e.Handle.String()) + ": " + e.Err.Error()
}
// Load returns the resulting [pkg.Artifact] of [ArtifactH]. // Load returns the resulting [pkg.Artifact] of [ArtifactH].
func (t Toolchain) Load(handle ArtifactH) (pkg.Artifact, string) { func (t Toolchain) Load(handle ArtifactH) (pkg.Artifact, string) {
defer func() {
r := recover()
if r == nil {
return
}
err, ok := r.(error)
if !ok {
panic(r)
}
if _, ok = err.(LoadError); ok {
panic(err)
}
panic(LoadError{handle, err})
}()
t.wantsArch() t.wantsArch()
e, ok := t.c[t.stage].Load(handle) e, ok := t.c[t.stage].Load(handle)
if ok { if ok {
@@ -552,6 +582,64 @@ func (s *S) Evaluate(r io.Reader, b fs.FS) error {
return nil return nil
} }
// EvaluateFS evaluates azalea files discovered in fsys. A file is evaluated if
// it is at the top level and its name has the suffix ".az", or it is in a
// top-level directory with the exact file name "package.az". The backing
// filesystem is directly exposed to azalea pathnames.
func (s *S) EvaluateFS(fsys fs.FS) error {
dents, err := fs.ReadDir(fsys, ".")
if err != nil {
return err
}
var r fs.File
for _, dent := range dents {
if dent.IsDir() {
var sub fs.FS
sub, err = fs.Sub(fsys, dent.Name())
if err != nil {
return err
}
r, err = sub.Open("package.az")
if errors.Is(err, fs.ErrNotExist) {
continue
}
if err != nil {
return err
}
err = s.Evaluate(r, sub)
if _err := r.Close(); err == nil {
err = _err
}
if err != nil {
return err
}
continue
}
if !dent.Type().IsRegular() ||
!strings.HasSuffix(dent.Name(), ".az") {
continue
}
r, err = fsys.Open(dent.Name())
if err != nil {
return err
}
err = s.Evaluate(r, fsys)
if _err := r.Close(); err == nil {
err = _err
}
if err != nil {
return err
}
}
return nil
}
// SetGentooStage3 sets the Gentoo stage3 tarball url and checksum. It panics // SetGentooStage3 sets the Gentoo stage3 tarball url and checksum. It panics
// if given zero values or if these values have already been set. // if given zero values or if these values have already been set.
func (s *S) SetGentooStage3(url string, checksum pkg.Checksum) { func (s *S) SetGentooStage3(url string, checksum pkg.Checksum) {