package main import ( "context" "errors" "log" "net/http" "os" "os/signal" "syscall" "time" "hakurei.app/command" "hakurei.app/container/check" "hakurei.app/internal/pkg" "hakurei.app/internal/rosa" "hakurei.app/message" ) const shutdownTimeout = 15 * time.Second func main() { log.SetFlags(0) log.SetPrefix("pkgserver: ") var ( flagBaseDir string flagAddr string ) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) defer stop() msg := message.New(log.Default()) c := command.New(os.Stderr, log.Printf, "pkgserver", func(args []string) error { var ( cache *pkg.Cache report *rosa.Report ) switch len(args) { case 0: break case 1: baseDir, err := check.NewAbs(flagBaseDir) if err != nil { return err } cache, err = pkg.Open(ctx, msg, 0, baseDir) if err != nil { return err } defer cache.Close() report, err = rosa.OpenReport(args[0]) if err != nil { return err } default: return errors.New("pkgserver requires 1 argument") } var index packageIndex if err := index.populate(cache, report); err != nil { return err } var mux http.ServeMux uiRoutes(&mux) index.registerAPI(&mux) server := http.Server{ Addr: flagAddr, Handler: &mux, } go func() { <-ctx.Done() c, cancel := context.WithTimeout(context.Background(), shutdownTimeout) defer cancel() if err := server.Shutdown(c); err != nil { log.Fatal(err) } }() return server.ListenAndServe() }).Flag( &flagBaseDir, "b", command.StringFlag(""), "base directory for cache", ).Flag( &flagAddr, "addr", command.StringFlag(":8067"), "TCP network address to listen on", ) c.MustParse(os.Args[1:], func(err error) { if errors.Is(err, http.ErrServerClosed) { os.Exit(0) } log.Fatal(err) }) }