github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/ruby/parse_gemfile_lock.go (about) 1 package ruby 2 3 import ( 4 "bufio" 5 "strings" 6 7 "github.com/anchore/syft/internal" 8 "github.com/anchore/syft/syft/artifact" 9 "github.com/anchore/syft/syft/file" 10 "github.com/anchore/syft/syft/pkg" 11 "github.com/anchore/syft/syft/pkg/cataloger/generic" 12 ) 13 14 var _ generic.Parser = parseGemFileLockEntries 15 16 var sectionsOfInterest = internal.NewStringSet("GEM", "GIT", "PATH", "PLUGIN SOURCE") 17 18 // parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered. 19 func parseGemFileLockEntries(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 20 var pkgs []pkg.Package 21 scanner := bufio.NewScanner(reader) 22 23 var currentSection string 24 25 for scanner.Scan() { 26 line := scanner.Text() 27 sanitizedLine := strings.TrimSpace(line) 28 29 if len(line) > 1 && line[0] != ' ' { 30 // start of section 31 currentSection = sanitizedLine 32 continue 33 } else if !sectionsOfInterest.Contains(currentSection) { 34 // skip this line, we're in the wrong section 35 continue 36 } 37 38 if isDependencyLine(line) { 39 candidate := strings.Fields(sanitizedLine) 40 if len(candidate) != 2 { 41 continue 42 } 43 pkgs = append(pkgs, 44 newGemfileLockPackage( 45 candidate[0], 46 strings.Trim(candidate[1], "()"), 47 reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 48 ), 49 ) 50 } 51 } 52 if err := scanner.Err(); err != nil { 53 return nil, nil, err 54 } 55 return pkgs, nil, nil 56 } 57 58 func isDependencyLine(line string) bool { 59 if len(line) < 5 { 60 return false 61 } 62 return strings.Count(line[:5], " ") == 4 63 }