From patchwork Wed Nov 24 14:47:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Herbrechtsmeier X-Patchwork-Id: 378 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0662FC43219 for ; Wed, 24 Nov 2021 14:48:17 +0000 (UTC) Received: from EUR02-AM5-obe.outbound.protection.outlook.com (EUR02-AM5-obe.outbound.protection.outlook.com [40.107.0.72]) by mx.groups.io with SMTP id smtpd.web10.6992.1637765289962517376 for ; Wed, 24 Nov 2021 06:48:15 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@weidmueller.onmicrosoft.com header.s=selector1-weidmueller-onmicrosoft-com header.b=O9BIHlCC; spf=pass (domain: weidmueller.com, ip: 40.107.0.72, mailfrom: stefan.herbrechtsmeier-oss@weidmueller.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Vfas8hbffeEL+FnqQL8jEdV4ebltpaFnTM76SrPu/UfEZYDNonad6CBEe+fEj7z7cKe2KPeT5IG5TYKL2HHPqrvGRAz9j7yWibXdlAAIPxKXX2stEqOk+VCj6pL7TuDuIz4FNFxDi1LARV8CJzSfuuYXeNSLZ3V6CQB3wbq70L1NrwpcELfO3pYvm44YQi47T6+BiCQYgKf6S5R3MnshQuCNsm2IdLZ7/CVLxJIqOJM4kv1ie9RH38aR7+6ea+U1w9EOMWOl+gF5Iyxq40ntVHc7QU8xQY8Ki6joUurpsbN6vbyybb5Qq9Lcq4wDi7JRg3jr7wvoQY48jLAHxSQLFQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=D/ojoUW+P2y1o3vcHovXTMzY6zBSVN0THSzip2H2Ojw=; b=hdCEnH8XRzJ2zI84gIIvQ/dvLbyIeaRtLMdZIpA38Q5Hny5cIH98A+Dao2l/6G2YeKAf01O8GL9fVWypA8ZepXFVDBntNdfh5AbwaVru4Lnf80yvVL48r4QPF7YjFJIRfWzeSs7Z0mGdNotbPO4VPtwioJFyAZi77rxWbGfBdGm0Hd1UVRUGO2GAXAUh8/0deLZ0sbDiitattuXHsKqOrNRfs4fbw21sd/TvULX00q/5B792NO/cNDDnSMtTveNkNBWS8zhUtPf1YAC3wzSVkQ+f4qO0AEd5GpjhCbHTRvyD0qqN9aU8cTsyFfiiFA69aaGhpFQB2WkilvHlkrBVlQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=weidmueller.com; dmarc=pass action=none header.from=weidmueller.com; dkim=pass header.d=weidmueller.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=weidmueller.onmicrosoft.com; s=selector1-weidmueller-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=D/ojoUW+P2y1o3vcHovXTMzY6zBSVN0THSzip2H2Ojw=; b=O9BIHlCCDadHiVCjjAArzZLuHu+ENt76svhR0gkIwM0Pe4mH5d95J09I7Ujxu01rMI9WWaczZTP970kQT3Vnbpln1Xfy9Y6v5iVI+Rn8/JohekDPnuGGmXqkCROTCrxZUko+7Hm79mD2sirOaumWlPt5H9wrsiH3svgzRSKA4DI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=weidmueller.com; Received: from PAXPR08MB6969.eurprd08.prod.outlook.com (2603:10a6:102:1d8::23) by PR3PR08MB5801.eurprd08.prod.outlook.com (2603:10a6:102:81::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.22; Wed, 24 Nov 2021 14:48:10 +0000 Received: from PAXPR08MB6969.eurprd08.prod.outlook.com ([fe80::f:41c4:eb10:5010]) by PAXPR08MB6969.eurprd08.prod.outlook.com ([fe80::f:41c4:eb10:5010%7]) with mapi id 15.20.4713.026; Wed, 24 Nov 2021 14:48:10 +0000 From: Stefan Herbrechtsmeier To: openembedded-core@lists.openembedded.org, Alexander Kanavin , Jasper Orschulko , Konrad Weihmann , Martin Koppehel , Richard Purdie CC: Stefan Herbrechtsmeier Subject: [RFC PATCH 12/15] recipetool: npm: Add dependencies to SRC_URI and auto select classes Date: Wed, 24 Nov 2021 15:47:36 +0100 Message-ID: <20211124144739.2250-13-stefan.herbrechtsmeier-oss@weidmueller.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20211124144739.2250-1-stefan.herbrechtsmeier-oss@weidmueller.com> References: <20211124144739.2250-1-stefan.herbrechtsmeier-oss@weidmueller.com> X-ClientProxiedBy: AM5PR0701CA0015.eurprd07.prod.outlook.com (2603:10a6:203:51::25) To PAXPR08MB6969.eurprd08.prod.outlook.com (2603:10a6:102:1d8::23) MIME-Version: 1.0 Received: from DE10512.weidmueller.com (94.134.181.208) by AM5PR0701CA0015.eurprd07.prod.outlook.com (2603:10a6:203:51::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4734.21 via Frontend Transport; Wed, 24 Nov 2021 14:48:10 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e8dcfe0c-a6bb-43b1-da99-08d9af596f43 X-MS-TrafficTypeDiagnostic: PR3PR08MB5801: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:393; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 7Je0k51NovSg+EInl3cP+kBFaHcKv4gD7s3eL2NKa/Cp+teWy0LerNLX3xTudUUASraCkPwGkCVFYOScRJUoOuYWfOIkji77x+c4slIALkMWdoTN3Gn5iFtgUHT/ewEuwBbjkYRm4f+bE2CAhKcGStDGSOsA7FeAtzzdvbsrRDLyCIiNtWFM7KWiiOKOxd0UPNq7HfR/g35zuv+aQDdyP52Ehi+oH2WTtANZ/2q14JO3ucWwEa7G0M4rZuukmwtmHD5BkxJI2DbpDENzuSvItxB/OQT722SJjq8908ULRpYtVc1PlZLTnCv1OZy5QmqXiB+S2RKP3JVCCzDfCAIKT24SQK7nTJFi0xo+xH5/U3kCq7PEjN3remMcle2FIEaAuJ3PStBKKsU8bqHFZZNSqAjoL6Xu8FOZfCNj9LDi+BJQ8ZQHX/kczF8LefnI1BpzotUEcK332ZqcBV3nXP068o13LAuaKMuqI6pNjgiazJUs0Hu93Mu/xMV2uvXD/eqESBx3ybi9qvJq3noEgf03uJlRlXDzRLEfNy2LQDnxmwzkP5JFSbKgi7ptG8L6MkGEEX9iEx9JTWufb43C5ZZD7140EKnMZP0DVquEjMQduHrZ7U39j/6ACuZwYe160YdWNU90VFhZEwnaSjrcBjofKeJgCa+owODH40N9512QrHswWdpiSN7ceL4EYXP31yt7EbWScFOGJWVn1nzMS2PhRNKAoc/60+0xqVK+ddwMIKRN5S6ngZX0VWhfbd84deRzmUxp/QwaQ6KMUbPwmM//Uj+YiAdwkkFhPbFxP78SGPQ= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PAXPR08MB6969.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6486002)(66476007)(66946007)(52116002)(66556008)(6666004)(8936002)(107886003)(8676002)(7696005)(2616005)(83380400001)(186003)(26005)(1076003)(38100700002)(5660300002)(38350700002)(2906002)(956004)(110136005)(316002)(508600001)(4326008)(86362001)(36756003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: bJ81sGBk0/2hyiHkJmK6Obw4Jn5Vh+ku6gNln58I8H8wfQaoqEPcXpFXh/gj7CuMTZKWpJdS2ufL5tTHZ/j98wBRugSuWtTgxF4cNe6dMVF0jdRD6ALy8A7hOB6us+pmP38C7bPYD7cPz1s0SSeXv/x+BKLM0p3ZFM8IIF6Pyc872rLNqJx2vsVlad47QEmcDFRzLN+dTd2PrUP/I0PVdlp8PRhgDKOBb8jSfB/OuuJSQtc5nRf1jL0J51NJfRbIP/Sj2GciTUlfjLgFw030WOts4YrvkrTudYJLVO9x0ZYQy796DQvgklILLUDS3Ba9Wf2ZjCtrJXrYZgCQvNqN5Jbbxw+tnElCUKRMkOZ7as7UqdHPy5xcGZczjE2CyCjMBYmKamshy/T74WYHWCx2Szem+KShQlE+fcfz1wlV5DeK6j7VCg7NJ92D+70YSFVPn4rGWKdGWhazLD2/Rn7EvQqTuMxSw+YS+urzgPoYM7PenKVMxRCMXpAVzeRTXOu1FRWRr2jtPGAauy3m92YF45Kmkvspd87hyYAxojFRJ3lyj5D60gpqHPyl1wairm4VnRnUPffVS7D/xKoNryFo3X6FWVfW3hEA7AqqnQ2zFGHbgTvTUDe0rSV+F66xv6jWNn1Dc2mbbhkl/g8iFW+x7gixZFORL16UsJjR8Z6AzhOCmsDmLu9eEuOZYKSlfe2O5Z2z3cTuvL+/2xB7E2wVs3Isqqvde9AtAuZ5Vl6GQ8NGjc6OKUiDCw6Z9OXZFp5Y8EE75ve1Li1ysk92fhQUkQoreQsEuqNTJZj6uivnu24txO88UvjpURJQ4Kx3qWWxgdehbMT0fS5nH4enCmWV3LxJIQ/Htisi8rUfmghHuCDc5WR8dgXRZ/L8UwJMzQZs84KDcQNoMHNklxnAwVAJpKZ48Qt3QR1G+NPzWVYFsuUTiNGDj30Aa44qCG2ntKTuDa81XCpFisq31w7eaGuX5BWShkWp+hlzCwMQ2FF6lGs2QmX96zAt94/4NTOBxa8c7jOlY7869iVozMcoS0sB4M+EhT6s2xWMSIkmRpGwXhkCYLT6lOsux7o8NbakJ2zaGSi2MqkSCCUCWvqMOAd2iHNMZksrtbxNf58PO2iBYyI4FrJQ1fslj8b08+T319mWM+kvtcxWPlADdIJ8kWhQYFH23VHvHi3/3V+7MtZjc0LDGBICZwrEu7rS01iw1diuzgxJoWB/2mllsfeUrzqsz4s2du0ec7fakqOzAdgtO2/l02EvpGvYSRyWh99Kqmrao18E7+2GOSdBUtZuui/Wkw9cdwa0cZszYePHCiGPb4BA/ZC9SMG2EYxf7iKAydobWt4YzhO2cY/+Pn53rhGeOx0aSQzUxGpgUSSfoZ7Sd2CugZW1KSWOTESdV0rbCzoQCfiUyK1fM64XiGtihjzdrBtbF0KaBR2L6hd1HnGdocGbb9A/pk2oopP0NzP+CIg0Qxn+9Bu5G7rHegxABXW0Vn9Arqpt9EWgkNTMXZq81+izyyOZhjlU9gApUBFmXMjlfH4enYESjTP3X0gwEuebQzNmme4XHGfRrM8+MJGsZcMPEE5bAS5uJx2DEYKx/fXoUNubzWt4mgBCDd7hLw50rkALDPZa4KC8oqObpIoSVC4= X-OriginatorOrg: weidmueller.com X-MS-Exchange-CrossTenant-Network-Message-Id: e8dcfe0c-a6bb-43b1-da99-08d9af596f43 X-MS-Exchange-CrossTenant-AuthSource: PAXPR08MB6969.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Nov 2021 14:48:10.5524 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: e4289438-1c5f-4c95-a51a-ee553b8b18ec X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Xxn6JaMCzUhdl6OF5HNPG7xMIN1XxuuOGWbOoOE9XuXcOWrGB7FNhPAR/4YQsQecgUjB0b5jfenw58M4oBMyKQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PR3PR08MB5801 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 24 Nov 2021 14:48:17 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/158707 From: Stefan Herbrechtsmeier Signed-off-by: Stefan Herbrechtsmeier --- scripts/lib/recipetool/create_npm.py | 243 ++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 21 deletions(-) diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py index 3394a89970..296b84340e 100644 --- a/scripts/lib/recipetool/create_npm.py +++ b/scripts/lib/recipetool/create_npm.py @@ -39,6 +39,14 @@ class NpmRecipeHandler(RecipeHandler): name = name.strip("-") return name + @staticmethod + def _node_recipe_name(name): + """Generate a OE friendly Node.js recipe name""" + name = NpmRecipeHandler._npm_name(name) + if not name.startswith("node-"): + name = "node-" + name + return name + @staticmethod def _get_registry(lines): """Get the registry value from the 'npm://registry' url""" @@ -54,6 +62,24 @@ class NpmRecipeHandler(RecipeHandler): return registry + @staticmethod + def _get_srcdir(lines): + """Get the source directory value from the url""" + srcdir = "" + + def _handle_srcdir(varname, origvalue, op, newlines): + nonlocal srcdir + if origvalue.startswith("${WORKDIR}"): + srcdir = origvalue[11:] + else: + srcdir = "${BP}" + + return origvalue, None, 0, True + + bb.utils.edit_metadata(lines, ["S"], _handle_srcdir) + + return srcdir + @staticmethod def _ensure_npm(): """Check if the 'npm' command is available in the recipes""" @@ -116,6 +142,118 @@ class NpmRecipeHandler(RecipeHandler): return os.path.join(srctree, "npm-shrinkwrap.json") + def _process_shrinkwrap(self, srctree, shrinkwrap, srcdir): + """ + Extract package urls from shrinkwrap dependencies + """ + + urls = [] + + def _populate_modules(name, params, deptree): + from bb.fetch2 import URI + from bb.fetch2.npm import npm_integrity + from bb.fetch2.npm import npm_localfile + + destsubdirs = [os.path.join("node_modules", dep) for dep in deptree] + destsuffix = os.path.join(srcdir, *destsubdirs) + + dev = params.get("dev", False) + integrity = params.get("integrity") + resolved = params.get("resolved") + version = params.get("version") + requires = params.get("requires", {}) + + # Handle registry sources + if bb.utils.is_semver(version) and integrity: + # Skip dependencies without url + if not resolved: + return + + pkgv = version + + uri = URI(resolved) + uri.params["downloadfilename"] = npm_localfile(name, version) + + checksum_name, checksum_expected = npm_integrity(integrity) + uri.params[checksum_name] = checksum_expected + + uri.params["subdir"] = destsuffix + uri.params["striplevel"] = "1" + + url = str(uri) + + # Handle http tarball sources + elif version.startswith("http") and integrity: + checksum_name, checksum_expected = npm_integrity(integrity) + + pkgv = checksum_expected[:13] + + uri = URI(version) + uri.params["downloadfilename"] = npm_localfile(name, pkgv) + + uri.params[checksum_name] = checksum_expected + + uri.params["destsuffix"] = destsuffix + uri.params["striplevel"] = "1" + + url = str(uri) + + # Handle git sources + elif version.startswith("git"): + if version.startswith("github:"): + version = "git+https://github.com/" + version[len("github:"):] + regex = re.compile(r""" + ^ + git\+ + (?P[a-z]+) + :// + (?P[^#]+) + \# + (?P[0-9a-f]+) + $ + """, re.VERBOSE) + + match = regex.match(version) + + if not match: + raise Exception("Invalid git url: %s - %s" % (version, url)) + + groups = match.groupdict() + + pkgv = str(groups["rev"])[:10] + + uri = URI("git://" + str(groups["url"])) + uri.params["destsuffix"] = destsuffix + uri.params["nobranch"] = "1" + uri.params["protocol"] = str(groups["protocol"]) + uri.params["rev"] = str(groups["rev"]) + + url = str(uri) + + else: + raise Exception("Unsupported dependency: %s - %s" % (name, version)) + + # Set package version in shrinkwrap for dependency resolution + params["pkgv"] = pkgv + + urls.append(url) + + def _foreach_shrinkwrap_dependency(shrinkwrap, callback): + def _walk_dependencies(deps, deptree): + for name in deps: + subtree = [*deptree, name] + _walk_dependencies(deps[name].get("dependencies", {}), subtree) + if deps[name].get("bundled", False): + continue + callback(name, deps[name], subtree) + + _walk_dependencies(shrinkwrap.get("dependencies", {}), []) + + _foreach_shrinkwrap_dependency(shrinkwrap, _populate_modules) + + return urls + + def _handle_licenses(self, srctree, shrinkwrap_file, dev): """Return the extra license files and the list of packages""" licfiles = [] @@ -173,7 +311,7 @@ class NpmRecipeHandler(RecipeHandler): if "name" not in data or "version" not in data: return False - extravalues["PN"] = self._npm_name(data["name"]) + extravalues["PN"] = self._node_recipe_name(data["name"]) extravalues["PV"] = data["version"] if "description" in data: @@ -184,6 +322,24 @@ class NpmRecipeHandler(RecipeHandler): dev = bb.utils.to_boolean(str(extravalues.get("NPM_INSTALL_DEV", "0")), False) registry = self._get_registry(lines_before) + srcdir = self._get_srcdir(lines_before) + # Replace reserved directories + if srcdir == "package": + srcdir = "npm" + def _handle_srcuri(varname, origvalue, op, newlines): + """Update the version value""" + values = "%s;subdir=%s;striplevel=1" % (origvalue, srcdir) + 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] + + def _handle_srcdir(varname, origvalue, op, newlines): + value = "${WORKDIR}/%s" % (srcdir) + return value, None, 0, True + + (_, newlines) = bb.utils.edit_metadata(lines_before, ["S"], _handle_srcdir) + lines_before[:] = [line.rstrip('\n') for line in newlines] bb.note("Checking if npm is available ...") # The native npm is used here (and not the host one) to ensure that the @@ -223,37 +379,65 @@ class NpmRecipeHandler(RecipeHandler): 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""" + """Update the version value""" 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()] - if "dependencies" in shrinkwrap: - 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] + urls = self._process_shrinkwrap(srctree, shrinkwrap, srcdir) + + # Add the package urls in the SRC_URI of the generated recipe + def _handle_srcuri(varname, origvalue, op, newlines): + """Add the package urls and git SRCREVs""" + values = None + # Handle SRCREVs + if varname == "SRCREV": + newlines.append('SRCREV_FORMAT = "main"') + newlines.append('SRCREV_main = "%s"' % origvalue) + # Handle urls + elif varname == "SRC_URI": + values = [line.strip() for line in origvalue.split()] + values = ["%s;name=main" % (v) if v.startswith(("git", "http")) else v for v in values] + values.extend(sorted(urls)) + # Handle hashes + else: + newvarname = varname.replace("[", "[main.") + newlines.append('%s = "%s"' % (newvarname, origvalue)) + return values, None, 4, False + + (_, newlines) = bb.utils.edit_metadata(lines_before, ["SRC_URI", "SRCREV", "SRC_URI\[\w*\]"], _handle_srcuri) + lines_before[:] = [line.rstrip('\n') for line in newlines] + + + # Add the package urls in the SRC_URI of the generated recipe + def _handle_sums(varname, origvalue, op, newlines): + """Add the package urls and git SRCREVs""" + values = None + if varname == "SRC_URI[md5sum]": + # Add the urls + values = [line.strip() for line in origvalue.split()] + values = [v + ";name=main" if v.startswith("git", "http") else v for v in values] + values.extend(sorted(urls)) + else: + # Add git SRCREVs + newlines.append('SRCREV_FORMAT = "main"') + newlines.append('SRCREV_main = "%s"' % origvalue) + return values, None, 4, False + + (_, newlines) = bb.utils.edit_metadata(lines_before, ["SRC_URI[md5sum]", "SRCREV" ], _handle_sums) + 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 + # dependencies have to be fetched agai n using the urls bb.note("Fetching npm dependencies ...") bb.utils.remove(os.path.join(srctree, "node_modules"), recurse=True) - fetcher = bb.fetch2.Fetch([url_local], d) + srcurls = [url.replace("=%s/node_modules" % srcdir, "=node_modules") for url in urls] + fetcher = bb.fetch2.Fetch(srcurls, d) fetcher.download() fetcher.unpack(srctree) @@ -289,7 +473,24 @@ class NpmRecipeHandler(RecipeHandler): (licenses, extravalues["LIC_FILES_CHKSUM"]) = _guess_odd_license(licfiles) split_pkg_licenses([*licenses, *guess_license(srctree, d)], packages, lines_after) - classes.append("npm") + # Add suitable npm class + if dev: + scripts = data.get("scripts", {}) + if scripts.get("build"): + deps = data.get("devDependencies", {}) + if deps.get("@angular/cli"): + classes.append("angular") + elif deps.get("karma"): + classes.append("karma") + elif scripts.get("test"): + classes.append("npm_test") + else: + classes.append("npm_build") + else: + classes.append("npm") + else: + classes.append("npm") + handled.append("buildsystem") return True