@@ -7,9 +7,11 @@ import (
77 "errors"
88 "fmt"
99 "io"
10+ "io/fs"
1011 "net/http"
1112 "os"
1213 "path"
14+ "path/filepath"
1315 "sort"
1416 "strings"
1517 "sync"
@@ -276,25 +278,32 @@ func (s *Artifactory) AddExtension(ctx context.Context, manifest *VSIXManifest,
276278 return s .uri + dir , nil
277279}
278280
279- func (s * Artifactory ) FileServer () http.Handler {
280- // TODO: Since we only extract a subset of files perhaps if the file does not
281- // exist we should download the vsix and extract the requested file as a
282- // fallback. Obviously this seems like quite a bit of overhead so we would
283- // then emit a warning so we can notice that VS Code has added new asset types
284- // that we should be extracting to avoid that overhead. Other solutions could
285- // be implemented though like extracting the VSIX to disk locally and only
286- // going to Artifactory for the VSIX when it is missing on disk (basically
287- // using the disk as a cache).
288- return http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
289- reader , code , err := s .read (r .Context (), r .URL .Path )
290- if err != nil {
291- http .Error (rw , err .Error (), code )
292- return
281+ // Open returns a file from Artifactory.
282+ // TODO: Since we only extract a subset of files perhaps if the file does not
283+ // exist we should download the vsix and extract the requested file as a
284+ // fallback. Obviously this seems like quite a bit of overhead so we would
285+ // then emit a warning so we can notice that VS Code has added new asset types
286+ // that we should be extracting to avoid that overhead. Other solutions could
287+ // be implemented though like extracting the VSIX to disk locally and only
288+ // going to Artifactory for the VSIX when it is missing on disk (basically
289+ // using the disk as a cache).
290+ func (s * Artifactory ) Open (ctx context.Context , fp string ) (fs.File , error ) {
291+ resp , code , err := s .request (ctx , http .MethodGet , path .Join (s .repo , fp ), nil )
292+ if err != nil {
293+ switch code {
294+ case http .StatusNotFound :
295+ return nil , fs .ErrNotExist
296+ case http .StatusForbidden :
297+ return nil , fs .ErrPermission
298+ default :
299+ return nil , err
293300 }
294- defer reader .Close ()
295- rw .WriteHeader (http .StatusOK )
296- _ , _ = io .Copy (rw , reader )
297- })
301+ }
302+
303+ return artifactoryFile {
304+ Response : resp ,
305+ path : fp ,
306+ }, nil
298307}
299308
300309func (s * Artifactory ) Manifest (ctx context.Context , publisher , name string , version Version ) (* VSIXManifest , error ) {
@@ -443,3 +452,30 @@ func (s *Artifactory) Versions(ctx context.Context, publisher, name string) ([]V
443452 sort .Sort (ByVersion (versions ))
444453 return versions , nil
445454}
455+
456+ type contextFs struct {
457+ ctx context.Context
458+ open func (ctx context.Context , name string ) (fs.File , error )
459+ }
460+
461+ func (c * contextFs ) Open (name string ) (fs.File , error ) {
462+ return c .open (c .ctx , name )
463+ }
464+
465+ var _ fs.File = (* artifactoryFile )(nil )
466+ var _ fs.FileInfo = (* artifactoryFile )(nil )
467+
468+ type artifactoryFile struct {
469+ * http.Response
470+ path string
471+ }
472+
473+ func (a artifactoryFile ) Name () string { return filepath .Base (a .path ) }
474+ func (a artifactoryFile ) Size () int64 { return a .Response .ContentLength }
475+ func (a artifactoryFile ) Mode () fs.FileMode { return fs .FileMode (0 ) } // ?
476+ func (a artifactoryFile ) ModTime () time.Time { return time .Now () }
477+ func (a artifactoryFile ) IsDir () bool { return false }
478+ func (a artifactoryFile ) Sys () any { return nil }
479+ func (a artifactoryFile ) Stat () (fs.FileInfo , error ) { return a , nil }
480+ func (a artifactoryFile ) Read (i []byte ) (int , error ) { return a .Response .Body .Read (i ) }
481+ func (a artifactoryFile ) Close () error { return a .Response .Body .Close () }
0 commit comments