1- #
2- # Copyright (c) nexB Inc. and others. All rights reserved.
3- # ScanCode is a trademark of nexB Inc.
4- # SPDX-License-Identifier: Apache-2.0
5- # See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6- # See https://github.com/nexB/scancode-toolkit for support or download.
7- # See https://aboutcode.org for more information about nexB OSS projects.
8- #
9-
101import toml
112from packagedcode import models
123from packageurl import PackageURL
4+ import yaml
135
146class BuildpackHandler (models .DatafileHandler ):
157 """
@@ -30,29 +22,34 @@ def parse(cls, location, package_only=False):
3022 with open (location , "r" , encoding = "utf-8" ) as f :
3123 data = toml .load (f )
3224
33- # Extract required fields
3425 api_version = data .get ("api" )
3526 buildpack = data .get ("buildpack" , {})
3627 if not buildpack :
3728 return
3829
30+ buildpack_id = buildpack .get ("id" )
3931 name = buildpack .get ("name" )
40- if not name :
41- return
4232
33+ if buildpack_id :
34+ namespace , name = buildpack_id .split ("/" , 1 )
35+
4336 # Initialize common package data
4437 package_data = dict (
4538 datasource_id = cls .datasource_id ,
4639 type = cls .default_package_type ,
4740 name = name ,
48- version = " unknown" ,
49- description = None ,
50- homepage_url = None ,
51- keywords = [] ,
52- declared_license_expression = None ,
41+ version = buildpack . get ( "version" , " unknown") ,
42+ description = buildpack . get ( "description" ) ,
43+ homepage_url = buildpack . get ( "homepage" ) ,
44+ keywords = buildpack . get ( "keywords" , []) ,
45+ extracted_license_statement = None ,
5346 dependencies = [],
47+ extra_data = {}
5448 )
5549
50+ if api_version :
51+ package_data ["extra_data" ]["api_version" ] = api_version
52+
5653 # Handle Paketo-specific fields if present
5754 if "api" in data :
5855 cls .handle_paketo_buildpack (data , buildpack , package_data )
@@ -67,7 +64,7 @@ def parse(cls, location, package_only=False):
6764 def handle_paketo_buildpack (data , buildpack , package_data ):
6865 buildpack_id = buildpack .get ("id" )
6966 if buildpack_id :
70- package_data ["extra_data" ] = { "id" : buildpack_id }
67+ package_data ["extra_data" ][ "id" ] = buildpack_id
7168
7269 package_data .update ({
7370 "version" : buildpack .get ("version" , "unknown" ),
@@ -77,11 +74,14 @@ def handle_paketo_buildpack(data, buildpack, package_data):
7774 })
7875
7976 licenses = buildpack .get ("licenses" , [])
80- license_expressions = [
81- license_entry .get ("type" ) for license_entry in licenses if license_entry .get ("type" )
82- ]
83- if license_expressions :
84- package_data ["declared_license_expression" ] = " AND " .join (license_expressions )
77+ if licenses :
78+ license_statements = [
79+ yaml .dump ({"type" : license_entry .get ("type" )}).strip ()
80+ for license_entry in licenses
81+ if license_entry .get ("type" )
82+ ]
83+ package_data ["extracted_license_statement" ] = "\n " .join (license_statements )
84+
8585
8686 dependencies = []
8787 metadata = data .get ("metadata" , {})
@@ -90,22 +90,20 @@ def handle_paketo_buildpack(data, buildpack, package_data):
9090 dep_purl = dep .get ("purl" )
9191 dep_name = dep .get ("name" )
9292 dep_version = dep .get ("version" )
93+ dep_cpes = dep .get ("cpes" , [])
94+ extra_data = {"cpes" : dep_cpes } if dep_cpes else {}
95+
96+ if not dep_purl and dep_name and dep_version :
97+ dep_purl = PackageURL (type = "generic" , name = dep_name , version = dep_version ).to_string ()
98+
9399 if dep_purl :
94100 dependencies .append (
95101 models .DependentPackage (
96102 purl = dep_purl ,
97103 scope = "runtime" ,
98104 is_runtime = True ,
99105 is_optional = False ,
100- )
101- )
102- elif dep_name and dep_version :
103- dependencies .append (
104- models .DependentPackage (
105- purl = PackageURL (type = "generic" , name = dep_name , version = dep_version ).to_string (),
106- scope = "runtime" ,
107- is_runtime = True ,
108- is_optional = False ,
106+ extra_data = extra_data ,
109107 )
110108 )
111109
@@ -126,18 +124,20 @@ def handle_paketo_buildpack(data, buildpack, package_data):
126124
127125 package_data ["dependencies" ] = dependencies
128126
127+ targets = data .get ("targets" , [])
128+ if targets :
129+ package_data ["extra_data" ]["targets" ] = targets
130+
129131 @staticmethod
130132 def handle_heroku_buildpack (data , buildpack , package_data ):
131133 publish_section = data .get ("publish" , {})
132134 if "Ignore" in publish_section :
133135 ignore_files = publish_section ["Ignore" ].get ("files" , [])
134- if ignore_files : # Only add if files are found
135- package_data ["extra_data" ] = { "ignore_files" : ignore_files }
136+ if ignore_files :
137+ package_data ["extra_data" ][ "ignore_files" ] = ignore_files
136138 else :
137- package_data ["extra_data" ] = { "ignore_files" : []}
139+ package_data ["extra_data" ][ "ignore_files" ] = []
138140 else :
139- package_data ["extra_data" ] = { "ignore_files" : []}
141+ package_data ["extra_data" ][ "ignore_files" ] = []
140142
141- # Add description for Heroku buildpack
142143 package_data ["description" ] = f"Heroku buildpack for { buildpack .get ('name' )} "
143-
0 commit comments