Files
hakurei/cmd/mbf/main.go
Ophestra 0bd6a18326
All checks were successful
Test / Create distribution (push) Successful in 49s
Test / Sandbox (push) Successful in 2m33s
Test / ShareFS (push) Successful in 3m55s
Test / Hpkg (push) Successful in 4m36s
Test / Sandbox (race detector) (push) Successful in 4m55s
Test / Hakurei (race detector) (push) Successful in 5m52s
Test / Hakurei (push) Successful in 2m33s
Test / Flake checks (push) Successful in 1m38s
internal/rosa: acl artifact
Required by hakurei.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-01-26 07:38:56 +09:00

234 lines
4.6 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log"
"os"
"os/signal"
"path/filepath"
"runtime"
"syscall"
"unique"
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
"hakurei.app/message"
)
func main() {
container.TryArgv0(nil)
log.SetFlags(0)
log.SetPrefix("mbf: ")
msg := message.New(log.Default())
if os.Geteuid() == 0 {
log.Fatal("this program must not run as root")
}
var cache *pkg.Cache
ctx, stop := signal.NotifyContext(context.Background(),
syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
defer stop()
defer func() {
if cache != nil {
cache.Close()
}
if r := recover(); r != nil {
fmt.Println(r)
log.Fatal("consider scrubbing the on-disk cache")
}
}()
var (
flagQuiet bool
flagCures int
flagBase string
flagTShift int
)
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) (err error) {
msg.SwapVerbose(!flagQuiet)
var base *check.Absolute
if flagBase, err = filepath.Abs(flagBase); err != nil {
return
} else if base, err = check.NewAbs(flagBase); err != nil {
return
}
if cache, err = pkg.Open(ctx, msg, flagCures, base); err == nil {
if flagTShift < 0 {
cache.SetThreshold(0)
} else if flagTShift > 31 {
cache.SetThreshold(1 << 31)
} else {
cache.SetThreshold(1 << flagTShift)
}
}
return
}).Flag(
&flagQuiet,
"q", command.BoolFlag(false),
"Do not print cure messages",
).Flag(
&flagCures,
"cures", command.IntFlag(0),
"Maximum number of dependencies to cure at any given time",
).Flag(
&flagBase,
"d", command.StringFlag("cache"),
"Directory to store cured artifacts",
).Flag(
&flagTShift,
"tshift", command.IntFlag(-1),
"Dependency graph size exponent, to the power of 2",
)
{
var flagShifts int
c.NewCommand(
"scrub", "Examine the on-disk cache for errors",
func(args []string) error {
if len(args) > 0 {
return errors.New("scrub expects no arguments")
}
if flagShifts < 0 || flagShifts > 31 {
flagShifts = 12
}
return cache.Scrub(runtime.NumCPU() << flagShifts)
},
).Flag(
&flagShifts,
"shift", command.IntFlag(12),
"Scrub parallelism size exponent, to the power of 2",
)
}
c.NewCommand(
"stage3",
"Check for toolchain 3-stage non-determinism",
func(args []string) (err error) {
_, _, _, stage2 := (rosa.Std - 1).NewLLVM()
_, _, _, stage3 := rosa.Std.NewLLVM()
var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
)
if pathname, checksum[0], err = cache.Cure(stage2); err != nil {
return err
}
log.Println("stage2:", pathname)
if pathname, checksum[1], err = cache.Cure(stage3); err != nil {
return err
}
log.Println("stage3:", pathname)
if checksum[0] != checksum[1] {
err = &pkg.ChecksumMismatchError{
Got: checksum[0].Value(),
Want: checksum[1].Value(),
}
}
return
},
)
c.NewCommand(
"cure",
"Cure the named artifact and show its path",
func(args []string) error {
if len(args) != 1 {
return errors.New("cure requires 1 argument")
}
var p rosa.PArtifact
switch args[0] {
case "acl":
p = rosa.ACL
case "attr":
p = rosa.Attr
case "autoconf":
p = rosa.Autoconf
case "bash":
p = rosa.Bash
case "busybox":
p = rosa.Busybox
case "cmake":
p = rosa.CMake
case "coreutils":
p = rosa.Coreutils
case "diffutils":
p = rosa.Diffutils
case "gettext":
p = rosa.Gettext
case "git":
p = rosa.Git
case "go":
p = rosa.Go
case "gperf":
p = rosa.Gperf
case "kernel-headers":
p = rosa.KernelHeaders
case "libexpat":
p = rosa.Libexpat
case "libseccomp":
p = rosa.Libseccomp
case "libxml2":
p = rosa.Libxml2
case "libffi":
p = rosa.Libffi
case "libgd":
p = rosa.Libgd
case "m4":
p = rosa.M4
case "make":
p = rosa.Make
case "meson":
p = rosa.Meson
case "ninja":
p = rosa.Ninja
case "patch":
p = rosa.Patch
case "perl":
p = rosa.Perl
case "pkg-config":
p = rosa.PkgConfig
case "python":
p = rosa.Python
case "rsync":
p = rosa.Rsync
case "setuptools":
p = rosa.Setuptools
case "wayland":
p = rosa.Wayland
case "wayland-protocols":
p = rosa.WaylandProtocols
case "zlib":
p = rosa.Zlib
default:
return fmt.Errorf("unsupported artifact %q", args[0])
}
pathname, _, err := cache.Cure(rosa.Std.Load(p))
if err == nil {
log.Println(pathname)
}
return err
},
)
c.MustParse(os.Args[1:], func(err error) {
if cache != nil {
cache.Close()
}
log.Fatal(err)
})
}