package cmd import ( "code.gitea.io/sdk/gitea" "fmt" "gitea.com/jolheiser/beaver/color" "gitea.com/jolheiser/sip/modules/git" "gitea.com/jolheiser/sip/modules/markdown" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" ) var PullsCreate = cli.Command{ Name: "create", Usage: "Create a new pull request", Action: doPullCreate, } func doPullCreate(ctx *cli.Context) error { fmt.Println() url := color.New(color.FgYellow).Format(fmt.Sprintf("%s/%s/%s", ctx.String("url"), ctx.String("owner"), ctx.String("repo"))) fmt.Println(color.New(color.FgCyan).Format("Creating a new pull request for"), url) token, err := requireToken(ctx) if err != nil { return err } client := gitea.NewClient(ctx.String("url"), token) upstreams, err := client.ListRepoBranches(getUpstreamRepo()[1], getUpstreamRepo()[2]) if err != nil { return err } bases := make([]string, len(upstreams)) defUpstream := upstreams[0].Name for idx, upstream := range upstreams { if upstream.Name == "master" { defUpstream = upstream.Name } bases[idx] = upstream.Name } origins, err := client.ListRepoBranches(getOriginRepo()[1], getOriginRepo()[2]) if err != nil { return err } heads := make([]string, len(origins)) defOrigin := origins[0].Name for idx, origin := range origins { if origin.Name == git.Branch() { defOrigin = getOriginRepo()[1] + ":" + origin.Name } heads[idx] = getOriginRepo()[1] + ":" + origin.Name } var confirmed bool var title, body string base := defUpstream head := defOrigin for !confirmed { questions := []*survey.Question{ { Name: "title", Prompt: &survey.Input{Message: "Title", Default: title}, Validate: survey.Required, }, { Name: "body", Prompt: &survey.Multiline{Message: "Description", Default: body}, }, { Name: "base", Prompt: &survey.Select{Message: "Base target", Options: bases, Default: base}, Validate: survey.Required, }, { Name: "head", Prompt: &survey.Select{Message: "Head target", Options: heads, Default: head}, Validate: survey.Required, }, } answers := struct { Title string Body string Base string Head string }{} if err := survey.Ask(questions, &answers); err != nil { return err } title = answers.Title body = answers.Body base = answers.Base head = answers.Head preview, err := markdown.Render(body) if err != nil { return err } fmt.Printf("%s\n\n%s\n", title, preview) confirm := &survey.Confirm{Message: "Preview above, enter to create or 'n' to edit", Default: true} if err := survey.AskOne(confirm, &confirmed); err != nil { return err } } pull, err := client.CreatePullRequest(ctx.String("owner"), ctx.String("repo"), gitea.CreatePullRequestOption{Title: title, Body: body, Base: base, Head: head}) if err != nil { if fmt.Sprint(err) == "409 Conflict" { // Hard-coded in the SDK return existingPR(client, getUpstreamRepo()[1], getUpstreamRepo()[2], head, err) } return err } info := color.Info cyan := color.New(color.FgCyan) fmt.Println(info.Format("PR"), cyan.Format(fmt.Sprintf("#%d", pull.Index)), info.Format("created!")) fmt.Println(cyan.Format(fmt.Sprintf("%s/%s/%s/pulls/%d", ctx.String("url"), ctx.String("owner"), ctx.String("repo"), pull.Index))) return nil } func existingPR(client *gitea.Client, owner, repo, head string, pullErr error) error { pulls, err := client.ListRepoPullRequests(owner, repo, gitea.ListPullRequestsOptions{State: "open"}) if err != nil { return err } for _, pull := range pulls { compare := fmt.Sprintf("%s:%s", pull.Head.Repository.Owner.UserName, pull.Head.Name) if compare == head { fmt.Println(color.New(color.FgCyan).Format("PR already exists at"), color.New(color.FgYellow).Format(pull.HTMLURL)) return nil } } return pullErr }