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, 77 insertions, 26 deletions
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index 2bcae91dfa..113a89f6a6 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
16from recipetool.create import RecipeHandler 18from recipetool.create import RecipeHandler
19from recipetool.create import get_license_md5sums
17from recipetool.create import guess_license 20from recipetool.create import guess_license
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
@@ -118,23 +113,32 @@ class NpmRecipeHandler(RecipeHandler):
118 licfiles = [] 113 licfiles = []
119 packages = {} 114 packages = {}
120 115
121 def _licfiles_append(licfile):
122 """Append 'licfile' to the license files list"""
123 licfilepath = os.path.join(srctree, licfile)
124 licmd5 = bb.utils.md5_file(licfilepath)
125 licfiles.append("file://%s;md5=%s" % (licfile, licmd5))
126
127 # Handle the parent package 116 # Handle the parent package
128 _licfiles_append("package.json")
129 packages["${PN}"] = "" 117 packages["${PN}"] = ""
130 118
119 def _licfiles_append_fallback_readme_files(destdir):
120 """Append README files as fallback to license files if a license files is missing"""
121
122 fallback = True
123 readmes = []
124 basedir = os.path.join(srctree, destdir)
125 for fn in os.listdir(basedir):
126 upper = fn.upper()
127 if upper.startswith("README"):
128 fullpath = os.path.join(basedir, fn)
129 readmes.append(fullpath)
130 if upper.startswith("COPYING") or "LICENCE" in upper or "LICENSE" in upper:
131 fallback = False
132 if fallback:
133 for readme in readmes:
134 licfiles.append(os.path.relpath(readme, srctree))
135
131 # Handle the dependencies 136 # Handle the dependencies
132 def _handle_dependency(name, params, deptree): 137 def _handle_dependency(name, params, destdir):
133 suffix = "-".join([self._npm_name(dep) for dep in deptree]) 138 deptree = destdir.split('node_modules/')
134 destdirs = [os.path.join("node_modules", dep) for dep in deptree] 139 suffix = "-".join([npm_package(dep) for dep in deptree])
135 destdir = os.path.join(*destdirs) 140 packages["${PN}" + suffix] = destdir
136 _licfiles_append(os.path.join(destdir, "package.json")) 141 _licfiles_append_fallback_readme_files(destdir)
137 packages["${PN}-" + suffix] = destdir
138 142
139 with open(shrinkwrap_file, "r") as f: 143 with open(shrinkwrap_file, "r") as f:
140 shrinkwrap = json.load(f) 144 shrinkwrap = json.load(f)
@@ -142,6 +146,23 @@ class NpmRecipeHandler(RecipeHandler):
142 foreach_dependencies(shrinkwrap, _handle_dependency, dev) 146 foreach_dependencies(shrinkwrap, _handle_dependency, dev)
143 147
144 return licfiles, packages 148 return licfiles, packages
149
150 # Handle the peer dependencies
151 def _handle_peer_dependency(self, shrinkwrap_file):
152 """Check if package has peer dependencies and show warning if it is the case"""
153 with open(shrinkwrap_file, "r") as f:
154 shrinkwrap = json.load(f)
155
156 packages = shrinkwrap.get("packages", {})
157 peer_deps = packages.get("", {}).get("peerDependencies", {})
158
159 for peer_dep in peer_deps:
160 peer_dep_yocto_name = npm_package(peer_dep)
161 bb.warn(peer_dep + " is a peer dependencie of the actual package. " +
162 "Please add this peer dependencie to the RDEPENDS variable as %s and generate its recipe with devtool"
163 % peer_dep_yocto_name)
164
165
145 166
146 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): 167 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
147 """Handle the npm recipe creation""" 168 """Handle the npm recipe creation"""
@@ -160,7 +181,7 @@ class NpmRecipeHandler(RecipeHandler):
160 if "name" not in data or "version" not in data: 181 if "name" not in data or "version" not in data:
161 return False 182 return False
162 183
163 extravalues["PN"] = self._npm_name(data["name"]) 184 extravalues["PN"] = npm_package(data["name"])
164 extravalues["PV"] = data["version"] 185 extravalues["PV"] = data["version"]
165 186
166 if "description" in data: 187 if "description" in data:
@@ -229,7 +250,7 @@ class NpmRecipeHandler(RecipeHandler):
229 value = origvalue.replace("version=" + data["version"], "version=${PV}") 250 value = origvalue.replace("version=" + data["version"], "version=${PV}")
230 value = value.replace("version=latest", "version=${PV}") 251 value = value.replace("version=latest", "version=${PV}")
231 values = [line.strip() for line in value.strip('\n').splitlines()] 252 values = [line.strip() for line in value.strip('\n').splitlines()]
232 if "dependencies" in shrinkwrap: 253 if "dependencies" in shrinkwrap.get("packages", {}).get("", {}):
233 values.append(url_recipe) 254 values.append(url_recipe)
234 return values, None, 4, False 255 return values, None, 4, False
235 256
@@ -246,12 +267,42 @@ class NpmRecipeHandler(RecipeHandler):
246 267
247 bb.note("Handling licences ...") 268 bb.note("Handling licences ...")
248 (licfiles, packages) = self._handle_licenses(srctree, shrinkwrap_file, dev) 269 (licfiles, packages) = self._handle_licenses(srctree, shrinkwrap_file, dev)
249 extravalues["LIC_FILES_CHKSUM"] = licfiles 270
250 split_pkg_licenses(guess_license(srctree, d), packages, lines_after, []) 271 def _guess_odd_license(licfiles):
272 import bb
273
274 md5sums = get_license_md5sums(d, linenumbers=True)
275
276 chksums = []
277 licenses = []
278 for licfile in licfiles:
279 f = os.path.join(srctree, licfile)
280 md5value = bb.utils.md5_file(f)
281 (license, beginline, endline, md5) = md5sums.get(md5value,
282 (None, "", "", ""))
283 if not license:
284 license = "Unknown"
285 logger.info("Please add the following line for '%s' to a "
286 "'lib/recipetool/licenses.csv' and replace `Unknown`, "
287 "`X`, `Y` and `MD5` with the license, begin line, "
288 "end line and partial MD5 checksum:\n" \
289 "%s,Unknown,X,Y,MD5" % (licfile, md5value))
290 chksums.append("file://%s%s%s;md5=%s" % (licfile,
291 ";beginline=%s" % (beginline) if beginline else "",
292 ";endline=%s" % (endline) if endline else "",
293 md5 if md5 else md5value))
294 licenses.append((license, licfile, md5value))
295 return (licenses, chksums)
296
297 (licenses, extravalues["LIC_FILES_CHKSUM"]) = _guess_odd_license(licfiles)
298 split_pkg_licenses([*licenses, *guess_license(srctree, d)], packages, lines_after)
251 299
252 classes.append("npm") 300 classes.append("npm")
253 handled.append("buildsystem") 301 handled.append("buildsystem")
254 302
303 # Check if package has peer dependencies and inform the user
304 self._handle_peer_dependency(shrinkwrap_file)
305
255 return True 306 return True
256 307
257def register_recipe_handlers(handlers): 308def register_recipe_handlers(handlers):