github.com/anchore/syft@v1.38.2/syft/internal/fileresolver/directory.go (about) 1 package fileresolver 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/anchore/stereoscope/pkg/filetree" 8 "github.com/anchore/syft/syft/file" 9 ) 10 11 var ErrSkipPath = errors.New("skip path") 12 13 var _ file.Resolver = (*Directory)(nil) 14 15 // Directory implements path and content access for the directory data source. 16 type Directory struct { 17 FiletreeResolver 18 path string 19 indexer *directoryIndexer 20 } 21 22 func NewFromDirectory(root, base string, pathFilters ...PathIndexVisitor) (*Directory, error) { 23 resolver, err := newFromDirectoryWithoutIndex(root, base, pathFilters...) 24 if err != nil { 25 return nil, err 26 } 27 28 return resolver, resolver.buildIndex() 29 } 30 31 func newFromDirectoryWithoutIndex(root, base string, pathFilters ...PathIndexVisitor) (*Directory, error) { 32 chroot, err := NewChrootContextFromCWD(root, base) 33 if err != nil { 34 return nil, fmt.Errorf("unable to interpret chroot context: %w", err) 35 } 36 37 cleanRoot := chroot.Root() 38 cleanBase := chroot.Base() 39 40 return &Directory{ 41 path: cleanRoot, 42 FiletreeResolver: FiletreeResolver{ 43 Chroot: *chroot, 44 Tree: filetree.New(), 45 Index: filetree.NewIndex(), 46 Opener: nativeOSFileOpener, 47 }, 48 indexer: newDirectoryIndexer(cleanRoot, cleanBase, pathFilters...), 49 }, nil 50 } 51 52 func (r *Directory) buildIndex() error { 53 if r.indexer == nil { 54 return fmt.Errorf("no directory indexer configured") 55 } 56 tree, index, err := r.indexer.build() 57 if err != nil { 58 return err 59 } 60 61 r.Tree = tree 62 r.Index = index 63 r.SearchContext = filetree.NewSearchContext(tree, index) 64 65 return nil 66 } 67 68 // Stringer to represent a directory path data source 69 func (r *Directory) String() string { 70 return fmt.Sprintf("dir:%s", r.path) 71 }