Skip to content

Commit c30b628

Browse files
committed
refactor
1 parent 2407f68 commit c30b628

2 files changed

Lines changed: 37 additions & 45 deletions

File tree

lib/node-gyp.js

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -122,54 +122,41 @@ class Gyp extends EventEmitter {
122122
}
123123

124124
// support for inheriting config env variables from npm
125+
// npm will set environment variables in the following forms:
126+
// - `npm_config_<key>` for values from npm's own config. Setting arbitrary
127+
// options on npm's config was deprecated in npm v11 but node-gyp still
128+
// supports it for backwards compatibility.
129+
// See https://github.com/nodejs/node-gyp/issues/3156
130+
// - `npm_package_config_node_gyp_<key>` for values from the `config` object
131+
// in package.json. This is the preferred way to set options for node-gyp
132+
// since npm v11. The `node_gyp_` prefix is used to avoid conflicts with
133+
// other tools.
134+
// The `npm_package_config_node_gyp_` prefix will take precedence over
135+
// `npm_config_` keys.
125136
const npmConfigPrefix = 'npm_config_'
126-
Object.keys(process.env).forEach((name) => {
127-
if (name.indexOf(npmConfigPrefix) !== 0) {
128-
return
129-
}
130-
const val = process.env[name]
131-
if (name === npmConfigPrefix + 'loglevel') {
132-
log.logger.level = val
133-
} else {
134-
// add the user-defined options to the config
135-
name = name.substring(npmConfigPrefix.length)
136-
// gyp@741b7f1 enters an infinite loop when it encounters
137-
// zero-length options so ensure those don't get through.
138-
if (name) {
139-
// convert names like force_process_config to force-process-config
140-
if (name.includes('_')) {
141-
name = name.replace(/_/g, '-')
142-
}
143-
this.opts[name] = val
144-
}
145-
}
146-
})
147-
148-
// Read values that npm sets based on the `config` object in package.json.
149-
// These take precendence over the npm_config_ prefixed values which
150-
// are deprecated in npm@11.
151-
// These can also be set directly in the environment, if setting in
152-
// package.json is not desired.
153137
const npmPackageConfigPrefix = 'npm_package_config_node_gyp_'
154-
Object.keys(process.env).forEach((name) => {
155-
if (name.indexOf(npmPackageConfigPrefix) !== 0) {
156-
return
157-
}
158-
const val = process.env[name]
159-
name = name.substring(npmPackageConfigPrefix.length)
138+
139+
const configEnvKeys = Object.keys(process.env)
140+
.filter((k) => k.startsWith(npmConfigPrefix) || k.startsWith(npmPackageConfigPrefix))
141+
// sort so that npm_package_config_node_gyp_ keys come last and will override
142+
.sort((a) => a.startsWith(npmConfigPrefix) ? -1 : 1)
143+
144+
for (const key of configEnvKeys) {
145+
// add the user-defined options to the config
146+
const name = key.startsWith(npmConfigPrefix)
147+
? key.substring(npmConfigPrefix.length)
148+
: key.substring(npmPackageConfigPrefix.length)
160149
// gyp@741b7f1 enters an infinite loop when it encounters
161150
// zero-length options so ensure those don't get through.
162151
if (name) {
163152
// convert names like force_process_config to force-process-config
164-
if (name.includes('_')) {
165-
name = name.replace(/_/g, '-')
166-
}
167-
this.opts[name] = val
153+
this.opts[name.replaceAll('_', '-')] = process.env[key]
168154
}
169-
})
155+
}
170156

171157
if (this.opts.loglevel) {
172158
log.logger.level = this.opts.loglevel
159+
delete this.opts.loglevel
173160
}
174161
log.resume()
175162
}

test/test-options.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
const { describe, it } = require('mocha')
44
const assert = require('assert')
55
const gyp = require('../lib/node-gyp')
6+
const log = require('../lib/log')
67

78
describe('options', function () {
89
it('options in environment', () => {
910
// `npm test` dumps a ton of npm_config_* variables in the environment.
1011
Object.keys(process.env)
11-
.filter((key) => /^npm_config_/.test(key) || /^npm_package_config_node_gyp_/.test(key))
12+
.filter((key) => /^npm_config_/i.test(key) || /^npm_package_config_node_gyp_/i.test(key))
1213
.forEach((key) => { delete process.env[key] })
1314

1415
// in some platforms, certain keys are stubborn and cannot be removed
1516
const keys = Object.keys(process.env)
16-
.filter((key) => /^npm_config_/.test(key) || /^npm_package_config_node_gyp_/.test(key))
17+
.filter((key) => /^npm_config_/i.test(key) || /^npm_package_config_node_gyp_/i.test(key))
1718
.map((key) => key.substring('npm_config_'.length))
18-
.concat('argv', 'x', 'y', 'foo')
1919

2020
// Environment variables with the following prefixes should be added to opts.
2121
// - `npm_config_` for npm versions before v11.
@@ -25,18 +25,23 @@ describe('options', function () {
2525
process.env.npm_config_ = '42'
2626
process.env.npm_package_config_node_gyp_ = '42'
2727
// Other keys should get added.
28+
process.env.npm_package_config_node_gyp_foo = '42'
2829
process.env.npm_config_x = '42'
2930
process.env.npm_config_y = '41'
30-
process.env.npm_package_config_node_gyp_foo = '42'
3131
// Package config should take precedence over npm_config_ keys.
3232
process.env.npm_package_config_node_gyp_y = '42'
33-
// Except loglevel.
34-
process.env.npm_config_loglevel = 'debug'
33+
// loglevel does not get added to opts but will change the logger's level.
34+
process.env.npm_config_loglevel = 'silly'
3535

3636
const g = gyp()
37+
38+
assert.strictEqual(log.logger.level.id, 'info')
39+
3740
g.parseArgv(['rebuild']) // Also sets opts.argv.
3841

39-
assert.deepStrictEqual(Object.keys(g.opts).sort(), keys.sort())
42+
assert.strictEqual(log.logger.level.id, 'silly')
43+
44+
assert.deepStrictEqual(Object.keys(g.opts).sort(), [...keys, 'argv', 'x', 'y', 'foo'].sort())
4045
assert.strictEqual(g.opts['x'], '42')
4146
assert.strictEqual(g.opts['y'], '42')
4247
assert.strictEqual(g.opts['foo'], '42')

0 commit comments

Comments
 (0)