forked from atom/atom
-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathupdate-process-env.js
143 lines (125 loc) · 3.35 KB
/
update-process-env.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const fs = require('fs');
const childProcess = require('child_process');
const ENVIRONMENT_VARIABLES_TO_PRESERVE = new Set([
'NODE_ENV',
'NODE_PATH',
'ATOM_HOME',
'ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT'
]);
const PLATFORMS_KNOWN_TO_WORK = new Set(['darwin', 'linux']);
// Shell command that returns env var=value lines separated by \0s so that
// newlines are handled properly. Note: need to use %c to inject the \0s
// to work with some non GNU awks.
const ENV_COMMAND =
'command awk \'BEGIN{for(v in ENVIRON) printf("%s=%s%c", v, ENVIRON[v], 0)}\'';
async function updateProcessEnv(launchEnv) {
let envToAssign;
if (launchEnv) {
if (shouldGetEnvFromShell(launchEnv)) {
envToAssign = await getEnvFromShell(launchEnv);
} else if (launchEnv.PWD || launchEnv.PROMPT || launchEnv.PSModulePath) {
envToAssign = launchEnv;
}
}
if (envToAssign) {
for (let key in process.env) {
if (!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key)) {
delete process.env[key];
}
}
for (let key in envToAssign) {
if (
!ENVIRONMENT_VARIABLES_TO_PRESERVE.has(key) ||
(!process.env[key] && envToAssign[key])
) {
process.env[key] = envToAssign[key];
}
}
if (envToAssign.ATOM_HOME && fs.existsSync(envToAssign.ATOM_HOME)) {
process.env.ATOM_HOME = envToAssign.ATOM_HOME;
}
}
}
function shouldGetEnvFromShell(env) {
if (!PLATFORMS_KNOWN_TO_WORK.has(process.platform)) {
return false;
}
if (!env || !env.SHELL || env.SHELL.trim() === '') {
return false;
}
const disableSellingOut =
env.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT ||
process.env.ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT;
if (disableSellingOut === 'true') {
return false;
}
return true;
}
async function getEnvFromShell(env) {
let { stdout, error } = await new Promise(resolve => {
let child;
let error;
let stdout = '';
let done = false;
const cleanup = () => {
if (!done && child) {
child.kill();
done = true;
}
};
process.once('exit', cleanup);
setTimeout(() => {
cleanup();
}, 5000);
child = childProcess.spawn(env.SHELL, ['-ilc', ENV_COMMAND], {
encoding: 'utf8',
detached: true,
stdio: ['ignore', 'pipe', process.stderr]
});
const buffers = [];
child.on('error', e => {
done = true;
error = e;
});
child.stdout.on('data', data => {
buffers.push(data);
});
child.on('close', (code, signal) => {
done = true;
process.removeListener('exit', cleanup);
if (buffers.length) {
stdout = Buffer.concat(buffers).toString('utf8');
}
resolve({ stdout, error });
});
});
if (error) {
if (error.handle) {
error.handle();
}
console.log(
'warning: ' +
env.SHELL +
' -ilc "' +
ENV_COMMAND +
'" failed with signal (' +
error.signal +
')'
);
console.log(error);
}
if (!stdout || stdout.trim() === '') {
return null;
}
let result = {};
for (let line of stdout.split('\0')) {
if (line.includes('=')) {
let components = line.split('=');
let key = components.shift();
let value = components.join('=');
result[key] = value;
}
}
return result;
}
module.exports = { updateProcessEnv, shouldGetEnvFromShell };