@@ -4,21 +4,32 @@ import (
44 "errors"
55 "fmt"
66 "os"
7- "path/filepath"
87 "strings"
98
9+ "github.com/MakeNowJust/heredoc"
10+ "github.com/cli/cli/git"
1011 "github.com/cli/cli/internal/ghrepo"
1112 "github.com/cli/cli/pkg/cmdutil"
12- "github.com/cli/cli/pkg/iostreams "
13+ "github.com/cli/cli/utils "
1314 "github.com/spf13/cobra"
1415)
1516
16- func NewCmdExtensions (io * iostreams.IOStreams ) * cobra.Command {
17- m := NewManager ()
17+ func NewCmdExtensions (f * cmdutil.Factory ) * cobra.Command {
18+ m := f .ExtensionManager
19+ io := f .IOStreams
1820
1921 extCmd := cobra.Command {
2022 Use : "extensions" ,
2123 Short : "Manage gh extensions" ,
24+ Long : heredoc .Docf (`
25+ GitHub CLI extensions are repositories that provide additional gh commands.
26+
27+ The name of the extension repository must start with "gh-" and it must contain an
28+ executable of the same name. All arguments passed to the %[1]sgh <extname>%[1]s invocation
29+ will be forwarded to the %[1]sgh-<extname>%[1]s executable of the extension.
30+
31+ An extension cannot override any of the core gh commands.
32+ ` , "`" ),
2233 }
2334
2435 extCmd .AddCommand (
@@ -31,12 +42,23 @@ func NewCmdExtensions(io *iostreams.IOStreams) *cobra.Command {
3142 if len (cmds ) == 0 {
3243 return errors .New ("no extensions installed" )
3344 }
45+ // cs := io.ColorScheme()
46+ t := utils .NewTablePrinter (io )
3447 for _ , c := range cmds {
35- name := filepath .Base (c )
36- parts := strings .SplitN (name , "-" , 2 )
37- fmt .Fprintf (io .Out , "%s %s\n " , parts [0 ], parts [1 ])
48+ var repo string
49+ if u , err := git .ParseURL (c .URL ()); err == nil {
50+ if r , err := ghrepo .FromURL (u ); err == nil {
51+ repo = ghrepo .FullName (r )
52+ }
53+ }
54+
55+ t .AddField (fmt .Sprintf ("gh %s" , c .Name ()), nil , nil )
56+ t .AddField (repo , nil , nil )
57+ // TODO: add notice about available update
58+ //t.AddField("Update available", nil, cs.Green)
59+ t .EndRow ()
3860 }
39- return nil
61+ return t . Render ()
4062 },
4163 },
4264 & cobra.Command {
@@ -58,16 +80,48 @@ func NewCmdExtensions(io *iostreams.IOStreams) *cobra.Command {
5880 if ! strings .HasPrefix (repo .RepoName (), "gh-" ) {
5981 return errors .New ("the repository name must start with `gh-`" )
6082 }
61- protocol := "https" // TODO: respect user's preferred protocol
83+ cfg , err := f .Config ()
84+ if err != nil {
85+ return err
86+ }
87+ protocol , _ := cfg .Get (repo .RepoHost (), "git_protocol" )
6288 return m .Install (ghrepo .FormatRemoteURL (repo , protocol ), io .Out , io .ErrOut )
6389 },
6490 },
91+ func () * cobra.Command {
92+ var flagAll bool
93+ cmd := & cobra.Command {
94+ Use : "upgrade {<name> | --all}" ,
95+ Short : "Upgrade installed extensions" ,
96+ Args : func (cmd * cobra.Command , args []string ) error {
97+ if len (args ) == 0 && ! flagAll {
98+ return & cmdutil.FlagError {Err : errors .New ("must specify an extension to upgrade" )}
99+ }
100+ if len (args ) > 0 && flagAll {
101+ return & cmdutil.FlagError {Err : errors .New ("cannot use `--all` with extension name" )}
102+ }
103+ if len (args ) > 1 {
104+ return & cmdutil.FlagError {Err : errors .New ("too many arguments" )}
105+ }
106+ return nil
107+ },
108+ RunE : func (cmd * cobra.Command , args []string ) error {
109+ var name string
110+ if len (args ) > 0 {
111+ name = args [0 ]
112+ }
113+ return m .Upgrade (name , io .Out , io .ErrOut )
114+ },
115+ }
116+ cmd .Flags ().BoolVar (& flagAll , "all" , false , "Upgrade all extensions" )
117+ return cmd
118+ }(),
65119 & cobra.Command {
66- Use : "upgrade " ,
67- Short : "Upgrade installed extensions " ,
68- Args : cobra .NoArgs ,
120+ Use : "remove " ,
121+ Short : "Remove an installed extension " ,
122+ Args : cobra .ExactArgs ( 1 ) ,
69123 RunE : func (cmd * cobra.Command , args []string ) error {
70- return m .Upgrade ( io . Out , io . ErrOut )
124+ return m .Remove ( args [ 0 ] )
71125 },
72126 },
73127 )
0 commit comments