207 lines
4.2 KiB
Go
207 lines
4.2 KiB
Go
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/github/gh-cli/api"
|
|
"github.com/github/gh-cli/context"
|
|
"github.com/github/gh-cli/git"
|
|
"github.com/github/gh-cli/utils"
|
|
"github.com/spf13/cobra"
|
|
"os"
|
|
"runtime"
|
|
)
|
|
|
|
var (
|
|
_draftF bool
|
|
_titleF string
|
|
_bodyF string
|
|
_baseF string
|
|
)
|
|
|
|
func prCreate(ctx context.Context) error {
|
|
ucc, err := git.UncommittedChangeCount()
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"could not determine state of working directory: %v", err)
|
|
}
|
|
if ucc > 0 {
|
|
noun := "change"
|
|
if ucc > 1 {
|
|
noun = noun + "s"
|
|
}
|
|
|
|
fmt.Printf("%s %d uncommitted %s %s", utils.Red("!!!"),
|
|
ucc, noun, utils.Red("!!!"))
|
|
}
|
|
|
|
head, err := ctx.Branch()
|
|
if err != nil {
|
|
return fmt.Errorf("could not determine current branch: %s", err)
|
|
}
|
|
|
|
remote, err := guessRemote(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = git.Push(remote, fmt.Sprintf("HEAD:%s", head)); err != nil {
|
|
return fmt.Errorf("was not able to push to remote '%s': %s", remote, err)
|
|
}
|
|
|
|
interactive := _titleF == "" || _bodyF == ""
|
|
|
|
inProgress := struct {
|
|
Body string
|
|
Title string
|
|
}{}
|
|
|
|
if interactive {
|
|
confirmed := false
|
|
editor := determineEditor()
|
|
|
|
for !confirmed {
|
|
titleQuestion := &survey.Question{
|
|
Name: "title",
|
|
Prompt: &survey.Input{
|
|
Message: "PR Title",
|
|
Default: inProgress.Title,
|
|
},
|
|
}
|
|
bodyQuestion := &survey.Question{
|
|
Name: "body",
|
|
Prompt: &survey.Editor{
|
|
Message: fmt.Sprintf("PR Body (%s)", editor),
|
|
FileName: "*.md",
|
|
Default: inProgress.Body,
|
|
AppendDefault: true,
|
|
Editor: editor,
|
|
},
|
|
}
|
|
|
|
qs := []*survey.Question{}
|
|
if _titleF == "" {
|
|
qs = append(qs, titleQuestion)
|
|
}
|
|
if _bodyF == "" {
|
|
qs = append(qs, bodyQuestion)
|
|
}
|
|
|
|
err := survey.Ask(qs, &inProgress)
|
|
if err != nil {
|
|
return fmt.Errorf("could not prompt: %s", err)
|
|
}
|
|
confirmAnswers := struct {
|
|
Confirmation string
|
|
}{}
|
|
confirmQs := []*survey.Question{
|
|
{
|
|
Name: "confirmation",
|
|
Prompt: &survey.Select{
|
|
Message: "Submit?",
|
|
Options: []string{
|
|
"Yes",
|
|
"Edit",
|
|
"Cancel",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
err = survey.Ask(confirmQs, &confirmAnswers)
|
|
if err != nil {
|
|
return fmt.Errorf("could not prompt: %s", err)
|
|
}
|
|
|
|
switch confirmAnswers.Confirmation {
|
|
case "Yes":
|
|
confirmed = true
|
|
case "Edit":
|
|
continue
|
|
case "Cancel":
|
|
fmt.Println(utils.Red("Discarding PR."))
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
title := _titleF
|
|
if title == "" {
|
|
title = inProgress.Title
|
|
}
|
|
body := _bodyF
|
|
if body == "" {
|
|
body = inProgress.Body
|
|
}
|
|
base := _baseF
|
|
if base == "" {
|
|
base = "master"
|
|
}
|
|
|
|
client, err := apiClientForContext(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("could not initialize api client: %s", err)
|
|
}
|
|
|
|
repo, err := ctx.BaseRepo()
|
|
if err != nil {
|
|
return fmt.Errorf("could not determine GitHub repo: %s", err)
|
|
}
|
|
|
|
payload, err := api.CreatePullRequest(client, repo, title, body, _draftF, base, head)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create PR: %s", err)
|
|
}
|
|
|
|
fmt.Println(payload)
|
|
|
|
return nil
|
|
}
|
|
|
|
func guessRemote(ctx context.Context) (string, error) {
|
|
remotes, err := ctx.Remotes()
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not determine suitable remote: %s", err)
|
|
}
|
|
|
|
remote, err := remotes.FindByName("origin", "github")
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not determine suitable remote: %s", err)
|
|
}
|
|
|
|
return remote.Name, nil
|
|
}
|
|
|
|
func determineEditor() string {
|
|
if runtime.GOOS == "windows" {
|
|
return "notepad"
|
|
}
|
|
if v := os.Getenv("VISUAL"); v != "" {
|
|
return v
|
|
}
|
|
if e := os.Getenv("EDITOR"); e != "" {
|
|
return e
|
|
}
|
|
return "nano"
|
|
}
|
|
|
|
var prCreateCmd = &cobra.Command{
|
|
Use: "create",
|
|
Short: "Create a pull request",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ctx := contextForCommand(cmd)
|
|
return prCreate(ctx)
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
prCreateCmd.Flags().BoolVarP(&_draftF, "draft", "d", false,
|
|
"Mark PR as a draft")
|
|
prCreateCmd.Flags().StringVarP(&_titleF, "title", "t", "",
|
|
"Supply a title. Will prompt for one otherwise.")
|
|
prCreateCmd.Flags().StringVarP(&_bodyF, "body", "b", "",
|
|
"Supply a body. Will prompt for one otherwise.")
|
|
prCreateCmd.Flags().StringVarP(&_baseF, "base", "T", "",
|
|
"The branch into which you want your code merged")
|
|
|
|
}
|