X Tutup
Skip to content

Commit e70bdbf

Browse files
committed
Add update checking to extensions list
1 parent 3ff94ae commit e70bdbf

File tree

6 files changed

+114
-25
lines changed

6 files changed

+114
-25
lines changed

pkg/cmd/extensions/command.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func NewCmdExtensions(f *cmdutil.Factory) *cobra.Command {
4343
if len(cmds) == 0 {
4444
return errors.New("no extensions installed")
4545
}
46-
// cs := io.ColorScheme()
46+
cs := io.ColorScheme()
4747
t := utils.NewTablePrinter(io)
4848
for _, c := range cmds {
4949
var repo string
@@ -55,8 +55,11 @@ func NewCmdExtensions(f *cmdutil.Factory) *cobra.Command {
5555

5656
t.AddField(fmt.Sprintf("gh %s", c.Name()), nil, nil)
5757
t.AddField(repo, nil, nil)
58-
// TODO: add notice about available update
59-
//t.AddField("Update available", nil, cs.Green)
58+
var updateAvailable string
59+
if c.UpdateAvailable() {
60+
updateAvailable = "Update available"
61+
}
62+
t.AddField(updateAvailable, nil, cs.Green)
6063
t.EndRow()
6164
}
6265
return t.Render()

pkg/cmd/extensions/command_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,21 @@ func TestNewCmdExtensions(t *testing.T) {
146146
isTTY: false,
147147
wantStdout: "",
148148
},
149+
{
150+
name: "list extensions",
151+
args: []string{"list"},
152+
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
153+
em.ListFunc = func() []extensions.Extension {
154+
ex1 := &Extension{path: "cli/gh-test", url: "https://github.com/cli/gh-test", updateAvailable: false}
155+
ex2 := &Extension{path: "cli/gh-test2", url: "https://github.com/cli/gh-test2", updateAvailable: true}
156+
return []extensions.Extension{ex1, ex2}
157+
}
158+
return func(t *testing.T) {
159+
assert.Equal(t, 1, len(em.ListCalls()))
160+
}
161+
},
162+
wantStdout: "gh test\tcli/gh-test\t\ngh test2\tcli/gh-test2\tUpdate available\n",
163+
},
149164
}
150165

151166
for _, tt := range tests {

pkg/cmd/extensions/extension.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import (
88
)
99

1010
type Extension struct {
11-
path string
12-
url string
11+
path string
12+
url string
13+
updateAvailable bool
1314
}
1415

1516
func (e *Extension) Name() string {
@@ -40,3 +41,7 @@ func (e *Extension) IsLocal() bool {
4041
}
4142
return false
4243
}
44+
45+
func (e *Extension) UpdateAvailable() bool {
46+
return e.updateAvailable
47+
}

pkg/cmd/extensions/manager.go

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,34 +87,63 @@ func (m *Manager) list(includeMetadata bool) []extensions.Extension {
8787
if err != nil {
8888
return nil
8989
}
90-
91-
var gitExe string
92-
if includeMetadata {
93-
gitExe, _ = m.lookPath("git")
94-
}
95-
9690
var results []extensions.Extension
9791
for _, f := range entries {
9892
if !strings.HasPrefix(f.Name(), "gh-") || !(f.IsDir() || f.Mode()&os.ModeSymlink != 0) {
9993
continue
10094
}
101-
var remoteURL string
102-
if gitExe != "" {
103-
stdout := bytes.Buffer{}
104-
cmd := m.newCommand(gitExe, "--git-dir="+filepath.Join(dir, f.Name(), ".git"), "config", "remote.origin.url")
105-
cmd.Stdout = &stdout
106-
if err := cmd.Run(); err == nil {
107-
remoteURL = strings.TrimSpace(stdout.String())
108-
}
95+
var remoteUrl string
96+
var updateAvailable bool
97+
if includeMetadata {
98+
remoteUrl = m.getRemoteUrl(f.Name())
99+
updateAvailable = m.checkUpdateAvailable(f.Name())
109100
}
110101
results = append(results, &Extension{
111-
path: filepath.Join(dir, f.Name(), f.Name()),
112-
url: remoteURL,
102+
path: filepath.Join(dir, f.Name(), f.Name()),
103+
url: remoteUrl,
104+
updateAvailable: updateAvailable,
113105
})
114106
}
115107
return results
116108
}
117109

110+
func (m *Manager) getRemoteUrl(extension string) string {
111+
gitExe, err := m.lookPath("git")
112+
if err != nil {
113+
return ""
114+
}
115+
dir := m.installDir()
116+
gitDir := "--git-dir=" + filepath.Join(dir, extension, ".git")
117+
cmd := m.newCommand(gitExe, gitDir, "config", "remote.origin.url")
118+
url, err := cmd.Output()
119+
if err != nil {
120+
return ""
121+
}
122+
return strings.TrimSpace(string(url))
123+
}
124+
125+
func (m *Manager) checkUpdateAvailable(extension string) bool {
126+
gitExe, err := m.lookPath("git")
127+
if err != nil {
128+
return false
129+
}
130+
dir := m.installDir()
131+
gitDir := "--git-dir=" + filepath.Join(dir, extension, ".git")
132+
cmd := m.newCommand(gitExe, gitDir, "ls-remote", "origin", "HEAD")
133+
lsRemote, err := cmd.Output()
134+
if err != nil {
135+
return false
136+
}
137+
remoteSha := bytes.SplitN(lsRemote, []byte("\t"), 2)[0]
138+
cmd = m.newCommand(gitExe, gitDir, "rev-parse", "HEAD")
139+
localSha, err := cmd.Output()
140+
if err != nil {
141+
return false
142+
}
143+
localSha = bytes.TrimSpace(localSha)
144+
return !bytes.Equal(remoteSha, localSha)
145+
}
146+
118147
func (m *Manager) InstallLocal(dir string) error {
119148
name := filepath.Base(dir)
120149
targetDir := filepath.Join(m.installDir(), name)

pkg/extensions/extension.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type Extension interface {
1010
Path() string
1111
URL() string
1212
IsLocal() bool
13+
UpdateAvailable() bool
1314
}
1415

1516
//go:generate moq -out manager_mock.go . ExtensionManager

pkg/extensions/extension_mock.go

Lines changed: 40 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
X Tutup