Skip to content

Commit da95386

Browse files
committed
set-envs: include booleans, skip already-set envs
Fix #1650 PR-URL: #1652 Credit: @isaacs Close: #1652 Reviewed-by: @MylesBorins
1 parent 631142f commit da95386

2 files changed

Lines changed: 186 additions & 18 deletions

File tree

lib/config/set-envs.js

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,25 @@ const sameArrayValue = (def, val) => {
2626
return false
2727
}
2828
for (let i = 0; i < def.length; i++) {
29+
/* istanbul ignore next - there are no array configs where the default
30+
* is not an empty array, so this loop is a no-op, but it's the correct
31+
* thing to do if we ever DO add a config like that. */
2932
if (def[i] !== val[i]) {
3033
return false
3134
}
3235
}
3336
return true
3437
}
3538

36-
const setEnv = (rawKey, rawVal) => {
39+
const setEnv = (env, rawKey, rawVal) => {
3740
const val = envVal(rawVal)
3841
const key = envKey(rawKey, val)
39-
if (key)
40-
process.env[key] = val
42+
if (key && val !== null) {
43+
env[key] = val
44+
}
4145
}
4246

43-
const setEnvs = npm => {
47+
const setEnvs = (npm, env = process.env) => {
4448
// This ensures that all npm config values that are not the defaults are
4549
// shared appropriately with child processes, without false positives.
4650
//
@@ -51,38 +55,37 @@ const setEnvs = npm => {
5155
// if the key is NOT the default value,
5256
// if the env is setting it, then leave it (already set)
5357
// otherwise, set the env
54-
console.error(npm.config.list)
55-
const { config: { list: [cli, env] } } = npm
56-
const cliSet = new Set(Object.keys(cli))
57-
const envSet = new Set(Object.keys(env))
58+
const { config: { list: [cliConf, envConf] } } = npm
59+
const cliSet = new Set(Object.keys(cliConf))
60+
const envSet = new Set(Object.keys(envConf))
5861
const { defaults } = require('./defaults.js')
5962
// the configs form a prototype chain, so we can for/in over cli to
6063
// see all the current values, and hasOwnProperty to see if it's
6164
// set therre.
62-
for (const key in cli) {
63-
if (sameConfigValue(defaults[key], cli[key])) {
64-
if (!sameConfigValue(defaults[key], env[key])) {
65+
for (const key in cliConf) {
66+
if (sameConfigValue(defaults[key], cliConf[key])) {
67+
if (!sameConfigValue(defaults[key], envConf[key])) {
6568
// getting set back to the default in the cli config
66-
setEnv(key, cli[key])
69+
setEnv(env, key, cliConf[key])
6770
}
6871
} else {
6972
// config is not the default
7073
if (!(envSet.has(key) && !cliSet.has(key))) {
7174
// was not set in the env, so we have to put it there
72-
setEnv(key, cli[key])
75+
setEnv(env, key, cliConf[key])
7376
}
7477
}
7578
}
7679

7780
// also set some other common ones.
78-
process.env.npm_execpath = require.main.filename
79-
process.env.npm_node_execpath = process.execPath
80-
process.env.npm_command = npm.command
81+
env.npm_execpath = require.main.filename
82+
env.npm_node_execpath = process.execPath
83+
env.npm_command = npm.command
8184

8285
// note: this doesn't afect the *current* node process, of course, since
8386
// it's already started, but it does affect the options passed to scripts.
84-
if (configs['node-options']) {
85-
process.env.NODE_OPTIONS = configs['node-options']
87+
if (cliConf['node-options']) {
88+
env.NODE_OPTIONS = cliConf['node-options']
8689
}
8790
}
8891

test/lib/config/set-envs.js

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
const t = require('tap')
2+
const setEnvs = require('../../../lib/config/set-envs.js')
3+
const { defaults } = require('../../../lib/config/defaults.js')
4+
5+
t.test('set envs that are not defaults and not already in env', t => {
6+
const envConf = Object.create(defaults)
7+
const cliConf = Object.create(envConf)
8+
const npm = {
9+
config: {
10+
list: [cliConf, envConf]
11+
}
12+
}
13+
const extras = {
14+
npm_execpath: require.main.filename,
15+
npm_node_execpath: process.execPath,
16+
npm_command: undefined
17+
}
18+
const env = {}
19+
setEnvs(npm, env)
20+
t.strictSame(env, { ...extras }, 'no new environment vars to create')
21+
envConf.call = 'me, maybe'
22+
setEnvs(npm, env)
23+
t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env')
24+
delete envConf.call
25+
cliConf.call = 'me, maybe'
26+
setEnvs(npm, env)
27+
t.strictSame(env, {
28+
...extras,
29+
npm_config_call: 'me, maybe'
30+
}, 'set in env, because changed from default in cli')
31+
envConf.call = 'me, maybe'
32+
cliConf.call = ''
33+
cliConf['node-options'] = 'some options for node'
34+
setEnvs(npm, env)
35+
t.strictSame(env, {
36+
...extras,
37+
npm_config_call: '',
38+
npm_config_node_options: 'some options for node',
39+
NODE_OPTIONS: 'some options for node'
40+
}, 'set in env, because changed from default in env, back to default in cli')
41+
t.end()
42+
})
43+
44+
t.test('set envs that are not defaults and not already in env, array style', t => {
45+
const envConf = Object.create(defaults)
46+
const cliConf = Object.create(envConf)
47+
const npm = {
48+
config: {
49+
list: [cliConf, envConf]
50+
}
51+
}
52+
const extras = {
53+
npm_execpath: require.main.filename,
54+
npm_node_execpath: process.execPath,
55+
npm_command: undefined
56+
}
57+
const env = {}
58+
setEnvs(npm, env)
59+
t.strictSame(env, { ...extras }, 'no new environment vars to create')
60+
envConf.omit = ['dev']
61+
setEnvs(npm, env)
62+
t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env')
63+
delete envConf.omit
64+
cliConf.omit = ['dev', 'optional']
65+
setEnvs(npm, env)
66+
t.strictSame(env, {
67+
...extras,
68+
npm_config_omit: 'dev\n\noptional'
69+
}, 'set in env, because changed from default in cli')
70+
envConf.omit = ['optional', 'peer']
71+
cliConf.omit = []
72+
setEnvs(npm, env)
73+
t.strictSame(env, {
74+
...extras,
75+
npm_config_omit: ''
76+
}, 'set in env, because changed from default in env, back to default in cli')
77+
t.end()
78+
})
79+
80+
t.test('set envs that are not defaults and not already in env, boolean edition', t => {
81+
const envConf = Object.create(defaults)
82+
const cliConf = Object.create(envConf)
83+
const npm = {
84+
config: {
85+
list: [cliConf, envConf]
86+
}
87+
}
88+
const extras = {
89+
npm_execpath: require.main.filename,
90+
npm_node_execpath: process.execPath,
91+
npm_command: undefined
92+
}
93+
const env = {}
94+
setEnvs(npm, env)
95+
t.strictSame(env, { ...extras }, 'no new environment vars to create')
96+
envConf.audit = false
97+
setEnvs(npm, env)
98+
t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env')
99+
delete envConf.audit
100+
cliConf.audit = false
101+
cliConf.ignoreObjects = {
102+
some: { object: 12345 }
103+
}
104+
setEnvs(npm, env)
105+
t.strictSame(env, {
106+
...extras,
107+
npm_config_audit: ''
108+
}, 'set in env, because changed from default in cli')
109+
envConf.audit = false
110+
cliConf.audit = true
111+
setEnvs(npm, env)
112+
t.strictSame(env, {
113+
...extras,
114+
npm_config_audit: 'true'
115+
}, 'set in env, because changed from default in env, back to default in cli')
116+
t.end()
117+
})
118+
119+
t.test('default to process.env', t => {
120+
const envConf = Object.create(defaults)
121+
const cliConf = Object.create(envConf)
122+
const npm = {
123+
config: {
124+
list: [cliConf, envConf]
125+
}
126+
}
127+
const extras = {
128+
npm_execpath: require.main.filename,
129+
npm_node_execpath: process.execPath,
130+
npm_command: undefined
131+
}
132+
const env = {}
133+
const envDescriptor = Object.getOwnPropertyDescriptor(process, 'env')
134+
Object.defineProperty(process, 'env', {
135+
value: env,
136+
configurable: true,
137+
enumerable: true,
138+
writable: true
139+
})
140+
t.teardown(() => Object.defineProperty(process, env, envDescriptor))
141+
142+
setEnvs(npm)
143+
t.strictSame(env, { ...extras }, 'no new environment vars to create')
144+
envConf.audit = false
145+
setEnvs(npm)
146+
t.strictSame(env, { ...extras }, 'no new environment vars to create, already in env')
147+
delete envConf.audit
148+
cliConf.audit = false
149+
cliConf.ignoreObjects = {
150+
some: { object: 12345 }
151+
}
152+
setEnvs(npm)
153+
t.strictSame(env, {
154+
...extras,
155+
npm_config_audit: ''
156+
}, 'set in env, because changed from default in cli')
157+
envConf.audit = false
158+
cliConf.audit = true
159+
setEnvs(npm)
160+
t.strictSame(env, {
161+
...extras,
162+
npm_config_audit: 'true'
163+
}, 'set in env, because changed from default in env, back to default in cli')
164+
t.end()
165+
})

0 commit comments

Comments
 (0)