github.com/grailbio/base@v0.0.11/file/s3file/versions.go (about) 1 package s3file 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/grailbio/base/errors" 8 "github.com/grailbio/base/file" 9 "github.com/grailbio/base/file/addfs" 10 "github.com/grailbio/base/file/fsnode" 11 "github.com/grailbio/base/grail/biofs/biofseventlog" 12 ) 13 14 type versionsFunc struct{} 15 16 var ( 17 VersionsFunc versionsFunc 18 _ addfs.PerNodeFunc = VersionsFunc 19 ) 20 21 func (versionsFunc) Apply(ctx context.Context, node fsnode.T) ([]fsnode.T, error) { 22 biofseventlog.UsedFeature("s3.versions.func") 23 // For now, we rely on gfilefs's fsnode.T implementations saving the underlying path as Sys(). 24 // This is temporary (BXDS-1030). When we fix that, we'll need to make this detect the 25 // concrete type for S3-backed fsnode.T's instead of looking for Sys(). That'll likely require 26 // refactoring such as merging gfilefs into this package. 27 path, ok := node.Info().Sys().(string) 28 if !ok { 29 return nil, nil 30 } 31 scheme, bucket, key, err := ParseURL(path) 32 if err != nil || scheme != Scheme { 33 return nil, nil 34 } 35 implIface := file.FindImplementation(Scheme) 36 impl, ok := implIface.(*s3Impl) 37 if !ok { 38 return nil, errors.E(errors.Precondition, fmt.Sprintf("unrecognized s3 impl: %T", implIface)) 39 } 40 var ( 41 q = s3Query{impl, bucket, key} 42 gen fsnode.ChildrenGenerator 43 ) 44 switch node.(type) { 45 case fsnode.Parent: 46 gen = versionsDirViewGen{q} 47 case fsnode.Leaf: 48 gen = versionsObjViewGen{q} 49 default: 50 return nil, errors.E(errors.Precondition, fmt.Sprintf("unrecognized node: %T", node)) 51 } 52 return []fsnode.T{ 53 fsnode.NewParent( 54 fsnode.NewDirInfo("versions").WithCacheableFor(fsnode.CacheableFor(node)), 55 gen, 56 ), 57 }, nil 58 }