Skip to content

Commit f588aec

Browse files
authored
Fix repo create regressions (cli#4904)
2 parents 4bbbf46 + 5cd977e commit f588aec

File tree

2 files changed

+128
-57
lines changed

2 files changed

+128
-57
lines changed

pkg/cmd/repo/create/create.go

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ type CreateOptions struct {
4545
DisableIssues bool
4646
DisableWiki bool
4747
Interactive bool
48-
49-
ConfirmSubmit bool
50-
EnableIssues bool
51-
EnableWiki bool
5248
}
5349

5450
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
5854
Config: f.Config,
5955
}
6056

57+
var enableIssues bool
58+
var enableWiki bool
59+
6160
cmd := &cobra.Command{
6261
Use: "create [<name>]",
6362
Short: "Create a new repository",
@@ -135,10 +134,10 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
135134
}
136135

137136
if cmd.Flags().Changed("enable-issues") {
138-
opts.DisableIssues = !opts.EnableIssues
137+
opts.DisableIssues = !enableIssues
139138
}
140139
if cmd.Flags().Changed("enable-wiki") {
141-
opts.DisableWiki = !opts.EnableWiki
140+
opts.DisableWiki = !enableWiki
142141
}
143142
if opts.Template != "" && (opts.Homepage != "" || opts.Team != "" || opts.DisableIssues || opts.DisableWiki) {
144143
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
168167
cmd.Flags().BoolVar(&opts.DisableWiki, "disable-wiki", false, "Disable wiki in the new repository")
169168

170169
// deprecated flags
171-
cmd.Flags().BoolVarP(&opts.ConfirmSubmit, "confirm", "y", false, "Skip the confirmation prompt")
172-
cmd.Flags().BoolVar(&opts.EnableIssues, "enable-issues", true, "Enable issues in the new repository")
173-
cmd.Flags().BoolVar(&opts.EnableWiki, "enable-wiki", true, "Enable wiki in the new repository")
170+
cmd.Flags().BoolP("confirm", "y", false, "Skip the confirmation prompt")
171+
cmd.Flags().BoolVar(&enableIssues, "enable-issues", true, "Enable issues in the new repository")
172+
cmd.Flags().BoolVar(&enableWiki, "enable-wiki", true, "Enable wiki in the new repository")
174173

175174
_ = cmd.Flags().MarkDeprecated("confirm", "Pass any argument to skip confirmation prompt")
176175
_ = 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
224223
}
225224

226225
func createRun(opts *CreateOptions) error {
227-
var fromScratch bool
228-
modeOptions := []string{
229-
"Create a new repository on GitHub from scratch",
230-
"Push an existing local repository to GitHub"}
226+
fromScratch := opts.Source == ""
231227

232228
if opts.Interactive {
233-
var createMode string
234-
createModePrompt := &survey.Select{
229+
var selectedMode string
230+
modeOptions := []string{
231+
"Create a new repository on GitHub from scratch",
232+
"Push an existing local repository to GitHub",
233+
}
234+
if err := prompt.SurveyAskOne(&survey.Select{
235235
Message: "What would you like to do?",
236236
Options: modeOptions,
237-
}
238-
err := prompt.SurveyAskOne(createModePrompt, &createMode)
239-
if err != nil {
237+
}, &selectedMode); err != nil {
240238
return err
241239
}
242-
fromScratch = createMode == modeOptions[0]
243-
} else {
244-
fromScratch = opts.Source == ""
240+
fromScratch = selectedMode == modeOptions[0]
245241
}
246242

247243
if fromScratch {
248244
return createFromScratch(opts)
249-
} else {
250-
return createFromLocal(opts)
251245
}
246+
return createFromLocal(opts)
252247
}
253248

254249
// create new repo on remote host
@@ -282,6 +277,10 @@ func createFromScratch(opts *CreateOptions) error {
282277
if err != nil {
283278
return err
284279
}
280+
281+
if err := confirmSubmission(opts.Name, opts.Visibility); err != nil {
282+
return err
283+
}
285284
}
286285

287286
if strings.Contains(opts.Name, "/") {
@@ -339,23 +338,15 @@ func createFromScratch(opts *CreateOptions) error {
339338
return err
340339
}
341340

342-
if opts.Interactive {
343-
doCreate, err := confirmSubmission(opts.Name, repoToCreate.RepoOwner(), opts.Visibility)
344-
if err != nil {
345-
return err
346-
}
347-
if !doCreate {
348-
return cmdutil.CancelError
349-
}
350-
}
351-
352341
cs := opts.IO.ColorScheme()
353342
isTTY := opts.IO.IsStdoutTTY()
354343
if isTTY {
355344
fmt.Fprintf(opts.IO.Out,
356345
"%s Created repository %s on GitHub\n",
357346
cs.SuccessIconWithColor(cs.Green),
358347
ghrepo.FullName(repo))
348+
} else {
349+
fmt.Fprintln(opts.IO.Out, repo.URL)
359350
}
360351

361352
if opts.Interactive {
@@ -503,6 +494,8 @@ func createFromLocal(opts *CreateOptions) error {
503494
"%s Created repository %s on GitHub\n",
504495
cs.SuccessIconWithColor(cs.Green),
505496
ghrepo.FullName(repo))
497+
} else {
498+
fmt.Fprintln(stdout, repo.URL)
506499
}
507500

508501
protocol, err := cfg.Get(repo.RepoHost(), "git_protocol")
@@ -783,13 +776,13 @@ func interactiveRepoInfo(defaultName string) (string, string, string, error) {
783776
{
784777
Name: "repoName",
785778
Prompt: &survey.Input{
786-
Message: "Repository Name: ",
779+
Message: "Repository name",
787780
Default: defaultName,
788781
},
789782
},
790783
{
791784
Name: "repoDescription",
792-
Prompt: &survey.Input{Message: "Description: "},
785+
Prompt: &survey.Input{Message: "Description"},
793786
},
794787
{
795788
Name: "repoVisibility",
@@ -816,7 +809,7 @@ func interactiveRepoInfo(defaultName string) (string, string, string, error) {
816809
func interactiveSource() (string, error) {
817810
var sourcePath string
818811
sourcePrompt := &survey.Input{
819-
Message: "Path to local repository: ",
812+
Message: "Path to local repository",
820813
Default: "."}
821814

822815
err := prompt.SurveyAskOne(sourcePrompt, &sourcePath)
@@ -826,33 +819,28 @@ func interactiveSource() (string, error) {
826819
return sourcePath, nil
827820
}
828821

829-
func confirmSubmission(repoName, repoOwner, visibility string) (bool, error) {
830-
qs := []*survey.Question{}
831-
targetRepo := normalizeRepoName(repoName)
832-
if repoOwner != "" {
833-
targetRepo = fmt.Sprintf("%s/%s", repoOwner, targetRepo)
822+
func confirmSubmission(repoWithOwner, visibility string) error {
823+
targetRepo := normalizeRepoName(repoWithOwner)
824+
if idx := strings.IndexRune(repoWithOwner, '/'); idx > 0 {
825+
targetRepo = repoWithOwner[0:idx+1] + normalizeRepoName(repoWithOwner[idx+1:])
834826
}
835-
promptString := fmt.Sprintf(`This will create "%s" as a %s repository on GitHub. Continue?`, targetRepo, strings.ToLower(visibility))
836-
837-
confirmSubmitQuestion := &survey.Question{
827+
var answer struct {
828+
ConfirmSubmit bool
829+
}
830+
err := prompt.SurveyAsk([]*survey.Question{{
838831
Name: "confirmSubmit",
839832
Prompt: &survey.Confirm{
840-
Message: promptString,
833+
Message: fmt.Sprintf(`This will create "%s" as a %s repository on GitHub. Continue?`, targetRepo, strings.ToLower(visibility)),
841834
Default: true,
842835
},
843-
}
844-
qs = append(qs, confirmSubmitQuestion)
845-
846-
answer := struct {
847-
ConfirmSubmit bool
848-
}{}
849-
850-
err := prompt.SurveyAsk(qs, &answer)
836+
}}, &answer)
851837
if err != nil {
852-
return false, err
838+
return err
853839
}
854-
855-
return answer.ConfirmSubmit, nil
840+
if !answer.ConfirmSubmit {
841+
return cmdutil.CancelError
842+
}
843+
return nil
856844
}
857845

858846
// normalizeRepoName takes in the repo name the user inputted and normalizes it using the same logic as GitHub (GitHub.com/new)

pkg/cmd/repo/create/create_test.go

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,28 @@ func Test_createRun(t *testing.T) {
205205
cs.Register(`git clone https://github.com/OWNER/REPO.git`, 0, "")
206206
},
207207
},
208+
{
209+
name: "interactive create from scratch but cancel before submit",
210+
opts: &CreateOptions{Interactive: true},
211+
tty: true,
212+
askStubs: func(as *prompt.AskStubber) {
213+
as.StubOne("Create a new repository on GitHub from scratch")
214+
as.Stub([]*prompt.QuestionStub{
215+
{Name: "repoName", Value: "REPO"},
216+
{Name: "repoDescription", Value: "my new repo"},
217+
{Name: "repoVisibility", Value: "PRIVATE"},
218+
})
219+
as.Stub([]*prompt.QuestionStub{
220+
{Name: "addGitIgnore", Value: false}})
221+
as.Stub([]*prompt.QuestionStub{
222+
{Name: "addLicense", Value: false}})
223+
as.Stub([]*prompt.QuestionStub{
224+
{Name: "confirmSubmit", Value: false}})
225+
},
226+
wantStdout: "",
227+
wantErr: true,
228+
errMsg: "CancelError",
229+
},
208230
{
209231
name: "interactive with existing repository public",
210232
opts: &CreateOptions{Interactive: true},
@@ -323,6 +345,66 @@ func Test_createRun(t *testing.T) {
323345
},
324346
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",
325347
},
348+
{
349+
name: "noninteractive create from scratch",
350+
opts: &CreateOptions{
351+
Interactive: false,
352+
Name: "REPO",
353+
Visibility: "PRIVATE",
354+
},
355+
tty: false,
356+
httpStubs: func(reg *httpmock.Registry) {
357+
reg.Register(
358+
httpmock.GraphQL(`mutation RepositoryCreate\b`),
359+
httpmock.StringResponse(`
360+
{
361+
"data": {
362+
"createRepository": {
363+
"repository": {
364+
"id": "REPOID",
365+
"name": "REPO",
366+
"owner": {"login":"OWNER"},
367+
"url": "https://github.com/OWNER/REPO"
368+
}
369+
}
370+
}
371+
}`))
372+
},
373+
wantStdout: "https://github.com/OWNER/REPO\n",
374+
},
375+
{
376+
name: "noninteractive create from source",
377+
opts: &CreateOptions{
378+
Interactive: false,
379+
Source: ".",
380+
Name: "REPO",
381+
Visibility: "PRIVATE",
382+
},
383+
tty: false,
384+
httpStubs: func(reg *httpmock.Registry) {
385+
reg.Register(
386+
httpmock.GraphQL(`mutation RepositoryCreate\b`),
387+
httpmock.StringResponse(`
388+
{
389+
"data": {
390+
"createRepository": {
391+
"repository": {
392+
"id": "REPOID",
393+
"name": "REPO",
394+
"owner": {"login":"OWNER"},
395+
"url": "https://github.com/OWNER/REPO"
396+
}
397+
}
398+
}
399+
}`))
400+
},
401+
execStubs: func(cs *run.CommandStubber) {
402+
cs.Register(`git -C . rev-parse --git-dir`, 0, ".git")
403+
cs.Register(`git -C . rev-parse HEAD`, 0, "commithash")
404+
cs.Register(`git -C . remote add origin https://github.com/OWNER/REPO`, 0, "")
405+
},
406+
wantStdout: "https://github.com/OWNER/REPO\n",
407+
},
326408
}
327409
for _, tt := range tests {
328410
q, teardown := prompt.InitAskStubber()
@@ -348,7 +430,7 @@ func Test_createRun(t *testing.T) {
348430
tt.execStubs(cs)
349431
}
350432

351-
io, _, stdout, _ := iostreams.Test()
433+
io, _, stdout, stderr := iostreams.Test()
352434
io.SetStdinTTY(tt.tty)
353435
io.SetStdoutTTY(tt.tty)
354436
tt.opts.IO = io
@@ -363,6 +445,7 @@ func Test_createRun(t *testing.T) {
363445
}
364446
assert.NoError(t, err)
365447
assert.Equal(t, tt.wantStdout, stdout.String())
448+
assert.Equal(t, "", stderr.String())
366449
})
367450
}
368451
}

0 commit comments

Comments
 (0)