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
-
10
1
import toml
11
2
from packagedcode import models
12
3
from packageurl import PackageURL
4
+ import yaml
13
5
14
6
class BuildpackHandler (models .DatafileHandler ):
15
7
"""
@@ -30,29 +22,34 @@ def parse(cls, location, package_only=False):
30
22
with open (location , "r" , encoding = "utf-8" ) as f :
31
23
data = toml .load (f )
32
24
33
- # Extract required fields
34
25
api_version = data .get ("api" )
35
26
buildpack = data .get ("buildpack" , {})
36
27
if not buildpack :
37
28
return
38
29
30
+ buildpack_id = buildpack .get ("id" )
39
31
name = buildpack .get ("name" )
40
- if not name :
41
- return
42
32
33
+ if buildpack_id :
34
+ namespace , name = buildpack_id .split ("/" , 1 )
35
+
43
36
# Initialize common package data
44
37
package_data = dict (
45
38
datasource_id = cls .datasource_id ,
46
39
type = cls .default_package_type ,
47
40
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 ,
53
46
dependencies = [],
47
+ extra_data = {}
54
48
)
55
49
50
+ if api_version :
51
+ package_data ["extra_data" ]["api_version" ] = api_version
52
+
56
53
# Handle Paketo-specific fields if present
57
54
if "api" in data :
58
55
cls .handle_paketo_buildpack (data , buildpack , package_data )
@@ -67,7 +64,7 @@ def parse(cls, location, package_only=False):
67
64
def handle_paketo_buildpack (data , buildpack , package_data ):
68
65
buildpack_id = buildpack .get ("id" )
69
66
if buildpack_id :
70
- package_data ["extra_data" ] = { "id" : buildpack_id }
67
+ package_data ["extra_data" ][ "id" ] = buildpack_id
71
68
72
69
package_data .update ({
73
70
"version" : buildpack .get ("version" , "unknown" ),
@@ -77,11 +74,14 @@ def handle_paketo_buildpack(data, buildpack, package_data):
77
74
})
78
75
79
76
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
+
85
85
86
86
dependencies = []
87
87
metadata = data .get ("metadata" , {})
@@ -90,22 +90,20 @@ def handle_paketo_buildpack(data, buildpack, package_data):
90
90
dep_purl = dep .get ("purl" )
91
91
dep_name = dep .get ("name" )
92
92
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
+
93
99
if dep_purl :
94
100
dependencies .append (
95
101
models .DependentPackage (
96
102
purl = dep_purl ,
97
103
scope = "runtime" ,
98
104
is_runtime = True ,
99
105
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 ,
109
107
)
110
108
)
111
109
@@ -126,18 +124,20 @@ def handle_paketo_buildpack(data, buildpack, package_data):
126
124
127
125
package_data ["dependencies" ] = dependencies
128
126
127
+ targets = data .get ("targets" , [])
128
+ if targets :
129
+ package_data ["extra_data" ]["targets" ] = targets
130
+
129
131
@staticmethod
130
132
def handle_heroku_buildpack (data , buildpack , package_data ):
131
133
publish_section = data .get ("publish" , {})
132
134
if "Ignore" in publish_section :
133
135
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
136
138
else :
137
- package_data ["extra_data" ] = { "ignore_files" : []}
139
+ package_data ["extra_data" ][ "ignore_files" ] = []
138
140
else :
139
- package_data ["extra_data" ] = { "ignore_files" : []}
141
+ package_data ["extra_data" ][ "ignore_files" ] = []
140
142
141
- # Add description for Heroku buildpack
142
143
package_data ["description" ] = f"Heroku buildpack for { buildpack .get ('name' )} "
143
-
0 commit comments