@@ -7,9 +7,11 @@ import (
7
7
"errors"
8
8
"fmt"
9
9
"io"
10
+ "io/fs"
10
11
"net/http"
11
12
"os"
12
13
"path"
14
+ "path/filepath"
13
15
"sort"
14
16
"strings"
15
17
"sync"
@@ -276,25 +278,32 @@ func (s *Artifactory) AddExtension(ctx context.Context, manifest *VSIXManifest,
276
278
return s .uri + dir , nil
277
279
}
278
280
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
293
300
}
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
298
307
}
299
308
300
309
func (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
443
452
sort .Sort (ByVersion (versions ))
444
453
return versions , nil
445
454
}
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