diff options
Diffstat (limited to 'scripts/lib/recipetool/create_npm.py')
-rw-r--r-- | scripts/lib/recipetool/create_npm.py | 139 |
1 files changed, 70 insertions, 69 deletions
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py index 3394a89970..8c4cdd5234 100644 --- a/scripts/lib/recipetool/create_npm.py +++ b/scripts/lib/recipetool/create_npm.py | |||
@@ -13,10 +13,11 @@ import sys | |||
13 | import tempfile | 13 | import tempfile |
14 | import bb | 14 | import bb |
15 | from bb.fetch2.npm import NpmEnvironment | 15 | from bb.fetch2.npm import NpmEnvironment |
16 | from bb.fetch2.npm import npm_package | ||
16 | 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 | ||
17 | from recipetool.create import RecipeHandler | 19 | from recipetool.create import RecipeHandler |
18 | from recipetool.create import get_license_md5sums | 20 | from recipetool.create import generate_common_licenses_chksums |
19 | from recipetool.create import guess_license | ||
20 | from recipetool.create import split_pkg_licenses | 21 | from recipetool.create import split_pkg_licenses |
21 | logger = logging.getLogger('recipetool') | 22 | logger = logging.getLogger('recipetool') |
22 | 23 | ||
@@ -31,15 +32,6 @@ class NpmRecipeHandler(RecipeHandler): | |||
31 | """Class to handle the npm recipe creation""" | 32 | """Class to handle the npm recipe creation""" |
32 | 33 | ||
33 | @staticmethod | 34 | @staticmethod |
34 | def _npm_name(name): | ||
35 | """Generate a Yocto friendly npm name""" | ||
36 | name = re.sub("/", "-", name) | ||
37 | name = name.lower() | ||
38 | name = re.sub(r"[^\-a-z0-9]", "", name) | ||
39 | name = name.strip("-") | ||
40 | return name | ||
41 | |||
42 | @staticmethod | ||
43 | def _get_registry(lines): | 35 | def _get_registry(lines): |
44 | """Get the registry value from the 'npm://registry' url""" | 36 | """Get the registry value from the 'npm://registry' url""" |
45 | registry = None | 37 | registry = None |
@@ -120,41 +112,71 @@ class NpmRecipeHandler(RecipeHandler): | |||
120 | """Return the extra license files and the list of packages""" | 112 | """Return the extra license files and the list of packages""" |
121 | licfiles = [] | 113 | licfiles = [] |
122 | 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 | ||
123 | 130 | ||
124 | # Handle the parent package | ||
125 | packages["${PN}"] = "" | ||
126 | |||
127 | def _licfiles_append_fallback_readme_files(destdir): | ||
128 | """Append README files as fallback to license files if a license files is missing""" | ||
129 | |||
130 | fallback = True | ||
131 | readmes = [] | ||
132 | basedir = os.path.join(srctree, destdir) | 131 | basedir = os.path.join(srctree, destdir) |
133 | for fn in os.listdir(basedir): | 132 | licfiles = find_license_files(basedir) |
134 | upper = fn.upper() | 133 | if len(licfiles) > 0: |
135 | if upper.startswith("README"): | 134 | return licfiles, None |
136 | fullpath = os.path.join(basedir, fn) | 135 | else: |
137 | readmes.append(fullpath) | 136 | # A license wasn't found in the package directory, so we'll use the package.json metadata |
138 | if upper.startswith("COPYING") or "LICENCE" in upper or "LICENSE" in upper: | 137 | pkg_json = os.path.join(basedir, "package.json") |
139 | fallback = False | 138 | return _get_licenses_from_package_json(pkg_json) |
140 | if fallback: | 139 | |
141 | for readme in readmes: | 140 | def _get_package_licenses(destdir, package): |
142 | licfiles.append(os.path.relpath(readme, srctree)) | 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 | ||
143 | 146 | ||
144 | # Handle the dependencies | 147 | # Handle the dependencies |
145 | def _handle_dependency(name, params, deptree): | 148 | def _handle_dependency(name, params, destdir): |
146 | suffix = "-".join([self._npm_name(dep) for dep in deptree]) | 149 | deptree = destdir.split('node_modules/') |
147 | destdirs = [os.path.join("node_modules", dep) for dep in deptree] | 150 | suffix = "-".join([npm_package(dep) for dep in deptree]) |
148 | destdir = os.path.join(*destdirs) | 151 | packages["${PN}" + suffix] = destdir |
149 | packages["${PN}-" + suffix] = destdir | 152 | _get_package_licenses(destdir, "${PN}" + suffix) |
150 | _licfiles_append_fallback_readme_files(destdir) | ||
151 | 153 | ||
152 | with open(shrinkwrap_file, "r") as f: | 154 | with open(shrinkwrap_file, "r") as f: |
153 | shrinkwrap = json.load(f) | 155 | shrinkwrap = json.load(f) |
154 | |||
155 | foreach_dependencies(shrinkwrap, _handle_dependency, dev) | 156 | foreach_dependencies(shrinkwrap, _handle_dependency, dev) |
156 | 157 | ||
157 | return licfiles, packages | 158 | # Handle the parent package |
159 | packages["${PN}"] = "" | ||
160 | _get_package_licenses(srctree, "${PN}") | ||
161 | |||
162 | return licfiles, packages, fallback_licenses | ||
163 | |||
164 | # Handle the peer dependencies | ||
165 | def _handle_peer_dependency(self, shrinkwrap_file): | ||
166 | """Check if package has peer dependencies and show warning if it is the case""" | ||
167 | with open(shrinkwrap_file, "r") as 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) | ||
178 | |||
179 | |||
158 | 180 | ||
159 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 181 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
160 | """Handle the npm recipe creation""" | 182 | """Handle the npm recipe creation""" |
@@ -173,7 +195,7 @@ class NpmRecipeHandler(RecipeHandler): | |||
173 | if "name" not in data or "version" not in data: | 195 | if "name" not in data or "version" not in data: |
174 | return False | 196 | return False |
175 | 197 | ||
176 | extravalues["PN"] = self._npm_name(data["name"]) | 198 | extravalues["PN"] = npm_package(data["name"]) |
177 | extravalues["PV"] = data["version"] | 199 | extravalues["PV"] = data["version"] |
178 | 200 | ||
179 | if "description" in data: | 201 | if "description" in data: |
@@ -242,7 +264,7 @@ class NpmRecipeHandler(RecipeHandler): | |||
242 | value = origvalue.replace("version=" + data["version"], "version=${PV}") | 264 | value = origvalue.replace("version=" + data["version"], "version=${PV}") |
243 | value = value.replace("version=latest", "version=${PV}") | 265 | value = value.replace("version=latest", "version=${PV}") |
244 | values = [line.strip() for line in value.strip('\n').splitlines()] | 266 | values = [line.strip() for line in value.strip('\n').splitlines()] |
245 | if "dependencies" in shrinkwrap: | 267 | if "dependencies" in shrinkwrap.get("packages", {}).get("", {}): |
246 | values.append(url_recipe) | 268 | values.append(url_recipe) |
247 | return values, None, 4, False | 269 | return values, None, 4, False |
248 | 270 | ||
@@ -258,40 +280,19 @@ class NpmRecipeHandler(RecipeHandler): | |||
258 | fetcher.unpack(srctree) | 280 | fetcher.unpack(srctree) |
259 | 281 | ||
260 | bb.note("Handling licences ...") | 282 | bb.note("Handling licences ...") |
261 | (licfiles, packages) = self._handle_licenses(srctree, shrinkwrap_file, dev) | 283 | (licfiles, packages, fallback_licenses) = self._handle_licenses(srctree, shrinkwrap_file, dev) |
262 | 284 | licvalues = match_licenses(licfiles, srctree, d) | |
263 | def _guess_odd_license(licfiles): | 285 | split_pkg_licenses(licvalues, packages, lines_after, fallback_licenses) |
264 | import bb | 286 | fallback_licenses_flat = [license for sublist in fallback_licenses.values() for license in sublist] |
265 | 287 | extravalues["LIC_FILES_CHKSUM"] = generate_common_licenses_chksums(fallback_licenses_flat, d) | |
266 | md5sums = get_license_md5sums(d, linenumbers=True) | 288 | extravalues["LICENSE"] = fallback_licenses_flat |
267 | |||
268 | chksums = [] | ||
269 | licenses = [] | ||
270 | for licfile in licfiles: | ||
271 | f = os.path.join(srctree, licfile) | ||
272 | md5value = bb.utils.md5_file(f) | ||
273 | (license, beginline, endline, md5) = md5sums.get(md5value, | ||
274 | (None, "", "", "")) | ||
275 | if not license: | ||
276 | license = "Unknown" | ||
277 | logger.info("Please add the following line for '%s' to a " | ||
278 | "'lib/recipetool/licenses.csv' and replace `Unknown`, " | ||
279 | "`X`, `Y` and `MD5` with the license, begin line, " | ||
280 | "end line and partial MD5 checksum:\n" \ | ||
281 | "%s,Unknown,X,Y,MD5" % (licfile, md5value)) | ||
282 | chksums.append("file://%s%s%s;md5=%s" % (licfile, | ||
283 | ";beginline=%s" % (beginline) if beginline else "", | ||
284 | ";endline=%s" % (endline) if endline else "", | ||
285 | md5 if md5 else md5value)) | ||
286 | licenses.append((license, licfile, md5value)) | ||
287 | return (licenses, chksums) | ||
288 | |||
289 | (licenses, extravalues["LIC_FILES_CHKSUM"]) = _guess_odd_license(licfiles) | ||
290 | split_pkg_licenses([*licenses, *guess_license(srctree, d)], packages, lines_after) | ||
291 | 289 | ||
292 | classes.append("npm") | 290 | classes.append("npm") |
293 | handled.append("buildsystem") | 291 | handled.append("buildsystem") |
294 | 292 | ||
293 | # Check if package has peer dependencies and inform the user | ||
294 | self._handle_peer_dependency(shrinkwrap_file) | ||
295 | |||
295 | return True | 296 | return True |
296 | 297 | ||
297 | def register_recipe_handlers(handlers): | 298 | def register_recipe_handlers(handlers): |