Fix repo create regressions (#4904)
This commit is contained in:
commit
f588aec7f3
2 changed files with 128 additions and 57 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue