55 "errors"
66 "fmt"
77 "io"
8+ "io/fs"
89 "io/ioutil"
910 "net/http"
1011 "os"
@@ -105,7 +106,6 @@ func (m *Manager) List(includeMetadata bool) []extensions.Extension {
105106}
106107
107108func (m * Manager ) list (includeMetadata bool ) ([]extensions.Extension , error ) {
108- // TODO need to fix this to work with binary extensions before upgrade will work
109109 dir := m .installDir ()
110110 entries , err := ioutil .ReadDir (dir )
111111 if err != nil {
@@ -117,36 +117,96 @@ func (m *Manager) list(includeMetadata bool) ([]extensions.Extension, error) {
117117 if ! strings .HasPrefix (f .Name (), "gh-" ) {
118118 continue
119119 }
120- var remoteUrl string
121- updateAvailable := false
122- isLocal := false
123- exePath := filepath .Join (dir , f .Name (), f .Name ())
124- if f .IsDir () {
125- if includeMetadata {
126- remoteUrl = m .getRemoteUrl (f .Name ())
127- updateAvailable = m .checkUpdateAvailable (f .Name ())
128- }
129- } else {
130- isLocal = true
131- if ! isSymlink (f .Mode ()) {
132- // if this is a regular file, its contents is the local directory of the extension
133- p , err := readPathFromFile (filepath .Join (dir , f .Name ()))
134- if err != nil {
135- return nil , err
136- }
137- exePath = filepath .Join (p , f .Name ())
138- }
120+ ext , err := m .parseExtensionDir (f , includeMetadata )
121+ if err != nil {
122+ return nil , err
139123 }
140- results = append (results , & Extension {
141- path : exePath ,
142- url : remoteUrl ,
143- isLocal : isLocal ,
144- updateAvailable : updateAvailable ,
145- })
124+ results = append (results , ext )
146125 }
126+
147127 return results , nil
148128}
149129
130+ func (m * Manager ) parseExtensionDir (fi fs.FileInfo , includeMetadata bool ) (* Extension , error ) {
131+ id := m .installDir ()
132+ if _ , err := os .Stat (filepath .Join (id , fi .Name (), manifestName )); err == nil {
133+ return m .parseBinaryExtension (fi , includeMetadata )
134+ }
135+
136+ return m .parseGitExtension (fi , includeMetadata )
137+ }
138+
139+ func (m * Manager ) parseBinaryExtension (fi fs.FileInfo , includeMetadata bool ) (* Extension , error ) {
140+ id := m .installDir ()
141+ exePath := filepath .Join (id , fi .Name (), fi .Name ())
142+ manifestPath := filepath .Join (id , fi .Name (), manifestName )
143+ manifest , err := os .ReadFile (manifestPath )
144+ if err != nil {
145+ return nil , fmt .Errorf ("could not open %s for reading: %w" , manifestPath , err )
146+ }
147+
148+ var bm binManifest
149+ err = yaml .Unmarshal (manifest , & bm )
150+ if err != nil {
151+ return nil , fmt .Errorf ("could not parse %s: %w" , manifestPath , err )
152+ }
153+
154+ repo := ghrepo .NewWithHost (bm .Owner , bm .Name , bm .Host )
155+
156+ var remoteURL string
157+ var updateAvailable bool
158+
159+ if includeMetadata {
160+ remoteURL = ghrepo .GenerateRepoURL (repo , "" )
161+ var r * release
162+ r , err = fetchLatestRelease (m .client , repo )
163+ if err != nil {
164+ return nil , fmt .Errorf ("failed to get release info for %s: %w" , ghrepo .FullName (repo ), err )
165+ }
166+ if bm .Tag != r .Tag {
167+ updateAvailable = true
168+ }
169+ }
170+
171+ return & Extension {
172+ path : exePath ,
173+ url : remoteURL ,
174+ updateAvailable : updateAvailable ,
175+ }, nil
176+ }
177+
178+ func (m * Manager ) parseGitExtension (fi fs.FileInfo , includeMetadata bool ) (* Extension , error ) {
179+ // TODO untangle local from this since local might be binary or git
180+ id := m .installDir ()
181+ var remoteUrl string
182+ updateAvailable := false
183+ isLocal := false
184+ exePath := filepath .Join (id , fi .Name (), fi .Name ())
185+ if fi .IsDir () {
186+ if includeMetadata {
187+ remoteUrl = m .getRemoteUrl (fi .Name ())
188+ updateAvailable = m .checkUpdateAvailable (fi .Name ())
189+ }
190+ } else {
191+ isLocal = true
192+ if ! isSymlink (fi .Mode ()) {
193+ // if this is a regular file, its contents is the local directory of the extension
194+ p , err := readPathFromFile (filepath .Join (id , fi .Name ()))
195+ if err != nil {
196+ return nil , err
197+ }
198+ exePath = filepath .Join (p , fi .Name ())
199+ }
200+ }
201+
202+ return & Extension {
203+ path : exePath ,
204+ url : remoteUrl ,
205+ isLocal : isLocal ,
206+ updateAvailable : updateAvailable ,
207+ }, nil
208+ }
209+
150210func (m * Manager ) getRemoteUrl (extension string ) string {
151211 gitExe , err := m .lookPath ("git" )
152212 if err != nil {
@@ -335,9 +395,8 @@ func (m *Manager) Upgrade(name string, force bool) error {
335395 continue
336396 }
337397
338- _ , err := os .Stat (filepath .Join (f .Path (), manifestName ))
339- if err == nil {
340- // TODO is there any need for a "forced" binary upgrade?
398+ binManifestPath := filepath .Join (filepath .Dir (f .Path ()), manifestName )
399+ if _ , e := os .Stat (binManifestPath ); e == nil {
341400 err = m .upgradeBin (f )
342401 someUpgraded = true
343402 continue
@@ -372,7 +431,7 @@ func (m *Manager) upgradeGit(ext extensions.Extension, exe string, force bool) e
372431}
373432
374433func (m * Manager ) upgradeBin (ext extensions.Extension ) error {
375- manifestPath := filepath .Join (ext .Path (), manifestName )
434+ manifestPath := filepath .Join (filepath . Dir ( ext .Path () ), manifestName )
376435 manifest , err := os .ReadFile (manifestPath )
377436 if err != nil {
378437 return fmt .Errorf ("could not open %s for reading: %w" , manifestPath , err )
@@ -395,7 +454,6 @@ func (m *Manager) upgradeBin(ext extensions.Extension) error {
395454 return nil
396455 }
397456
398- // TODO will this work?
399457 return m .installBin (repo )
400458}
401459
0 commit comments