github.com/snyk/vervet/v3@v3.7.0/internal/files/files.go (about) 1 package files 2 3 import ( 4 "io/fs" 5 "os" 6 "path/filepath" 7 8 "github.com/bmatcuk/doublestar/v4" 9 10 "github.com/snyk/vervet/v3" 11 "github.com/snyk/vervet/v3/config" 12 ) 13 14 // FileSource defines a source of spec files to lint. This abstraction allows 15 // linters to operate seamlessly over version control systems and local files. 16 type FileSource interface { 17 // Name returns a string describing the file source. 18 Name() string 19 20 // Match returns a slice of logical paths to spec files that should be 21 // linted from the given resource set configuration. 22 Match(*config.ResourceSet) ([]string, error) 23 24 // Prefetch retrieves an entire directory tree starting at the given root, 25 // for remote sources which need to download and cache a local copy. For 26 // such sources, a call to Fetch without a pre-fetched root will error. 27 // The path to the local copy of the "root" is returned. 28 // 29 // For local sources, this method may be a no-op / passthrough. 30 // 31 // The root must contain all relative OpenAPI $ref references in all linted 32 // specs, or the lint will fail. 33 Prefetch(root string) (string, error) 34 35 // Fetch retrieves the contents of the requested logical path as a local 36 // file and returns the absolute path where it may be found. An empty 37 // string, rather than an error, is returned if the file does not exist. 38 Fetch(path string) (string, error) 39 40 // Close releases any resources consumed in content retrieval. Any files 41 // returned by Fetch will no longer be available after calling Close, and 42 // any further calls to Fetch will error. 43 Close() error 44 } 45 46 // NilSource is a FileSource that does not have any files in it. 47 type NilSource struct{} 48 49 // Name implements FileSource. 50 func (NilSource) Name() string { return "does not exist" } 51 52 // Match implements FileSource. 53 func (NilSource) Match(*config.ResourceSet) ([]string, error) { return nil, nil } 54 55 // Prefetch implements FileSource. 56 func (NilSource) Prefetch(root string) (string, error) { 57 return "", nil 58 } 59 60 // Fetch implements FileSource. 61 func (NilSource) Fetch(path string) (string, error) { 62 return "", nil 63 } 64 65 // Close implements FileSource. 66 func (NilSource) Close() error { return nil } 67 68 // LocalFSSource is a FileSource that resolves files from the local filesystem 69 // relative to the current working directory. 70 type LocalFSSource struct{} 71 72 // Name implements FileSource. 73 func (LocalFSSource) Name() string { return "local file" } 74 75 // Match implements FileSource. 76 func (LocalFSSource) Match(rcConfig *config.ResourceSet) ([]string, error) { 77 var result []string 78 err := doublestar.GlobWalk(os.DirFS(rcConfig.Path), 79 vervet.SpecGlobPattern, 80 func(path string, d fs.DirEntry) error { 81 rcPath := filepath.Join(rcConfig.Path, path) 82 for i := range rcConfig.Excludes { 83 if ok, err := doublestar.Match(rcConfig.Excludes[i], rcPath); ok { 84 return nil 85 } else if err != nil { 86 return err 87 } 88 } 89 result = append(result, rcPath) 90 return nil 91 }) 92 return result, err 93 } 94 95 // Prefetch implements FileSource. 96 func (LocalFSSource) Prefetch(root string) (string, error) { 97 cwd, err := os.Getwd() 98 if err != nil { 99 return "", err 100 } 101 return filepath.Join(cwd, root), nil 102 } 103 104 // Fetch implements FileSource. 105 func (LocalFSSource) Fetch(path string) (string, error) { 106 if _, err := os.Stat(path); err == nil { 107 return filepath.Abs(path) 108 } else if os.IsNotExist(err) { 109 return "", nil 110 } else { 111 return "", err 112 } 113 } 114 115 // Close implements FileSource. 116 func (LocalFSSource) Close() error { return nil }