def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): import bb.utils import oe.package from collections import OrderedDict if 'buildsystem' in handled: return False def read_package_json(fn): with open(fn, 'r', errors='surrogateescape') as f: return json.loads(f.read()) files = RecipeHandler.checkfiles(srctree, ['package.json']) if files: d = bb.data.createCopy(tinfoil.config_data) npm_bindir = self._ensure_npm() if not npm_bindir: sys.exit(14) d.prependVar('PATH', '%s:' % npm_bindir) data = read_package_json(files[0]) if 'name' in data and 'version' in data: extravalues['PN'] = data['name'] extravalues['PV'] = data['version'] classes.append('npm') handled.append('buildsystem') if 'description' in data: extravalues['SUMMARY'] = data['description'] if 'homepage' in data: extravalues['HOMEPAGE'] = data['homepage'] fetchdev = extravalues['fetchdev'] or None deps, optdeps, devdeps = self.get_npm_package_dependencies(data, fetchdev) self._handle_dependencies(d, deps, optdeps, devdeps, lines_before, srctree) # Shrinkwrap localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm') self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before, d) # Lockdown self._lockdown(srctree, localfilesdir, extravalues, lines_before, d) # Split each npm module out to is own package npmpackages = oe.package.npm_split_package_dirs(srctree) licvalues = None for item in handled: if isinstance(item, tuple): if item[0] == 'license': licvalues = item[1] break if not licvalues: licvalues = handle_license_vars(srctree, lines_before, handled, extravalues, d) if licvalues: # Augment the license list with information we have in the packages licenses = {} license = self._handle_license(data) if license: licenses['${PN}'] = license for pkgname, pkgitem in npmpackages.items(): _, pdata = pkgitem license = self._handle_license(pdata) if license: licenses[pkgname] = license # Now write out the package-specific license values # We need to strip out the json data dicts for this since split_pkg_licenses # isn't expecting it packages = OrderedDict((x,y[0]) for x,y in npmpackages.items()) packages['${PN}'] = '' pkglicenses = split_pkg_licenses(licvalues, packages, lines_after, licenses) all_licenses = list(set([item.replace('_', ' ') for pkglicense in pkglicenses.values() for item in pkglicense])) if '&' in all_licenses: all_licenses.remove('&') extravalues['LICENSE'] = ' & '.join(all_licenses) # Need to move S setting after inherit npm for i, line in enumerate(lines_before): if line.startswith('S ='): lines_before.pop(i) lines_after.insert(0, '# Must be set after inherit npm since that itself sets S') lines_after.insert(1, line) break return True return False
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): """Handle the npm recipe creation""" if "buildsystem" in handled: return False files = RecipeHandler.checkfiles(srctree, ["package.json"]) if not files: return False with open(files[0], "r") as f: data = json.load(f) if "name" not in data or "version" not in data: return False extravalues["PN"] = self._npm_name(data["name"]) extravalues["PV"] = data["version"] if "description" in data: extravalues["SUMMARY"] = data["description"] if "homepage" in data: extravalues["HOMEPAGE"] = data["homepage"] dev = bb.utils.to_boolean(str(extravalues.get("NPM_INSTALL_DEV", "0")), False) registry = self._get_registry(lines_before) bb.note("Checking if npm is available ...") # The native npm is used here (and not the host one) to ensure that the # npm version is high enough to ensure an efficient dependency tree # resolution and avoid issue with the shrinkwrap file format. # Moreover the native npm is mandatory for the build. bindir = self._ensure_npm() d = bb.data.createCopy(TINFOIL.config_data) d.prependVar("PATH", bindir + ":") d.setVar("S", srctree) bb.note("Generating shrinkwrap file ...") # To generate the shrinkwrap file the dependencies have to be installed # first. During the generation process some files may be updated / # deleted. By default devtool tracks the diffs in the srctree and raises # errors when finishing the recipe if some diffs are found. git_exclude_file = os.path.join(srctree, ".git", "info", "exclude") if os.path.exists(git_exclude_file): with open(git_exclude_file, "r+") as f: lines = f.readlines() for line in ["/node_modules/", "/npm-shrinkwrap.json"]: if line not in lines: f.write(line + "\n") lock_file = os.path.join(srctree, "package-lock.json") lock_copy = lock_file + ".copy" if os.path.exists(lock_file): bb.utils.copyfile(lock_file, lock_copy) self._run_npm_install(d, srctree, registry, dev) shrinkwrap_file = self._generate_shrinkwrap(d, srctree, dev) if os.path.exists(lock_copy): bb.utils.movefile(lock_copy, lock_file) # Add the shrinkwrap file as 'extrafiles' shrinkwrap_copy = shrinkwrap_file + ".copy" bb.utils.copyfile(shrinkwrap_file, shrinkwrap_copy) extravalues.setdefault("extrafiles", {}) extravalues["extrafiles"]["npm-shrinkwrap.json"] = shrinkwrap_copy url_local = "npmsw://%s" % shrinkwrap_file url_recipe = "npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json" if dev: url_local += ";dev=1" url_recipe += ";dev=1" # Add the npmsw url in the SRC_URI of the generated recipe def _handle_srcuri(varname, origvalue, op, newlines): """Update the version value and add the 'npmsw://' url""" value = origvalue.replace("version=" + data["version"], "version=${PV}") value = value.replace("version=latest", "version=${PV}") values = [line.strip() for line in value.strip('\n').splitlines()] values.append(url_recipe) return values, None, 4, False (_, newlines) = bb.utils.edit_metadata(lines_before, ["SRC_URI"], _handle_srcuri) lines_before[:] = [line.rstrip('\n') for line in newlines] # In order to generate correct licence checksums in the recipe the # dependencies have to be fetched again using the npmsw url bb.note("Fetching npm dependencies ...") bb.utils.remove(os.path.join(srctree, "node_modules"), recurse=True) fetcher = bb.fetch2.Fetch([url_local], d) fetcher.download() fetcher.unpack(srctree) bb.note("Handling licences ...") (licfiles, packages) = self._handle_licenses(srctree, shrinkwrap_file, dev) extravalues["LIC_FILES_CHKSUM"] = licfiles split_pkg_licenses(guess_license(srctree, d), packages, lines_after, []) classes.append("npm") handled.append("buildsystem") return True
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): import bb.utils import oe from collections import OrderedDict if 'buildsystem' in handled: return False def read_package_json(fn): with open(fn, 'r', errors='surrogateescape') as f: return json.loads(f.read()) files = RecipeHandler.checkfiles(srctree, ['package.json']) if files: check_npm(tinfoil.config_data) data = read_package_json(files[0]) if 'name' in data and 'version' in data: extravalues['PN'] = data['name'] extravalues['PV'] = data['version'] classes.append('npm') handled.append('buildsystem') if 'description' in data: extravalues['SUMMARY'] = data['description'] if 'homepage' in data: extravalues['HOMEPAGE'] = data['homepage'] deps = data.get('dependencies', {}) updated = self._handle_dependencies(tinfoil.config_data, deps, lines_before, srctree) if updated: # We need to redo the license stuff self._replace_license_vars(srctree, lines_before, handled, extravalues, tinfoil.config_data) # Shrinkwrap localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm') self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before) # Lockdown self._lockdown(srctree, localfilesdir, extravalues, lines_before) # Split each npm module out to is own package npmpackages = oe.package.npm_split_package_dirs(srctree) for item in handled: if isinstance(item, tuple): if item[0] == 'license': licvalues = item[1] break if licvalues: # Augment the license list with information we have in the packages licenses = {} license = self._handle_license(data) if license: licenses['${PN}'] = license for pkgname, pkgitem in npmpackages.items(): _, pdata = pkgitem license = self._handle_license(pdata) if license: licenses[pkgname] = license # Now write out the package-specific license values # We need to strip out the json data dicts for this since split_pkg_licenses # isn't expecting it packages = OrderedDict( (x, y[0]) for x, y in npmpackages.items()) packages['${PN}'] = '' pkglicenses = split_pkg_licenses(licvalues, packages, lines_after, licenses) all_licenses = list( set([ item for pkglicense in pkglicenses.values() for item in pkglicense ])) # Go back and update the LICENSE value since we have a bit more # information than when that was written out (and we know all apply # vs. there being a choice, so we can join them with &) for i, line in enumerate(lines_before): if line.startswith('LICENSE = '): lines_before[i] = 'LICENSE = "%s"' % ' & '.join( all_licenses) break # Need to move S setting after inherit npm for i, line in enumerate(lines_before): if line.startswith('S ='): lines_before.pop(i) lines_after.insert( 0, '# Must be set after inherit npm since that itself sets S' ) lines_after.insert(1, line) break return True return False
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): import bb.utils import oe from collections import OrderedDict if 'buildsystem' in handled: return False def read_package_json(fn): with open(fn, 'r', errors='surrogateescape') as f: return json.loads(f.read()) files = RecipeHandler.checkfiles(srctree, ['package.json']) if files: data = read_package_json(files[0]) if 'name' in data and 'version' in data: extravalues['PN'] = data['name'] extravalues['PV'] = data['version'] classes.append('npm') handled.append('buildsystem') if 'description' in data: extravalues['SUMMARY'] = data['description'] if 'homepage' in data: extravalues['HOMEPAGE'] = data['homepage'] deps = data.get('dependencies', {}) updated = self._handle_dependencies(tinfoil.config_data, deps, lines_before, srctree) if updated: # We need to redo the license stuff self._replace_license_vars(srctree, lines_before, handled, extravalues, tinfoil.config_data) # Shrinkwrap localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm') self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before) # Lockdown self._lockdown(srctree, localfilesdir, extravalues, lines_before) # Split each npm module out to is own package npmpackages = oe.package.npm_split_package_dirs(srctree) for item in handled: if isinstance(item, tuple): if item[0] == 'license': licvalues = item[1] break if licvalues: # Augment the license list with information we have in the packages licenses = {} license = self._handle_license(data) if license: licenses['${PN}'] = license for pkgname, pkgitem in npmpackages.items(): _, pdata = pkgitem license = self._handle_license(pdata) if license: licenses[pkgname] = license # Now write out the package-specific license values # We need to strip out the json data dicts for this since split_pkg_licenses # isn't expecting it packages = OrderedDict((x,y[0]) for x,y in npmpackages.items()) packages['${PN}'] = '' pkglicenses = split_pkg_licenses(licvalues, packages, lines_after, licenses) all_licenses = list(set([item for pkglicense in pkglicenses.values() for item in pkglicense])) # Go back and update the LICENSE value since we have a bit more # information than when that was written out (and we know all apply # vs. there being a choice, so we can join them with &) for i, line in enumerate(lines_before): if line.startswith('LICENSE = '): lines_before[i] = 'LICENSE = "%s"' % ' & '.join(all_licenses) break # Need to move S setting after inherit npm for i, line in enumerate(lines_before): if line.startswith('S ='): lines_before.pop(i) lines_after.insert(0, '# Must be set after inherit npm since that itself sets S') lines_after.insert(1, line) break return True return False