github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/dart/parse_pubspec_lock.go (about) 1 package dart 2 3 import ( 4 "context" 5 "fmt" 6 "net/url" 7 "sort" 8 9 "gopkg.in/yaml.v3" 10 11 "github.com/anchore/syft/internal/log" 12 "github.com/anchore/syft/syft/artifact" 13 "github.com/anchore/syft/syft/file" 14 "github.com/anchore/syft/syft/pkg" 15 "github.com/anchore/syft/syft/pkg/cataloger/generic" 16 ) 17 18 var _ generic.Parser = parsePubspecLock 19 20 const defaultPubRegistry string = "https://pub.dartlang.org" 21 22 type pubspecLock struct { 23 Packages map[string]pubspecLockPackage `yaml:"packages"` 24 Sdks map[string]string `yaml:"sdks"` 25 } 26 27 type pubspecLockPackage struct { 28 Dependency string `yaml:"dependency" mapstructure:"dependency"` 29 Description pubspecLockDescription `yaml:"description" mapstructure:"description"` 30 Source string `yaml:"source" mapstructure:"source"` 31 Version string `yaml:"version" mapstructure:"version"` 32 } 33 34 type pubspecLockDescription struct { 35 Name string `yaml:"name" mapstructure:"name"` 36 URL string `yaml:"url" mapstructure:"url"` 37 Path string `yaml:"path" mapstructure:"path"` 38 Ref string `yaml:"ref" mapstructure:"ref"` 39 ResolvedRef string `yaml:"resolved-ref" mapstructure:"resolved-ref"` 40 } 41 42 func (p *pubspecLockDescription) UnmarshalYAML(value *yaml.Node) error { 43 type pld pubspecLockDescription 44 var p2 pld 45 46 if value.Decode(&p.Name) == nil { 47 return nil 48 } 49 50 if err := value.Decode(&p2); err != nil { 51 return err 52 } 53 54 *p = pubspecLockDescription(p2) 55 56 return nil 57 } 58 59 func parsePubspecLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 60 var pkgs []pkg.Package 61 62 dec := yaml.NewDecoder(reader) 63 64 var p pubspecLock 65 if err := dec.Decode(&p); err != nil { 66 return nil, nil, fmt.Errorf("failed to parse pubspec.lock file: %w", err) 67 } 68 69 var names []string 70 for name := range p.Packages { 71 names = append(names, name) 72 } 73 74 // always ensure there is a stable ordering of packages 75 sort.Strings(names) 76 77 for _, name := range names { 78 pubPkg := p.Packages[name] 79 pkgs = append(pkgs, 80 newPubspecLockPackage( 81 name, 82 pubPkg, 83 reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 84 ), 85 ) 86 } 87 88 return pkgs, nil, nil 89 } 90 91 func (p *pubspecLockPackage) getVcsURL() string { 92 if p.Source == "git" { 93 if p.Description.Path == "." { 94 return fmt.Sprintf("%s@%s", p.Description.URL, p.Description.ResolvedRef) 95 } 96 97 return fmt.Sprintf("%s@%s#%s", p.Description.URL, p.Description.ResolvedRef, p.Description.Path) 98 } 99 100 return "" 101 } 102 103 func (p *pubspecLockPackage) getHostedURL() string { 104 if p.Source == "hosted" && p.Description.URL != defaultPubRegistry { 105 u, err := url.Parse(p.Description.URL) 106 if err != nil { 107 log.Debugf("Unable to parse registry url %w", err) 108 return p.Description.URL 109 } 110 return u.Host 111 } 112 113 return "" 114 }