2022-08-23 19:38:41 +00:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"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"
|
2022-08-30 18:58:49 +00:00
|
|
|
"github.com/skratchdot/open-golang/open"
|
2022-08-23 19:38:41 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-08-30 18:58:49 +00:00
|
|
|
backportFS = flag.NewFlagSet("backport", flag.ContinueOnError)
|
|
|
|
backportFromFlag = backportFS.String("from", "", "Release to backport from (ex: `main`, default: main)")
|
|
|
|
backportToFlag = backportFS.String("to", "", "Release to backport to (ex: `1.17`, default: <latest>)")
|
|
|
|
backportListFlag = backportFS.Bool("list", false, "Open repository to see needed backports")
|
|
|
|
Backport = &ffcli.Command{
|
2022-08-23 19:38:41 +00:00
|
|
|
Name: "backport",
|
|
|
|
FlagSet: backportFS,
|
2022-08-30 18:58:49 +00:00
|
|
|
ShortUsage: "backport --from [release=main] --to [release=latest]",
|
2022-08-23 19:38:41 +00:00
|
|
|
ShortHelp: "backport cherry-picks a <commit> and applies it to a clean branch based on <release>",
|
2022-08-30 18:58:49 +00:00
|
|
|
Exec: func(ctx context.Context, _ []string) error {
|
|
|
|
to := *backportToFlag
|
|
|
|
if to == "" {
|
|
|
|
to = latestRelease()
|
|
|
|
}
|
|
|
|
|
|
|
|
if *backportListFlag {
|
|
|
|
if err := open.Run(fmt.Sprintf("https://github.com/go-gitea/gitea/pulls?q=is%%3Apr+-label%%3Abackport%%2Fdone+label%%3Abackport%%2Fv1.%s+is%%3Amerged", to)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-08-23 19:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fetch(ctx)
|
|
|
|
|
|
|
|
if !isClean() {
|
|
|
|
log.Fatal().Msg("working tree is dirty")
|
|
|
|
}
|
|
|
|
|
2022-08-30 18:58:49 +00:00
|
|
|
from := *backportFromFlag
|
|
|
|
if from == "" {
|
|
|
|
from = "main"
|
|
|
|
}
|
|
|
|
|
2022-08-23 19:38:41 +00:00
|
|
|
commits, err := repo().Log(&git.LogOptions{
|
2022-08-30 18:58:49 +00:00
|
|
|
From: head(from),
|
2022-08-23 19:38:41 +00:00
|
|
|
})
|
|
|
|
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("backport-%s", hash)
|
2022-08-30 18:58:49 +00:00
|
|
|
base := fmt.Sprintf("upstream/release/v1.%s", to)
|
|
|
|
if err := Branch.ParseAndRun(ctx, []string{"--base", base, branch}); err != nil {
|
2022-08-23 19:38:41 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return run(ctx, "git", "cherry-pick", hash.String())
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|