Merge pull request #1492 from ShubhankarKG/newConfirmations

New confirmations
This commit is contained in:
Nate Smith 2020-08-25 13:31:47 -05:00 committed by GitHub
commit fc1c800042
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 283 additions and 61 deletions

View file

@ -6,6 +6,7 @@ import (
"path"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/git"
"github.com/cli/cli/internal/config"
@ -23,13 +24,16 @@ type CreateOptions struct {
Config func() (config.Config, error)
IO *iostreams.IOStreams
Name string
Description string
Homepage string
Team string
EnableIssues bool
EnableWiki bool
Public bool
Name string
Description string
Homepage string
Team string
EnableIssues bool
EnableWiki bool
Public bool
Private bool
Internal bool
ConfirmSubmit bool
}
func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command {
@ -78,7 +82,10 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
cmd.Flags().StringVarP(&opts.Team, "team", "t", "", "The name of the organization team to be granted access")
cmd.Flags().BoolVar(&opts.EnableIssues, "enable-issues", true, "Enable issues in the new repository")
cmd.Flags().BoolVar(&opts.EnableWiki, "enable-wiki", true, "Enable wiki in the new repository")
cmd.Flags().BoolVar(&opts.Public, "public", false, "Make the new repository public (default: private)")
cmd.Flags().BoolVar(&opts.Public, "public", false, "Make the new repository public")
cmd.Flags().BoolVar(&opts.Private, "private", false, "Make the new repository private")
cmd.Flags().BoolVar(&opts.Internal, "internal", false, "Make the new repository internal")
cmd.Flags().BoolVarP(&opts.ConfirmSubmit, "confirm", "y", false, "Confirm the submission directly")
return cmd
}
@ -88,7 +95,12 @@ func createRun(opts *CreateOptions) error {
var repoToCreate ghrepo.Interface
isNameAnArg := false
isDescEmpty := opts.Description == ""
isVisibilityPassed := false
if opts.Name != "" {
isNameAnArg = true
if strings.Contains(opts.Name, "/") {
var err error
repoToCreate, err = ghrepo.FromFullName(opts.Name)
@ -105,10 +117,52 @@ func createRun(opts *CreateOptions) error {
repoToCreate = ghrepo.New("", path.Base(projectDir))
}
visibility := "PRIVATE"
enabledFlagCount := 0
visibility := ""
if opts.Public {
enabledFlagCount++
visibility = "PUBLIC"
}
if opts.Private {
enabledFlagCount++
visibility = "PRIVATE"
}
if opts.Internal {
enabledFlagCount++
visibility = "INTERNAL"
}
if enabledFlagCount > 1 {
return fmt.Errorf("expected exactly one of --public, --private, or --internal to be true")
} else if enabledFlagCount == 1 {
isVisibilityPassed = true
}
// Trigger interactive prompt if name is not passed
if !isNameAnArg {
newName, newDesc, newVisibility, err := interactiveRepoCreate(isDescEmpty, isVisibilityPassed, repoToCreate.RepoName())
if err != nil {
return err
}
if newName != "" {
opts.Name = newName
}
if newDesc != "" {
opts.Description = newDesc
}
if newVisibility != "" {
visibility = newVisibility
}
} else {
// Go for a prompt only if visibility isn't passed
if !isVisibilityPassed {
newVisibility, err := getVisibility()
if err != nil {
return nil
}
visibility = newVisibility
}
}
input := repoCreateInput{
Name: repoToCreate.RepoName(),
@ -126,67 +180,186 @@ func createRun(opts *CreateOptions) error {
return err
}
repo, err := repoCreate(httpClient, repoToCreate.RepoHost(), input)
if err != nil {
return err
}
stderr := opts.IO.ErrOut
stdout := opts.IO.Out
isTTY := opts.IO.IsStdoutTTY()
if isTTY {
fmt.Fprintf(stderr, "%s Created repository %s on GitHub\n", utils.GreenCheck(), ghrepo.FullName(repo))
} else {
fmt.Fprintln(stdout, repo.URL)
}
// TODO This is overly wordy and I'd like to streamline this.
cfg, err := opts.Config()
if err != nil {
return err
}
protocol, err := cfg.Get(repo.RepoHost(), "git_protocol")
if err != nil {
return err
}
remoteURL := ghrepo.FormatRemoteURL(repo, protocol)
if projectDirErr == nil {
_, err = git.AddRemote("origin", remoteURL)
createLocalDirectory := opts.ConfirmSubmit
if !opts.ConfirmSubmit {
opts.ConfirmSubmit, err = confirmSubmission(input.Name, input.OwnerID, &opts.ConfirmSubmit)
if err != nil {
return err
}
}
if opts.ConfirmSubmit {
repo, err := repoCreate(httpClient, repoToCreate.RepoHost(), input)
if err != nil {
return err
}
stderr := opts.IO.ErrOut
stdout := opts.IO.Out
greenCheck := utils.Green("✓")
isTTY := opts.IO.IsStdoutTTY()
if isTTY {
fmt.Fprintf(stderr, "%s Added remote %s\n", utils.GreenCheck(), remoteURL)
fmt.Fprintf(stderr, "%s Created repository %s on GitHub\n", greenCheck, ghrepo.FullName(repo))
} else {
fmt.Fprintln(stdout, repo.URL)
}
} else if isTTY {
doSetup := false
err := prompt.Confirm(fmt.Sprintf("Create a local project directory for %s?", ghrepo.FullName(repo)), &doSetup)
// TODO This is overly wordy and I'd like to streamline this.
cfg, err := opts.Config()
if err != nil {
return err
}
if doSetup {
path := repo.Name
gitInit := git.GitCommand("init", path)
gitInit.Stdout = stdout
gitInit.Stderr = stderr
err = run.PrepareCmd(gitInit).Run()
if err != nil {
return err
}
gitRemoteAdd := git.GitCommand("-C", path, "remote", "add", "origin", remoteURL)
gitRemoteAdd.Stdout = stdout
gitRemoteAdd.Stderr = stderr
err = run.PrepareCmd(gitRemoteAdd).Run()
if err != nil {
return err
}
fmt.Fprintf(stderr, "%s Initialized repository in './%s/'\n", utils.GreenCheck(), path)
protocol, err := cfg.Get(repo.RepoHost(), "git_protocol")
if err != nil {
return err
}
remoteURL := ghrepo.FormatRemoteURL(repo, protocol)
if projectDirErr == nil {
_, err = git.AddRemote("origin", remoteURL)
if err != nil {
return err
}
if isTTY {
fmt.Fprintf(stderr, "%s Added remote %s\n", greenCheck, remoteURL)
}
} else if isTTY {
doSetup := createLocalDirectory
if !doSetup {
err := prompt.Confirm(fmt.Sprintf("Create a local project directory for %s?", ghrepo.FullName(repo)), &doSetup)
if err != nil {
return err
}
}
if doSetup {
path := repo.Name
gitInit := git.GitCommand("init", path)
gitInit.Stdout = stdout
gitInit.Stderr = stderr
err = run.PrepareCmd(gitInit).Run()
if err != nil {
return err
}
gitRemoteAdd := git.GitCommand("-C", path, "remote", "add", "origin", remoteURL)
gitRemoteAdd.Stdout = stdout
gitRemoteAdd.Stderr = stderr
err = run.PrepareCmd(gitRemoteAdd).Run()
if err != nil {
return err
}
fmt.Fprintf(stderr, "%s Initialized repository in './%s/'\n", utils.GreenCheck(), path)
}
}
return nil
}
fmt.Fprintln(opts.IO.Out, "Discarding...")
return nil
}
func interactiveRepoCreate(isDescEmpty bool, isVisibilityPassed bool, repoName string) (string, string, string, error) {
qs := []*survey.Question{}
repoOwnerQuestion := &survey.Question{
Name: "repoOwner",
Prompt: &survey.Input{
Message: "Repository name",
Default: repoName,
},
}
qs = append(qs, repoOwnerQuestion)
if isDescEmpty {
repoDescriptionQuestion := &survey.Question{
Name: "repoDescription",
Prompt: &survey.Input{
Message: "Repository description",
},
}
qs = append(qs, repoDescriptionQuestion)
}
if !isVisibilityPassed {
repoVisibilityQuestion := &survey.Question{
Name: "repoVisibility",
Prompt: &survey.Select{
Message: "Visibility",
Options: []string{"Public", "Private", "Internal"},
},
}
qs = append(qs, repoVisibilityQuestion)
}
answers := struct {
RepoOwner string
RepoDescription string
RepoVisibility string
}{}
err := prompt.SurveyAsk(qs, &answers)
if err != nil {
return "", "", "", err
}
return answers.RepoOwner, answers.RepoDescription, strings.ToUpper(answers.RepoVisibility), nil
}
func confirmSubmission(repoName string, repoOwner string, isConfirmFlagPassed *bool) (bool, error) {
qs := []*survey.Question{}
promptString := ""
if repoOwner != "" {
promptString = fmt.Sprintf("This will create '%s/%s' in your current directory. Continue? ", repoOwner, repoName)
} else {
promptString = fmt.Sprintf("This will create '%s' in your current directory. Continue? ", repoName)
}
confirmSubmitQuestion := &survey.Question{
Name: "confirmSubmit",
Prompt: &survey.Confirm{
Message: promptString,
Default: true,
},
}
qs = append(qs, confirmSubmitQuestion)
answer := struct {
ConfirmSubmit bool
}{}
err := prompt.SurveyAsk(qs, &answer)
if err != nil {
return false, err
}
return answer.ConfirmSubmit, nil
}
func getVisibility() (string, error) {
qs := []*survey.Question{}
getVisibilityQuestion := &survey.Question{
Name: "repoVisibility",
Prompt: &survey.Select{
Message: "Visibility",
Options: []string{"Public", "Private", "Internal"},
},
}
qs = append(qs, getVisibilityQuestion)
answer := struct {
RepoVisibility string
}{}
err := prompt.SurveyAsk(qs, &answer)
if err != nil {
return "", err
}
return strings.ToUpper(answer.RepoVisibility), nil
}

View file

@ -14,6 +14,7 @@ import (
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/httpmock"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/pkg/prompt"
"github.com/cli/cli/test"
"github.com/google/shlex"
"github.com/stretchr/testify/assert"
@ -87,6 +88,22 @@ func TestRepoCreate(t *testing.T) {
})
defer restoreCmd()
as, surveyTearDown := prompt.InitAskStubber()
defer surveyTearDown()
as.Stub([]*prompt.QuestionStub{
{
Name: "repoVisibility",
Value: "PRIVATE",
},
})
as.Stub([]*prompt.QuestionStub{
{
Name: "confirmSubmit",
Value: true,
},
})
output, err := runCommand(httpClient, "REPO")
if err != nil {
t.Errorf("error running command `repo create`: %v", err)
@ -153,6 +170,22 @@ func TestRepoCreate_org(t *testing.T) {
})
defer restoreCmd()
as, surveyTearDown := prompt.InitAskStubber()
defer surveyTearDown()
as.Stub([]*prompt.QuestionStub{
{
Name: "repoVisibility",
Value: "PRIVATE",
},
})
as.Stub([]*prompt.QuestionStub{
{
Name: "confirmSubmit",
Value: true,
},
})
output, err := runCommand(httpClient, "ORG/REPO")
if err != nil {
t.Errorf("error running command `repo create`: %v", err)
@ -219,6 +252,22 @@ func TestRepoCreate_orgWithTeam(t *testing.T) {
})
defer restoreCmd()
as, surveyTearDown := prompt.InitAskStubber()
defer surveyTearDown()
as.Stub([]*prompt.QuestionStub{
{
Name: "repoVisibility",
Value: "PRIVATE",
},
})
as.Stub([]*prompt.QuestionStub{
{
Name: "confirmSubmit",
Value: true,
},
})
output, err := runCommand(httpClient, "ORG/REPO --team monkeys")
if err != nil {
t.Errorf("error running command `repo create`: %v", err)