aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-01-18 22:19:19 +0900
committerOphestra <cat@gensokyo.uk>2026-01-18 22:19:19 +0900
commit2a9525c77ab0d15f802c9277a13072311d147483 (patch)
treeb7465f50131a637cc17132265a11dd11ddc543a2 /cmd
parentefc90c3221f42562a9758b0bbdabf30cc95b8f7b (diff)
cmd/mbf: command handling
This tool is a frontend for bootstrapping hakurei via internal/pkg. Named mbf for now for "maiden's best friend" as a tribute to the DOOM source port. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/mbf/main.go113
1 files changed, 113 insertions, 0 deletions
diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go
new file mode 100644
index 00000000..372c0acd
--- /dev/null
+++ b/cmd/mbf/main.go
@@ -0,0 +1,113 @@
+package main
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "runtime"
+ "syscall"
+
+ "hakurei.app/command"
+ "hakurei.app/container"
+ "hakurei.app/container/check"
+ "hakurei.app/internal/pkg"
+ "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 (
+ flagVerbose bool
+ flagCures int
+ flagBase string
+ flagTShift int
+ )
+ c := command.New(os.Stderr, log.Printf, "mbf", func([]string) (err error) {
+ msg.SwapVerbose(flagVerbose)
+
+ 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 || flagTShift > 31 {
+ flagTShift = 31
+ }
+ cache.SetThreshold(1 << flagTShift)
+ }
+ return
+ }).Flag(
+ &flagVerbose,
+ "v", command.BoolFlag(false),
+ "Print cure messages to the console",
+ ).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(31),
+ "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.MustParse(os.Args[1:], func(err error) {
+ if cache != nil {
+ cache.Close()
+ }
+ log.Fatal(err)
+ })
+}