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