gh auth login: add git protocol flag (#5158)

Co-authored-by: Mislav Marohnić <mislav@github.com>
This commit is contained in:
Jonathan Mayer 2022-02-17 11:35:59 -08:00 committed by GitHub
parent f4b4a4e18f
commit 1eefda0b45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 9 deletions

View file

@ -27,10 +27,11 @@ type LoginOptions struct {
Interactive bool
Hostname string
Scopes []string
Token string
Web bool
Hostname string
Scopes []string
Token string
Web bool
GitProtocol string
}
func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Command {
@ -54,8 +55,8 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
Alternatively, pass in a token on standard input by using %[1]s--with-token%[1]s.
The minimum required scopes for the token are: "repo", "read:org".
The --scopes flag accepts a comma separated list of scopes you want your gh credentials to have. If
absent, this command ensures that gh has access to a minimum set of scopes.
The %[1]s--scopes%[1]s flag accepts a comma separated list of scopes you want your gh credentials to
have. If absent, this command ensures that gh has access to a minimum set of scopes.
`, "`"),
Example: heredoc.Doc(`
# start interactive setup
@ -64,7 +65,7 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
# authenticate against github.com by reading the token from a file
$ gh auth login --with-token < mytoken.txt
# authenticate with a specific GitHub Enterprise Server instance
# authenticate with a specific GitHub instance
$ gh auth login --hostname enterprise.internal
`),
RunE: func(cmd *cobra.Command, args []string) error {
@ -111,6 +112,7 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
cmd.Flags().StringSliceVarP(&opts.Scopes, "scopes", "s", nil, "Additional authentication scopes for gh to have")
cmd.Flags().BoolVar(&tokenStdin, "with-token", false, "Read token from standard input")
cmd.Flags().BoolVarP(&opts.Web, "web", "w", false, "Open a browser to authenticate")
cmdutil.StringEnumFlag(cmd, &opts.GitProtocol, "git-protocol", "p", "", []string{"ssh", "https"}, "The protocol to use for git operations")
return cmd
}
@ -186,6 +188,7 @@ func loginRun(opts *LoginOptions) error {
Web: opts.Web,
Scopes: opts.Scopes,
Executable: opts.MainExecutable,
GitProtocol: opts.GitProtocol,
})
}

View file

@ -29,6 +29,7 @@ type LoginOptions struct {
Web bool
Scopes []string
Executable string
GitProtocol string
sshContext sshContext
}
@ -39,8 +40,8 @@ func Login(opts *LoginOptions) error {
httpClient := opts.HTTPClient
cs := opts.IO.ColorScheme()
var gitProtocol string
if opts.Interactive {
gitProtocol := strings.ToLower(opts.GitProtocol)
if opts.Interactive && gitProtocol == "" {
var proto string
err := prompt.SurveyAskOne(&survey.Select{
Message: "What is your preferred protocol for Git operations?",

View file

@ -1,7 +1,9 @@
package cmdutil
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@ -21,6 +23,20 @@ func NilBoolFlag(cmd *cobra.Command, p **bool, name string, shorthand string, us
return f
}
// StringEnumFlag defines a new string flag that only allows values listed in options.
func StringEnumFlag(cmd *cobra.Command, p *string, name, shorthand, defaultValue string, options []string, usage string) *pflag.Flag {
val := &enumValue{string: p, options: options}
f := cmd.Flags().VarPF(val, name, shorthand, fmt.Sprintf("%s: %s", usage, formatValuesForUsageDocs(options)))
_ = cmd.RegisterFlagCompletionFunc(name, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return options, cobra.ShellCompDirectiveNoFileComp
})
return f
}
func formatValuesForUsageDocs(values []string) string {
return fmt.Sprintf("{%s}", strings.Join(values, "|"))
}
type stringValue struct {
string **string
}
@ -75,3 +91,31 @@ func (b *boolValue) Type() string {
func (b *boolValue) IsBoolFlag() bool {
return true
}
type enumValue struct {
string *string
options []string
}
func (e *enumValue) Set(value string) error {
found := false
for _, opt := range e.options {
if strings.EqualFold(opt, value) {
found = true
break
}
}
if !found {
return fmt.Errorf("valid values are %s", formatValuesForUsageDocs(e.options))
}
*e.string = value
return nil
}
func (e *enumValue) String() string {
return *e.string
}
func (e *enumValue) Type() string {
return "string"
}