package cmd import ( "context" "errors" "flag" "fmt" "strings" "github.com/AlecAivazis/survey/v2" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/peterbourgon/ff/v3/ffcli" "github.com/rs/zerolog/log" ) var ( frontportFS = flag.NewFlagSet("frontport", flag.ContinueOnError) Frontport = &ffcli.Command{ Name: "frontport", FlagSet: frontportFS, ShortUsage: "frontport [release=main]", ShortHelp: "frontport cherry-picks a and applies it to a clean branch based on ", Exec: func(ctx context.Context, args []string) error { if len(args) < 1 { return errors.New("frontport requires at least one argument") } from := args[0] if !strings.HasPrefix(from, "release") { from = fmt.Sprintf("release/v%s", args[0]) } fetch(ctx) if !isClean() { log.Fatal().Msg("working tree is dirty") } commits, err := repo().Log(&git.LogOptions{ From: head(from), }) if err != nil { return err } optMap := make(map[string]plumbing.Hash) var opts []string if err := commits.ForEach(func(c *object.Commit) error { title := strings.Split(c.Message, "\n")[0] opts = append(opts, title) optMap[title] = c.Hash return nil }); err != nil { return err } var resp string if err := survey.AskOne(&survey.Select{ Message: "Commit to cherry-pick", Options: opts, }, &resp, survey.WithValidator(survey.Required)); err != nil { return err } hash := optMap[resp] branch := fmt.Sprintf("frontport-%s", hash) base := "upstream/main" if len(args) > 1 { base = fmt.Sprintf("upstream/release/v%s", args[1]) } if err := Branch.ParseAndRun(ctx, []string{branch, base}); err != nil { return err } return run(ctx, "git", "cherry-pick", hash.String()) }, } )