forked from GoogleCloudPlatform/nodejs-docker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstall_node
executable file
·197 lines (168 loc) · 4.91 KB
/
install_node
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/env node
var semver = require('semver');
var https = require('https');
var spawn = require('child_process').spawn;
function request(method, host, path, cb) {
var options = {
'host': host,
'method': method,
'path': path
};
var req = https.request(options, function(res) {
if (res.statusCode != 200) {
return cb(new Error('Returned status code: ' + res.statusCode));
}
var body = '';
res.on('data', function(d) {
body += d;
});
res.on('end', function() {
cb(null, body, res);
});
});
req.end();
}
function getAvailableVersions(cb) {
request(
'GET', 'storage.googleapis.com', '/gcp-node-packages/node_versions',
function(err, body) {
if (err) {
return cb(err);
}
return cb(
null,
body
.trim()
.split('\n')
.sort(function(a, b) {
if (semver.gt(a, b)) {
return -1;
}
return +1;
})
);
}
);
}
function getSatisfyingVersion(requestedVersion, cb) {
getAvailableVersions(function(err, versions) {
if (err) {
return cb(err);
}
var satisfied = versions.some(function(version) {
if (semver.satisfies(version, requestedVersion)) {
cb(null, version);
return true;
}
});
if (!satisfied) {
return cb(new Error(
'No Node.js version satisfying ' + requestedVersion + ' found.'));
}
});
}
function verifyBinaryExists(version, cb) {
request(
'HEAD',
'storage.googleapis.com',
'/gcp-node-packages/node-' + version + '-linux-x64.tar.gz',
function(err) {
if (err) {
return cb(new Error(
'Binary for Node.js version ' + version + ' is not available.'));
}
return cb();
});
}
function downloadAndInstallVersion(version, args, cb) {
var command = '/opt/gcp/runtime/bootstrap_node';
var proc = spawn(command, [version].concat(args ? args : []));
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
// wrap the callback to use state to ensure the callback
// is not called more than once
var invoked = false;
function guardedCallback(err) {
if (invoked) {
return;
}
invoked = true;
return cb(err);
}
proc.on('error', guardedCallback);
proc.on('exit', function(code) {
return guardedCallback(code === 0 ? null :
new Error(command + ' exited with a non-zero exit code: ' + code));
});
}
function fail(err) {
console.error('Node installation failed: ' + err.message);
process.exit(1);
}
function main(requestedVersion, args) {
// Does the current Node.js version already satisfy the requested version?
// If so, we have nothing to do.
if (semver.satisfies(process.version, requestedVersion)) {
return;
}
// Otherwise, find which version satisfies and install it.
getSatisfyingVersion(requestedVersion, function(err, version) {
if (err) {
return fail(err);
}
verifyBinaryExists(version, function(err) {
if (err) {
return fail(err);
}
downloadAndInstallVersion(version, args, function(err) {
if (err) {
return fail(err);
}
console.log('Installed Node.js ' + version);
});
});
});
}
function printUsageAndExit() {
console.log('Usage: install_node: [--ignore-verification-failure] [--direct] [--help] version');
console.log('');
console.log('Verifies and installs the specified version of Node.js.');
console.log('');
console.log('Options:');
console.log(' --ignore-verification-failure If the binary verification fails,');
console.log(' still continue with the installation.');
console.log(' By default, if binary verification');
console.log(' fails, the installation is aborted.');
console.log(' --direct Download and install directly from');
console.log(' nodejs.org instead of from');
console.log(' https://storage.googleapis.com/gcp-node-packages');
console.log(' --help Prints this help message');
console.log('');
console.log(' version The version of Node.js to install.');
console.log(' The version number is expected to be');
console.log(' of the form \'v#.#.#\'.');
process.exit(1);
}
var spec;
var args = [];
for (var i=2; i<process.argv.length; i++) {
var a = process.argv[i];
// Check if the argument starts with '--' in a way that can be used with
// Node >= 0.10.0
if (a.indexOf('--') === 0) {
args.push(a);
}
else {
if (spec) {
console.log('Exactly one version must be specified.');
printUsageAndExit();
}
else {
spec = a;
}
}
}
if (!spec) {
printUsageAndExit();
}
main(spec, args);