summaryrefslogtreecommitdiffstats
path: root/scripts/lib/recipetool/create_npm.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/recipetool/create_npm.py')
-rw-r--r--scripts/lib/recipetool/create_npm.py103
1 files changed, 72 insertions, 31 deletions
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index 2bcae91dfa..8c4cdd5234 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -6,16 +6,20 @@
6"""Recipe creation tool - npm module support plugin""" 6"""Recipe creation tool - npm module support plugin"""
7 7
8import json 8import json
9import logging
9import os 10import os
10import re 11import re
11import sys 12import sys
12import tempfile 13import tempfile
13import bb 14import bb
14from bb.fetch2.npm import NpmEnvironment 15from bb.fetch2.npm import NpmEnvironment
16from bb.fetch2.npm import npm_package
15from bb.fetch2.npmsw import foreach_dependencies 17from bb.fetch2.npmsw import foreach_dependencies
18from oe.license_finder import match_licenses, find_license_files
16from recipetool.create import RecipeHandler 19from recipetool.create import RecipeHandler
17from recipetool.create import guess_license 20from recipetool.create import generate_common_licenses_chksums
18from recipetool.create import split_pkg_licenses 21from recipetool.create import split_pkg_licenses
22logger = logging.getLogger('recipetool')
19 23
20TINFOIL = None 24TINFOIL = None
21 25
@@ -28,15 +32,6 @@ class NpmRecipeHandler(RecipeHandler):
28 """Class to handle the npm recipe creation""" 32 """Class to handle the npm recipe creation"""
29 33
30 @staticmethod 34 @staticmethod
31 def _npm_name(name):
32 """Generate a Yocto friendly npm name"""
33 name = re.sub("/", "-", name)
34 name = name.lower()
35 name = re.sub(r"[^\-a-z0-9]", "", name)
36 name = name.strip("-")
37 return name
38
39 @staticmethod
40 def _get_registry(lines): 35 def _get_registry(lines):
41 """Get the registry value from the 'npm://registry' url""" 36 """Get the registry value from the 'npm://registry' url"""
42 registry = None 37 registry = None
@@ -117,31 +112,71 @@ class NpmRecipeHandler(RecipeHandler):
117 """Return the extra license files and the list of packages""" 112 """Return the extra license files and the list of packages"""
118 licfiles = [] 113 licfiles = []
119 packages = {} 114 packages = {}
115 # Licenses from package.json will point to COMMON_LICENSE_DIR so we need
116 # to associate them explicitely to packages for split_pkg_licenses()
117 fallback_licenses = dict()
118
119 def _find_package_licenses(destdir):
120 """Either find license files, or use package.json metadata"""
121 def _get_licenses_from_package_json(package_json):
122 with open(os.path.join(srctree, package_json), "r") as f:
123 data = json.load(f)
124 if "license" in data:
125 licenses = data["license"].split(" ")
126 licenses = [license.strip("()") for license in licenses if license != "OR" and license != "AND"]
127 return [], licenses
128 else:
129 return [package_json], None
130
131 basedir = os.path.join(srctree, destdir)
132 licfiles = find_license_files(basedir)
133 if len(licfiles) > 0:
134 return licfiles, None
135 else:
136 # A license wasn't found in the package directory, so we'll use the package.json metadata
137 pkg_json = os.path.join(basedir, "package.json")
138 return _get_licenses_from_package_json(pkg_json)
139
140 def _get_package_licenses(destdir, package):
141 (package_licfiles, package_licenses) = _find_package_licenses(destdir)
142 if package_licfiles:
143 licfiles.extend(package_licfiles)
144 else:
145 fallback_licenses[package] = package_licenses
120 146
121 def _licfiles_append(licfile): 147 # Handle the dependencies
122 """Append 'licfile' to the license files list""" 148 def _handle_dependency(name, params, destdir):
123 licfilepath = os.path.join(srctree, licfile) 149 deptree = destdir.split('node_modules/')
124 licmd5 = bb.utils.md5_file(licfilepath) 150 suffix = "-".join([npm_package(dep) for dep in deptree])
125 licfiles.append("file://%s;md5=%s" % (licfile, licmd5)) 151 packages["${PN}" + suffix] = destdir
152 _get_package_licenses(destdir, "${PN}" + suffix)
153
154 with open(shrinkwrap_file, "r") as f:
155 shrinkwrap = json.load(f)
156 foreach_dependencies(shrinkwrap, _handle_dependency, dev)
126 157
127 # Handle the parent package 158 # Handle the parent package
128 _licfiles_append("package.json")
129 packages["${PN}"] = "" 159 packages["${PN}"] = ""
160 _get_package_licenses(srctree, "${PN}")
130 161
131 # Handle the dependencies 162 return licfiles, packages, fallback_licenses
132 def _handle_dependency(name, params, deptree): 163
133 suffix = "-".join([self._npm_name(dep) for dep in deptree]) 164 # Handle the peer dependencies
134 destdirs = [os.path.join("node_modules", dep) for dep in deptree] 165 def _handle_peer_dependency(self, shrinkwrap_file):
135 destdir = os.path.join(*destdirs) 166 """Check if package has peer dependencies and show warning if it is the case"""
136 _licfiles_append(os.path.join(destdir, "package.json"))
137 packages["${PN}-" + suffix] = destdir
138
139 with open(shrinkwrap_file, "r") as f: 167 with open(shrinkwrap_file, "r") as f:
140 shrinkwrap = json.load(f) 168 shrinkwrap = json.load(f)
169
170 packages = shrinkwrap.get("packages", {})
171 peer_deps = packages.get("", {}).get("peerDependencies", {})
172
173 for peer_dep in peer_deps:
174 peer_dep_yocto_name = npm_package(peer_dep)
175 bb.warn(peer_dep + " is a peer dependencie of the actual package. " +
176 "Please add this peer dependencie to the RDEPENDS variable as %s and generate its recipe with devtool"
177 % peer_dep_yocto_name)
141 178
142 foreach_dependencies(shrinkwrap, _handle_dependency, dev)
143 179
144 return licfiles, packages
145 180
146 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): 181 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
147 """Handle the npm recipe creation""" 182 """Handle the npm recipe creation"""
@@ -160,7 +195,7 @@ class NpmRecipeHandler(RecipeHandler):
160 if "name" not in data or "version" not in data: 195 if "name" not in data or "version" not in data:
161 return False 196 return False
162 197
163 extravalues["PN"] = self._npm_name(data["name"]) 198 extravalues["PN"] = npm_package(data["name"])
164 extravalues["PV"] = data["version"] 199 extravalues["PV"] = data["version"]
165 200
166 if "description" in data: 201 if "description" in data:
@@ -229,7 +264,7 @@ class NpmRecipeHandler(RecipeHandler):
229 value = origvalue.replace("version=" + data["version"], "version=${PV}") 264 value = origvalue.replace("version=" + data["version"], "version=${PV}")
230 value = value.replace("version=latest", "version=${PV}") 265 value = value.replace("version=latest", "version=${PV}")
231 values = [line.strip() for line in value.strip('\n').splitlines()] 266 values = [line.strip() for line in value.strip('\n').splitlines()]
232 if "dependencies" in shrinkwrap: 267 if "dependencies" in shrinkwrap.get("packages", {}).get("", {}):
233 values.append(url_recipe) 268 values.append(url_recipe)
234 return values, None, 4, False 269 return values, None, 4, False
235 270
@@ -245,13 +280,19 @@ class NpmRecipeHandler(RecipeHandler):
245 fetcher.unpack(srctree) 280 fetcher.unpack(srctree)
246 281
247 bb.note("Handling licences ...") 282 bb.note("Handling licences ...")
248 (licfiles, packages) = self._handle_licenses(srctree, shrinkwrap_file, dev) 283 (licfiles, packages, fallback_licenses) = self._handle_licenses(srctree, shrinkwrap_file, dev)
249 extravalues["LIC_FILES_CHKSUM"] = licfiles 284 licvalues = match_licenses(licfiles, srctree, d)
250 split_pkg_licenses(guess_license(srctree, d), packages, lines_after, []) 285 split_pkg_licenses(licvalues, packages, lines_after, fallback_licenses)
286 fallback_licenses_flat = [license for sublist in fallback_licenses.values() for license in sublist]
287 extravalues["LIC_FILES_CHKSUM"] = generate_common_licenses_chksums(fallback_licenses_flat, d)
288 extravalues["LICENSE"] = fallback_licenses_flat
251 289
252 classes.append("npm") 290 classes.append("npm")
253 handled.append("buildsystem") 291 handled.append("buildsystem")
254 292
293 # Check if package has peer dependencies and inform the user
294 self._handle_peer_dependency(shrinkwrap_file)
295
255 return True 296 return True
256 297
257def register_recipe_handlers(handlers): 298def register_recipe_handlers(handlers):