summaryrefslogtreecommitdiffstats
path: root/scripts/lib/recipetool/create_npm.py
diff options
context:
space:
mode:
authorEnguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>2024-08-12 14:28:29 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-08-23 09:51:36 +0100
commit0a0caacfa54dd086b87e31f5e806e5f21d5ffc3f (patch)
tree16808016f555c6bb2096240809bf481cea5cc458 /scripts/lib/recipetool/create_npm.py
parent69bf37a3dd0470dc153bb7a21bd8f13a64bde2c3 (diff)
downloadpoky-0a0caacfa54dd086b87e31f5e806e5f21d5ffc3f.tar.gz
recipetool: create_npm: reuse license utils
create_npm.py duplicated the logic for matching licenses from files and also finding them. This patch refactors the code to reuse the license utils. This will make the code more maintainable and also align both behaviors. For instance, some licenses weren't matched properly because the duplicate logic did not support the difference in format in the md5 tables for COMMON_LICENSE_DIR and licenses.csv. This is also faster since the license files were being read twice. The result is slightly more accurate since the utils have better implementations, and I was able to reuse the logic for the root PN package, as well as the base LICENSE variable. I chose to extract generate_common_licenses_chksums into create.py since it can be considered a general utility function to allow other recipetool creators to refer to COMMON_LICENSE_DIR files. I updated the wording in the code when appropriate. v3: - added commit - this replaces the commit that added all the COMMON_LICENSE_DIR md5 to licenses.csv (From OE-Core rev: 7bc18bed63b94689890bcde63402d7cc1cedffa9) Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib/recipetool/create_npm.py')
-rw-r--r--scripts/lib/recipetool/create_npm.py92
1 files changed, 28 insertions, 64 deletions
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index 78dc248f31..3363a0e7ee 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -16,8 +16,7 @@ from bb.fetch2.npm import NpmEnvironment
16from bb.fetch2.npm import npm_package 16from bb.fetch2.npm import npm_package
17from bb.fetch2.npmsw import foreach_dependencies 17from bb.fetch2.npmsw import foreach_dependencies
18from recipetool.create import RecipeHandler 18from recipetool.create import RecipeHandler
19from recipetool.create import get_license_md5sums 19from recipetool.create import match_licenses, find_license_files, generate_common_licenses_chksums
20from recipetool.create import find_licenses
21from recipetool.create import split_pkg_licenses 20from recipetool.create import split_pkg_licenses
22logger = logging.getLogger('recipetool') 21logger = logging.getLogger('recipetool')
23 22
@@ -112,51 +111,53 @@ class NpmRecipeHandler(RecipeHandler):
112 """Return the extra license files and the list of packages""" 111 """Return the extra license files and the list of packages"""
113 licfiles = [] 112 licfiles = []
114 packages = {} 113 packages = {}
115 # Licenses from package.json point to COMMON_LICENSE_DIR so we need 114 # Licenses from package.json will point to COMMON_LICENSE_DIR so we need
116 # to associate them explicitely for split_pkg_licenses() 115 # to associate them explicitely to packages for split_pkg_licenses()
117 fallback_licenses = dict() 116 fallback_licenses = dict()
118 117
119 # Handle the parent package 118 def _find_package_licenses(destdir):
120 packages["${PN}"] = "" 119 """Either find license files, or use package.json metadata"""
121
122 def _licfiles_append_fallback_package_files(destdir):
123 """Append package.json files as fallback to license files if a license files is missing"""
124 def _get_licenses_from_package_json(package_json): 120 def _get_licenses_from_package_json(package_json):
125 with open(os.path.join(srctree, package_json), "r") as f: 121 with open(os.path.join(srctree, package_json), "r") as f:
126 data = json.load(f) 122 data = json.load(f)
127 if "license" in data: 123 if "license" in data:
128 licenses = data["license"].split(" ") 124 licenses = data["license"].split(" ")
129 licenses = [license.strip("()") for license in licenses if license != "OR" and license != "AND"] 125 licenses = [license.strip("()") for license in licenses if license != "OR" and license != "AND"]
130 return ["${COMMON_LICENSE_DIR}/" + license for license in licenses], licenses 126 return [], licenses
131 else: 127 else:
132 return [package_json], None 128 return [package_json], None
133 129
134 fallback = True
135 basedir = os.path.join(srctree, destdir) 130 basedir = os.path.join(srctree, destdir)
136 for fn in os.listdir(basedir): 131 licfiles = find_license_files(basedir)
137 upper = fn.upper() 132 if len(licfiles) > 0:
138 if upper.startswith("COPYING") or "LICENCE" in upper or "LICENSE" in upper: 133 return licfiles, None
139 fallback = False 134 else:
140 if fallback: 135 # A license wasn't found in the package directory, so we'll use the package.json metadata
141 pkg_json = os.path.join(basedir, "package.json") 136 pkg_json = os.path.join(basedir, "package.json")
142 return _get_licenses_from_package_json(pkg_json) 137 return _get_licenses_from_package_json(pkg_json)
143 return [], None 138
139 def _get_package_licenses(destdir, package):
140 (package_licfiles, package_licenses) = _find_package_licenses(destdir)
141 if package_licfiles:
142 licfiles.extend(package_licfiles)
143 else:
144 fallback_licenses[package] = package_licenses
144 145
145 # Handle the dependencies 146 # Handle the dependencies
146 def _handle_dependency(name, params, destdir): 147 def _handle_dependency(name, params, destdir):
147 deptree = destdir.split('node_modules/') 148 deptree = destdir.split('node_modules/')
148 suffix = "-".join([npm_package(dep) for dep in deptree]) 149 suffix = "-".join([npm_package(dep) for dep in deptree])
149 packages["${PN}" + suffix] = destdir 150 packages["${PN}" + suffix] = destdir
150 (fallback_licfiles, common_lics) = _licfiles_append_fallback_package_files(destdir) 151 _get_package_licenses(destdir, "${PN}" + suffix)
151 licfiles.extend(fallback_licfiles)
152 if common_lics:
153 fallback_licenses["${PN}" + suffix] = common_lics
154 152
155 with open(shrinkwrap_file, "r") as f: 153 with open(shrinkwrap_file, "r") as f:
156 shrinkwrap = json.load(f) 154 shrinkwrap = json.load(f)
157
158 foreach_dependencies(shrinkwrap, _handle_dependency, dev) 155 foreach_dependencies(shrinkwrap, _handle_dependency, dev)
159 156
157 # Handle the parent package
158 packages["${PN}"] = ""
159 _get_package_licenses(srctree, "${PN}")
160
160 return licfiles, packages, fallback_licenses 161 return licfiles, packages, fallback_licenses
161 162
162 # Handle the peer dependencies 163 # Handle the peer dependencies
@@ -279,48 +280,11 @@ class NpmRecipeHandler(RecipeHandler):
279 280
280 bb.note("Handling licences ...") 281 bb.note("Handling licences ...")
281 (licfiles, packages, fallback_licenses) = self._handle_licenses(srctree, shrinkwrap_file, dev) 282 (licfiles, packages, fallback_licenses) = self._handle_licenses(srctree, shrinkwrap_file, dev)
282 283 licvalues = match_licenses(licfiles, srctree, d)
283 def _guess_odd_license(licfiles): 284 split_pkg_licenses(licvalues, packages, lines_after, fallback_licenses)
284 import bb 285 fallback_licenses_flat = [license for sublist in fallback_licenses.values() for license in sublist]
285 286 extravalues["LIC_FILES_CHKSUM"] = generate_common_licenses_chksums(fallback_licenses_flat, d)
286 md5sums = get_license_md5sums(d, linenumbers=True) 287 extravalues["LICENSE"] = fallback_licenses_flat
287
288 def _resolve_licfile(srctree, licfile):
289 match = re.search(r'\$\{COMMON_LICENSE_DIR\}/(.+)$', licfile)
290 if match:
291 license = match.group(1)
292 commonlicdir = d.getVar('COMMON_LICENSE_DIR')
293 return os.path.join(commonlicdir, license)
294
295 return os.path.join(srctree, licfile)
296
297 chksums = []
298 licenses = []
299 md5value = None
300 for licfile in licfiles:
301 f = _resolve_licfile(srctree, licfile)
302 try:
303 md5value = bb.utils.md5_file(f)
304 except FileNotFoundError:
305 logger.info("Could not determine license for '%s'" % licfile)
306 (license, beginline, endline, md5) = md5sums.get(md5value,
307 (None, "", "", ""))
308 if not license:
309 license = "Unknown"
310 logger.info("Please add the following line for '%s' to a "
311 "'lib/recipetool/licenses.csv' and replace `Unknown`, "
312 "`X`, `Y` and `MD5` with the license, begin line, "
313 "end line and partial MD5 checksum:\n" \
314 "%s,Unknown,X,Y,MD5" % (licfile, md5value))
315 chksums.append("file://%s%s%s;md5=%s" % (licfile,
316 ";beginline=%s" % (beginline) if beginline else "",
317 ";endline=%s" % (endline) if endline else "",
318 md5 if md5 else md5value))
319 licenses.append((license, licfile, md5value))
320 return (licenses, chksums, fallback_licenses)
321
322 (licenses, extravalues["LIC_FILES_CHKSUM"], fallback_licenses) = _guess_odd_license(licfiles)
323 split_pkg_licenses([*licenses, *find_licenses(srctree, d)], packages, lines_after, fallback_licenses)
324 288
325 classes.append("npm") 289 classes.append("npm")
326 handled.append("buildsystem") 290 handled.append("buildsystem")