package main import ( "context" "fmt" "os" "os/exec" "path/filepath" "strings" "git.golem15.com/golem15/summercms/bonfire" "git.golem15.com/golem15/summercms/internal/build" ) func delegateCommand(name, description string) bonfire.Command { return bonfire.Command{ Name: name, Description: description, Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error { argv := []string{name} argv = append(argv, in.Args()...) return runAppBinary(ctx, argv, out) }, } } func delegateRollbackCommand() bonfire.Command { return bonfire.Command{ Name: "migrate:rollback", Description: "Roll back the last migration of a plugin in the app binary", Flags: []bonfire.Flag{{ Name: "plugin", Description: "Plugin ID whose last migration to roll back", }}, Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error { argv := []string{"migrate:rollback"} if plugin, ok := in.Flag("plugin"); ok && plugin != "" { argv = append(argv, "--plugin", plugin) } argv = append(argv, in.Args()...) return runAppBinary(ctx, argv, out) }, } } func runAppBinary(ctx context.Context, argv []string, out bonfire.Output) error { if len(argv) == 0 { return fmt.Errorf("summer: missing app command") } dir, err := os.Getwd() if err != nil { return err } appDir, err := build.FindAppDir(dir) if err != nil { return err } m, err := build.LoadManifest(filepath.Join(appDir, "summer.yaml")) if err != nil { return err } bin := filepath.Join(appDir, "bin", m.Binary) if _, err := os.Stat(bin); err != nil { if err := build.App(ctx, appDir, out); err != nil { return err } } self, err := os.Executable() if err == nil { if same, _ := sameFile(self, bin); same { return fmt.Errorf("summer: refusing to recurse into %s", bin) } } cmd := exec.CommandContext(ctx, bin, argv...) cmd.Dir = appDir cmd.Stdout = out cmd.Stderr = out cmd.Stdin = os.Stdin cmd.Env = os.Environ() if err := cmd.Run(); err != nil { return fmt.Errorf("summer: %s: %w", strings.Join(argv, " "), err) } return nil } func sameFile(a, b string) (bool, error) { ai, err := os.Stat(a) if err != nil { return false, err } bi, err := os.Stat(b) if err != nil { return false, err } return os.SameFile(ai, bi), nil }