Merge pull request #4158 from cli/extensions-ux
Enable `help` for extensions, accept full extension names as argument
This commit is contained in:
commit
a508fee4e1
3 changed files with 84 additions and 6 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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-")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue