Merge pull request #4158 from cli/extensions-ux

Enable `help` for extensions, accept full extension names as argument
This commit is contained in:
Mislav Marohnić 2021-08-23 12:45:22 +02:00 committed by GitHub
commit a508fee4e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 6 deletions

View file

@ -102,12 +102,17 @@ func mainRun() exitCode {
expandedArgs = os.Args[1:]
}
cmd, _, err := rootCmd.Traverse(expandedArgs)
if err != nil || cmd == rootCmd {
// translate `gh help <command>` to `gh <command> --help` for extensions
if len(expandedArgs) == 2 && expandedArgs[0] == "help" && !hasCommand(rootCmd, expandedArgs[1:]) {
expandedArgs = []string{expandedArgs[1], "--help"}
}
if !hasCommand(rootCmd, expandedArgs) {
originalArgs := expandedArgs
isShell := false
expandedArgs, isShell, err = expand.ExpandAlias(cfg, os.Args, nil)
argsForExpansion := append([]string{"gh"}, expandedArgs...)
expandedArgs, isShell, err = expand.ExpandAlias(cfg, argsForExpansion, nil)
if err != nil {
fmt.Fprintf(stderr, "failed to process aliases: %s\n", err)
return exitError
@ -141,7 +146,7 @@ func mainRun() exitCode {
}
return exitOK
} else if c, _, err := rootCmd.Traverse(expandedArgs); err == nil && c == rootCmd && len(expandedArgs) > 0 {
} else if len(expandedArgs) > 0 && !hasCommand(rootCmd, expandedArgs) {
extensionManager := cmdFactory.ExtensionManager
if found, err := extensionManager.Dispatch(expandedArgs, os.Stdin, os.Stdout, os.Stderr); err != nil {
var execError *exec.ExitError
@ -244,6 +249,12 @@ func mainRun() exitCode {
return exitOK
}
// hasCommand returns true if args resolve to a built-in command
func hasCommand(rootCmd *cobra.Command, args []string) bool {
c, _, err := rootCmd.Traverse(args)
return err == nil && c != rootCmd
}
func printError(out io.Writer, err error, cmd *cobra.Command, debug bool) {
var dnsError *net.DNSError
if errors.As(err, &dnsError) {

View file

@ -116,7 +116,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
var name string
if len(args) > 0 {
name = args[0]
name = normalizeExtensionSelector(args[0])
}
return m.Upgrade(name, flagForce, io.Out, io.ErrOut)
},
@ -130,7 +130,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
Short: "Remove an installed extension",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
extName := args[0]
extName := normalizeExtensionSelector(args[0])
if err := m.Remove(extName); err != nil {
return err
}
@ -167,3 +167,10 @@ func checkValidExtension(rootCmd *cobra.Command, m extensions.ExtensionManager,
return nil
}
func normalizeExtensionSelector(n string) string {
if idx := strings.IndexRune(n, '/'); idx >= 0 {
n = n[idx+1:]
}
return strings.TrimPrefix(n, "gh-")
}

View file

@ -100,6 +100,34 @@ func TestNewCmdExtension(t *testing.T) {
}
},
},
{
name: "upgrade an extension gh-prefix",
args: []string{"upgrade", "gh-hello"},
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
em.UpgradeFunc = func(name string, force bool, out, errOut io.Writer) error {
return nil
}
return func(t *testing.T) {
calls := em.UpgradeCalls()
assert.Equal(t, 1, len(calls))
assert.Equal(t, "hello", calls[0].Name)
}
},
},
{
name: "upgrade an extension full name",
args: []string{"upgrade", "monalisa/gh-hello"},
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
em.UpgradeFunc = func(name string, force bool, out, errOut io.Writer) error {
return nil
}
return func(t *testing.T) {
calls := em.UpgradeCalls()
assert.Equal(t, 1, len(calls))
assert.Equal(t, "hello", calls[0].Name)
}
},
},
{
name: "upgrade all",
args: []string{"upgrade", "--all"},
@ -146,6 +174,38 @@ func TestNewCmdExtension(t *testing.T) {
isTTY: false,
wantStdout: "",
},
{
name: "remove extension gh-prefix",
args: []string{"remove", "gh-hello"},
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
em.RemoveFunc = func(name string) error {
return nil
}
return func(t *testing.T) {
calls := em.RemoveCalls()
assert.Equal(t, 1, len(calls))
assert.Equal(t, "hello", calls[0].Name)
}
},
isTTY: false,
wantStdout: "",
},
{
name: "remove extension full name",
args: []string{"remove", "monalisa/gh-hello"},
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
em.RemoveFunc = func(name string) error {
return nil
}
return func(t *testing.T) {
calls := em.RemoveCalls()
assert.Equal(t, 1, len(calls))
assert.Equal(t, "hello", calls[0].Name)
}
},
isTTY: false,
wantStdout: "",
},
{
name: "list extensions",
args: []string{"list"},