From 37df040d85e06100c69c6aa3560b2e4ebf977255 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Mon, 18 May 2026 17:53:48 +0900 Subject: [PATCH] internal/rosa: evaluate packages from fs This migrates GNU sed to azalea, and resulting IR matches. Signed-off-by: Ophestra --- cmd/mbf/main.go | 4 +- internal/rosa/gnu.go | 27 --------- internal/rosa/package/gnu/package.az | 22 +++++++ internal/rosa/rosa.go | 20 +++++++ internal/rosa/state.go | 90 +++++++++++++++++++++++++++- 5 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 internal/rosa/package/gnu/package.az diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index f3532326..69e84fce 100644 --- a/cmd/mbf/main.go +++ b/cmd/mbf/main.go @@ -64,11 +64,11 @@ func main() { return } - h, ok := r.(rosa.HandleError) + e, ok := r.(rosa.LoadError) if !ok { panic(r) } - log.Fatal(h) + log.Fatal(e) }() ctx, stop := signal.NotifyContext(context.Background(), diff --git a/internal/rosa/gnu.go b/internal/rosa/gnu.go index 54833db5..5e6bb358 100644 --- a/internal/rosa/gnu.go +++ b/internal/rosa/gnu.go @@ -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) { const ( version = "2.73" diff --git a/internal/rosa/package/gnu/package.az b/internal/rosa/package/gnu/package.az new file mode 100644 index 00000000..a50c1a90 --- /dev/null +++ b/internal/rosa/package/gnu/package.az @@ -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, + ]; +} diff --git a/internal/rosa/rosa.go b/internal/rosa/rosa.go index 709b8420..d1a6c25e 100644 --- a/internal/rosa/rosa.go +++ b/internal/rosa/rosa.go @@ -2,6 +2,9 @@ package rosa import ( + "embed" + "io/fs" + "os" "path" "slices" "strconv" @@ -608,3 +611,20 @@ var native S // Native returns the global [S]. 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) + } +} diff --git a/internal/rosa/state.go b/internal/rosa/state.go index 71f25520..b01c4c38 100644 --- a/internal/rosa/state.go +++ b/internal/rosa/state.go @@ -52,7 +52,7 @@ func (handle *ArtifactH) UnmarshalJSON(data []byte) error { type HandleError ArtifactH func (e HandleError) Error() string { - return "artifact " + strconv.Quote(ArtifactH(e).String()) + " not available" + return "package " + strconv.Quote(ArtifactH(e).String()) + " not available" } 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. 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]. 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() e, ok := t.c[t.stage].Load(handle) if ok { @@ -552,6 +582,64 @@ func (s *S) Evaluate(r io.Reader, b fs.FS) error { 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 // if given zero values or if these values have already been set. func (s *S) SetGentooStage3(url string, checksum pkg.Checksum) {