Fix repo create regressions (#4904)

This commit is contained in:
Mislav Marohnić 2021-12-15 19:05:04 +01:00 committed by GitHub
commit f588aec7f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 128 additions and 57 deletions

View file

@ -45,10 +45,6 @@ type CreateOptions struct {
DisableIssues bool
DisableWiki bool
Interactive bool
ConfirmSubmit bool
EnableIssues bool
EnableWiki bool
}
func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command {
@ -58,6 +54,9 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
Config: f.Config,
}
var enableIssues bool
var enableWiki bool
cmd := &cobra.Command{
Use: "create [<name>]",
Short: "Create a new repository",
@ -135,10 +134,10 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
}
if cmd.Flags().Changed("enable-issues") {
opts.DisableIssues = !opts.EnableIssues
opts.DisableIssues = !enableIssues
}
if cmd.Flags().Changed("enable-wiki") {
opts.DisableWiki = !opts.EnableWiki
opts.DisableWiki = !enableWiki
}
if opts.Template != "" && (opts.Homepage != "" || opts.Team != "" || opts.DisableIssues || opts.DisableWiki) {
return cmdutil.FlagErrorf("the `--template` option is not supported with `--homepage`, `--team`, `--disable-issues`, or `--disable-wiki`")
@ -168,9 +167,9 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
cmd.Flags().BoolVar(&opts.DisableWiki, "disable-wiki", false, "Disable wiki in the new repository")
// deprecated flags
cmd.Flags().BoolVarP(&opts.ConfirmSubmit, "confirm", "y", false, "Skip the confirmation prompt")
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().BoolP("confirm", "y", false, "Skip the confirmation prompt")
cmd.Flags().BoolVar(&enableIssues, "enable-issues", true, "Enable issues in the new repository")
cmd.Flags().BoolVar(&enableWiki, "enable-wiki", true, "Enable wiki in the new repository")
_ = cmd.Flags().MarkDeprecated("confirm", "Pass any argument to skip confirmation prompt")
_ = cmd.Flags().MarkDeprecated("enable-issues", "Disable issues with `--disable-issues`")
@ -224,31 +223,27 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
}
func createRun(opts *CreateOptions) error {
var fromScratch bool
modeOptions := []string{
"Create a new repository on GitHub from scratch",
"Push an existing local repository to GitHub"}
fromScratch := opts.Source == ""
if opts.Interactive {
var createMode string
createModePrompt := &survey.Select{
var selectedMode string
modeOptions := []string{
"Create a new repository on GitHub from scratch",
"Push an existing local repository to GitHub",
}
if err := prompt.SurveyAskOne(&survey.Select{
Message: "What would you like to do?",
Options: modeOptions,
}
err := prompt.SurveyAskOne(createModePrompt, &createMode)
if err != nil {
}, &selectedMode); err != nil {
return err
}
fromScratch = createMode == modeOptions[0]
} else {
fromScratch = opts.Source == ""
fromScratch = selectedMode == modeOptions[0]
}
if fromScratch {
return createFromScratch(opts)
} else {
return createFromLocal(opts)
}
return createFromLocal(opts)
}
// create new repo on remote host
@ -282,6 +277,10 @@ func createFromScratch(opts *CreateOptions) error {
if err != nil {
return err
}
if err := confirmSubmission(opts.Name, opts.Visibility); err != nil {
return err
}
}
if strings.Contains(opts.Name, "/") {
@ -339,16 +338,6 @@ func createFromScratch(opts *CreateOptions) error {
return err
}
if opts.Interactive {
doCreate, err := confirmSubmission(opts.Name, repoToCreate.RepoOwner(), opts.Visibility)
if err != nil {
return err
}
if !doCreate {
return cmdutil.CancelError
}
}
cs := opts.IO.ColorScheme()
isTTY := opts.IO.IsStdoutTTY()
if isTTY {
@ -356,6 +345,8 @@ func createFromScratch(opts *CreateOptions) error {
"%s Created repository %s on GitHub\n",
cs.SuccessIconWithColor(cs.Green),
ghrepo.FullName(repo))
} else {
fmt.Fprintln(opts.IO.Out, repo.URL)
}
if opts.Interactive {
@ -503,6 +494,8 @@ func createFromLocal(opts *CreateOptions) error {
"%s Created repository %s on GitHub\n",
cs.SuccessIconWithColor(cs.Green),
ghrepo.FullName(repo))
} else {
fmt.Fprintln(stdout, repo.URL)
}
protocol, err := cfg.Get(repo.RepoHost(), "git_protocol")
@ -783,13 +776,13 @@ func interactiveRepoInfo(defaultName string) (string, string, string, error) {
{
Name: "repoName",
Prompt: &survey.Input{
Message: "Repository Name: ",
Message: "Repository name",
Default: defaultName,
},
},
{
Name: "repoDescription",
Prompt: &survey.Input{Message: "Description: "},
Prompt: &survey.Input{Message: "Description"},
},
{
Name: "repoVisibility",
@ -816,7 +809,7 @@ func interactiveRepoInfo(defaultName string) (string, string, string, error) {
func interactiveSource() (string, error) {
var sourcePath string
sourcePrompt := &survey.Input{
Message: "Path to local repository: ",
Message: "Path to local repository",
Default: "."}
err := prompt.SurveyAskOne(sourcePrompt, &sourcePath)
@ -826,33 +819,28 @@ func interactiveSource() (string, error) {
return sourcePath, nil
}
func confirmSubmission(repoName, repoOwner, visibility string) (bool, error) {
qs := []*survey.Question{}
targetRepo := normalizeRepoName(repoName)
if repoOwner != "" {
targetRepo = fmt.Sprintf("%s/%s", repoOwner, targetRepo)
func confirmSubmission(repoWithOwner, visibility string) error {
targetRepo := normalizeRepoName(repoWithOwner)
if idx := strings.IndexRune(repoWithOwner, '/'); idx > 0 {
targetRepo = repoWithOwner[0:idx+1] + normalizeRepoName(repoWithOwner[idx+1:])
}
promptString := fmt.Sprintf(`This will create "%s" as a %s repository on GitHub. Continue?`, targetRepo, strings.ToLower(visibility))
confirmSubmitQuestion := &survey.Question{
var answer struct {
ConfirmSubmit bool
}
err := prompt.SurveyAsk([]*survey.Question{{
Name: "confirmSubmit",
Prompt: &survey.Confirm{
Message: promptString,
Message: fmt.Sprintf(`This will create "%s" as a %s repository on GitHub. Continue?`, targetRepo, strings.ToLower(visibility)),
Default: true,
},
}
qs = append(qs, confirmSubmitQuestion)
answer := struct {
ConfirmSubmit bool
}{}
err := prompt.SurveyAsk(qs, &answer)
}}, &answer)
if err != nil {
return false, err
return err
}
return answer.ConfirmSubmit, nil
if !answer.ConfirmSubmit {
return cmdutil.CancelError
}
return nil
}
// normalizeRepoName takes in the repo name the user inputted and normalizes it using the same logic as GitHub (GitHub.com/new)

View file

@ -205,6 +205,28 @@ func Test_createRun(t *testing.T) {
cs.Register(`git clone https://github.com/OWNER/REPO.git`, 0, "")
},
},
{
name: "interactive create from scratch but cancel before submit",
opts: &CreateOptions{Interactive: true},
tty: true,
askStubs: func(as *prompt.AskStubber) {
as.StubOne("Create a new repository on GitHub from scratch")
as.Stub([]*prompt.QuestionStub{
{Name: "repoName", Value: "REPO"},
{Name: "repoDescription", Value: "my new repo"},
{Name: "repoVisibility", Value: "PRIVATE"},
})
as.Stub([]*prompt.QuestionStub{
{Name: "addGitIgnore", Value: false}})
as.Stub([]*prompt.QuestionStub{
{Name: "addLicense", Value: false}})
as.Stub([]*prompt.QuestionStub{
{Name: "confirmSubmit", Value: false}})
},
wantStdout: "",
wantErr: true,
errMsg: "CancelError",
},
{
name: "interactive with existing repository public",
opts: &CreateOptions{Interactive: true},
@ -323,6 +345,66 @@ func Test_createRun(t *testing.T) {
},
wantStdout: "✓ Created repository OWNER/REPO on GitHub\n✓ Added remote https://github.com/OWNER/REPO.git\n✓ Pushed commits to https://github.com/OWNER/REPO.git\n",
},
{
name: "noninteractive create from scratch",
opts: &CreateOptions{
Interactive: false,
Name: "REPO",
Visibility: "PRIVATE",
},
tty: false,
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`mutation RepositoryCreate\b`),
httpmock.StringResponse(`
{
"data": {
"createRepository": {
"repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login":"OWNER"},
"url": "https://github.com/OWNER/REPO"
}
}
}
}`))
},
wantStdout: "https://github.com/OWNER/REPO\n",
},
{
name: "noninteractive create from source",
opts: &CreateOptions{
Interactive: false,
Source: ".",
Name: "REPO",
Visibility: "PRIVATE",
},
tty: false,
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`mutation RepositoryCreate\b`),
httpmock.StringResponse(`
{
"data": {
"createRepository": {
"repository": {
"id": "REPOID",
"name": "REPO",
"owner": {"login":"OWNER"},
"url": "https://github.com/OWNER/REPO"
}
}
}
}`))
},
execStubs: func(cs *run.CommandStubber) {
cs.Register(`git -C . rev-parse --git-dir`, 0, ".git")
cs.Register(`git -C . rev-parse HEAD`, 0, "commithash")
cs.Register(`git -C . remote add origin https://github.com/OWNER/REPO`, 0, "")
},
wantStdout: "https://github.com/OWNER/REPO\n",
},
}
for _, tt := range tests {
q, teardown := prompt.InitAskStubber()
@ -348,7 +430,7 @@ func Test_createRun(t *testing.T) {
tt.execStubs(cs)
}
io, _, stdout, _ := iostreams.Test()
io, _, stdout, stderr := iostreams.Test()
io.SetStdinTTY(tt.tty)
io.SetStdoutTTY(tt.tty)
tt.opts.IO = io
@ -363,6 +445,7 @@ func Test_createRun(t *testing.T) {
}
assert.NoError(t, err)
assert.Equal(t, tt.wantStdout, stdout.String())
assert.Equal(t, "", stderr.String())
})
}
}