From bfbacdd5c066ee7eac3166341a3a167d3919fdfd Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Sat, 19 Mar 2022 23:54:53 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A6=20NEW:=20Support=20libc=20field=20?= =?UTF-8?q?on=20conditions=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/cnpm/npminstall/issues/386 --- lib/download/npm.js | 11 +++++++++++ lib/utils.js | 21 ++++++++++++++++++++- test/utils.test.js | 23 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/download/npm.js b/lib/download/npm.js index f86dbc7a..ee9f0161 100644 --- a/lib/download/npm.js +++ b/lib/download/npm.js @@ -246,6 +246,17 @@ async function download(pkg, options) { err.name = 'UnSupportedPlatformError'; throw err; } + // dont download pkg in not matched libc + if (Array.isArray(pkg.libc)) { + const currentLibc = utils.getLibc(); + debug('currentLibc', currentLibc, pkg.libc) + if (!utils.matchPlatform(currentLibc, pkg.libc)) { + const errMsg = `[${pkg.name}@${pkg.version}] skip download for reason ${pkg.libc.join(', ')} dont includes your libc ${currentLibc}`; + const err = new Error(errMsg); + err.name = 'UnSupportedPlatformError'; + throw err; + } + } const ungzipDir = options.ungzipDir || utils.getPackageStorePath(options.storeDir, pkg); diff --git a/lib/utils.js b/lib/utils.js index 9c1f4789..226a10ee 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -463,7 +463,26 @@ exports.getBugVersions = async (registry, globalOptions) => { return pkg.config['bug-versions']; }; -// match platform or arch +// detect libc +// follow yarn impl: https://github.com/yarnpkg/berry/pull/3981/files#diff-f9ba955128e960171ac97ce06b0b0a940bb074af2794429a9f03c75f2a3bd459R10 +exports.getLibc = () => { + if (process.platform === 'win32') return null; + const report = process.report && process.report.getReport() || {}; + const sharedObjects = report.sharedObjects || []; + + // Matches the first group if libc, second group if musl + const libcRE = /\/(?:(ld-linux-|[^/]+-linux-gnu\/)|(libc.musl-|ld-musl-))/i; + for (const sharedObject of sharedObjects) { + const m = sharedObject.match(libcRE); + if (m) { + if (m[1]) return 'libc'; + if (m[2]) return 'musl'; + } + } + return null; +} + +// match platform, arch or libc // see https://docs.npmjs.com/cli/v7/configuring-npm/package-json#os exports.matchPlatform = (current, osNames) => { if (!Array.isArray(osNames) || osNames.length === 0) { diff --git a/test/utils.test.js b/test/utils.test.js index a90dc519..3655fe48 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -31,6 +31,20 @@ describe('test/utils.test.js', () => { assert(utils.matchPlatform('x64', [ 'x64', '!x64' ])); }); + it('should match libc names', () => { + assert(utils.matchPlatform('glibc', [])); + assert(utils.matchPlatform('musl', [])); + assert(utils.matchPlatform(null, [])); + assert(utils.matchPlatform('glibc', [ 'glibc' ])); + assert(utils.matchPlatform('glibc', [ 'glibc', 'musl' ])); + assert(utils.matchPlatform('musl', [ 'glibc', 'musl' ])); + assert(utils.matchPlatform('musl', [ 'musl' ])); + assert(utils.matchPlatform('glibc', [ '!glibc' ])); + assert(utils.matchPlatform('musl', [ '!musl' ])); + assert(utils.matchPlatform('glibc', [ '!musl', 'glibc' ])); + assert(utils.matchPlatform('glibc', [ 'glibc', '!glibc' ])); + }); + it('should not match os names', () => { assert(!utils.matchPlatform('darwin', [ 'linux' ])); assert(!utils.matchPlatform('darwin', [ 'win32' ])); @@ -53,6 +67,15 @@ describe('test/utils.test.js', () => { assert(!utils.matchPlatform('mips', [ '!x64', '!mips' ])); assert(!utils.matchPlatform('x64', [ '!x64' ])); }); + + it('should not match libc names', () => { + assert(!utils.matchPlatform(null, [ 'musl' ])); + assert(!utils.matchPlatform(null, [ 'glibc' ])); + assert(!utils.matchPlatform('glibc', [ 'musl' ])); + assert(!utils.matchPlatform('musl', [ 'glibc' ])); + assert(!utils.matchPlatform('glibc', [ '!glibc' ])); + assert(!utils.matchPlatform('musl', [ '!musl' ])); + }); }); describe('findMaxSatisfyingVersion()', () => {