diff options
Diffstat (limited to 'scripts/lib/recipetool/create_npm.py')
-rw-r--r-- | scripts/lib/recipetool/create_npm.py | 103 |
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 | ||
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 |
18 | from oe.license_finder import match_licenses, find_license_files | ||
16 | from recipetool.create import RecipeHandler | 19 | from recipetool.create import RecipeHandler |
17 | from recipetool.create import guess_license | 20 | from recipetool.create import generate_common_licenses_chksums |
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 |
@@ -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 | ||
257 | def register_recipe_handlers(handlers): | 298 | def register_recipe_handlers(handlers): |