diff options
Diffstat (limited to 'scripts/lib/recipetool/create_npm.py')
-rw-r--r-- | scripts/lib/recipetool/create_npm.py | 103 |
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 | ||
8 | import json | 8 | import json |
9 | import logging | ||
9 | import os | 10 | import os |
10 | import re | 11 | import re |
11 | import sys | 12 | import sys |
12 | import tempfile | 13 | import tempfile |
13 | import bb | 14 | import bb |
14 | from bb.fetch2.npm import NpmEnvironment | 15 | from bb.fetch2.npm import NpmEnvironment |
16 | from bb.fetch2.npm import npm_package | ||
15 | from bb.fetch2.npmsw import foreach_dependencies | 17 | from bb.fetch2.npmsw import foreach_dependencies |
16 | from recipetool.create import RecipeHandler | 18 | from recipetool.create import RecipeHandler |
19 | from recipetool.create import get_license_md5sums | ||
17 | from recipetool.create import guess_license | 20 | from recipetool.create import guess_license |
18 | from recipetool.create import split_pkg_licenses | 21 | from recipetool.create import split_pkg_licenses |
22 | logger = logging.getLogger('recipetool') | ||
19 | 23 | ||
20 | TINFOIL = None | 24 | TINFOIL = 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 | ||
257 | def register_recipe_handlers(handlers): | 308 | def register_recipe_handlers(handlers): |