@@ -22,6 +22,10 @@ const streamPipeline = util.promisify(stream.pipeline)
22
22
23
23
async function install ( fs , gyp , argv ) {
24
24
const release = processRelease ( argv , gyp , process . version , process . release )
25
+ // Detecting target_arch based on logic from create-cnfig-gyp.js. Used on Windows only.
26
+ const arch = win ? ( gyp . opts . target_arch || gyp . opts . arch || process . arch || 'ia32' ) : ''
27
+ // Used to prevent downloading tarball if only new node.lib is required on Windows.
28
+ let shouldDownloadTarball = true
25
29
26
30
// Determine which node dev files version we are installing
27
31
log . verbose ( 'install' , 'input version string %j' , release . version )
@@ -92,6 +96,26 @@ async function install (fs, gyp, argv) {
92
96
}
93
97
}
94
98
log . verbose ( 'install' , 'version is good' )
99
+ if ( win ) {
100
+ log . verbose ( 'on Windows; need to check node.lib' )
101
+ const nodeLibPath = path . resolve ( devDir , arch , 'node.lib' )
102
+ try {
103
+ await fs . promises . stat ( nodeLibPath )
104
+ } catch ( err ) {
105
+ if ( err . code === 'ENOENT' ) {
106
+ log . verbose ( 'install' , `version not already installed for ${ arch } , continuing with install` , release . version )
107
+ try {
108
+ shouldDownloadTarball = false
109
+ return await go ( )
110
+ } catch ( err ) {
111
+ return rollback ( err )
112
+ }
113
+ } else if ( err . code === 'EACCES' ) {
114
+ return eaccesFallback ( err )
115
+ }
116
+ throw err
117
+ }
118
+ }
95
119
} else {
96
120
try {
97
121
return await go ( )
@@ -179,66 +203,69 @@ async function install (fs, gyp, argv) {
179
203
}
180
204
181
205
// download the tarball and extract!
206
+ // Ommited on Windows if only new node.lib is required
182
207
183
208
// on Windows there can be file errors from tar if parallel installs
184
209
// are happening (not uncommon with multiple native modules) so
185
210
// extract the tarball to a temp directory first and then copy over
186
211
const tarExtractDir = win ? await fs . promises . mkdtemp ( path . join ( os . tmpdir ( ) , 'node-gyp-tmp-' ) ) : devDir
187
212
188
213
try {
189
- if ( tarPath ) {
190
- await tar . extract ( {
191
- file : tarPath ,
192
- strip : 1 ,
193
- filter : isValid ,
194
- onwarn,
195
- cwd : tarExtractDir
196
- } )
197
- } else {
198
- try {
199
- const res = await download ( gyp , release . tarballUrl )
214
+ if ( shouldDownloadTarball ) {
215
+ if ( tarPath ) {
216
+ await tar . extract ( {
217
+ file : tarPath ,
218
+ strip : 1 ,
219
+ filter : isValid ,
220
+ onwarn,
221
+ cwd : tarExtractDir
222
+ } )
223
+ } else {
224
+ try {
225
+ const res = await download ( gyp , release . tarballUrl )
200
226
201
- if ( res . status !== 200 ) {
202
- throw new Error ( `${ res . status } response downloading ${ release . tarballUrl } ` )
203
- }
227
+ if ( res . status !== 200 ) {
228
+ throw new Error ( `${ res . status } response downloading ${ release . tarballUrl } ` )
229
+ }
204
230
205
- await streamPipeline (
206
- res . body ,
207
- // content checksum
208
- new ShaSum ( ( _ , checksum ) => {
209
- const filename = path . basename ( release . tarballUrl ) . trim ( )
210
- contentShasums [ filename ] = checksum
211
- log . verbose ( 'content checksum' , filename , checksum )
212
- } ) ,
213
- tar . extract ( {
214
- strip : 1 ,
215
- cwd : tarExtractDir ,
216
- filter : isValid ,
217
- onwarn
218
- } )
219
- )
220
- } catch ( err ) {
231
+ await streamPipeline (
232
+ res . body ,
233
+ // content checksum
234
+ new ShaSum ( ( _ , checksum ) => {
235
+ const filename = path . basename ( release . tarballUrl ) . trim ( )
236
+ contentShasums [ filename ] = checksum
237
+ log . verbose ( 'content checksum' , filename , checksum )
238
+ } ) ,
239
+ tar . extract ( {
240
+ strip : 1 ,
241
+ cwd : tarExtractDir ,
242
+ filter : isValid ,
243
+ onwarn
244
+ } )
245
+ )
246
+ } catch ( err ) {
221
247
// something went wrong downloading the tarball?
222
- if ( err . code === 'ENOTFOUND' ) {
223
- throw new Error ( 'This is most likely not a problem with node-gyp or the package itself and\n' +
248
+ if ( err . code === 'ENOTFOUND' ) {
249
+ throw new Error ( 'This is most likely not a problem with node-gyp or the package itself and\n' +
224
250
'is related to network connectivity. In most cases you are behind a proxy or have bad \n' +
225
251
'network settings.' )
252
+ }
253
+ throw err
226
254
}
227
- throw err
228
255
}
229
- }
230
256
231
- // invoked after the tarball has finished being extracted
232
- if ( extractErrors || extractCount === 0 ) {
233
- throw new Error ( 'There was a fatal problem while downloading/extracting the tarball' )
234
- }
257
+ // invoked after the tarball has finished being extracted
258
+ if ( extractErrors || extractCount === 0 ) {
259
+ throw new Error ( 'There was a fatal problem while downloading/extracting the tarball' )
260
+ }
235
261
236
- log . verbose ( 'tarball' , 'done parsing tarball' )
262
+ log . verbose ( 'tarball' , 'done parsing tarball' )
263
+ }
237
264
238
265
const installVersionPath = path . resolve ( tarExtractDir , 'installVersion' )
239
266
await Promise . all ( [
240
- // need to download node.lib
241
- ...( win ? downloadNodeLib ( ) : [ ] ) ,
267
+ // need to download node.lib
268
+ ...( win ? [ downloadNodeLib ( ) ] : [ ] ) ,
242
269
// write the "installVersion" file
243
270
fs . promises . writeFile ( installVersionPath , gyp . package . installVersion + '\n' ) ,
244
271
// Only download SHASUMS.txt if we downloaded something in need of SHA verification
@@ -293,43 +320,33 @@ async function install (fs, gyp, argv) {
293
320
log . verbose ( 'checksum data' , JSON . stringify ( expectShasums ) )
294
321
}
295
322
296
- function downloadNodeLib ( ) {
323
+ async function downloadNodeLib ( ) {
297
324
log . verbose ( 'on Windows; need to download `' + release . name + '.lib`...' )
298
- const archs = [ 'ia32' , 'x64' , 'arm64' ]
299
- return archs . map ( async ( arch ) => {
300
- const dir = path . resolve ( tarExtractDir , arch )
301
- const targetLibPath = path . resolve ( dir , release . name + '.lib' )
302
- const { libUrl, libPath } = release [ arch ]
303
- const name = `${ arch } ${ release . name } .lib`
304
- log . verbose ( name , 'dir' , dir )
305
- log . verbose ( name , 'url' , libUrl )
306
-
307
- await fs . promises . mkdir ( dir , { recursive : true } )
308
- log . verbose ( 'streaming' , name , 'to:' , targetLibPath )
309
-
310
- const res = await download ( gyp , libUrl )
311
-
312
- if ( res . status === 403 || res . status === 404 ) {
313
- if ( arch === 'arm64' ) {
314
- // Arm64 is a newer platform on Windows and not all node distributions provide it.
315
- log . verbose ( `${ name } was not found in ${ libUrl } ` )
316
- } else {
317
- log . warn ( `${ name } was not found in ${ libUrl } ` )
318
- }
319
- return
320
- } else if ( res . status !== 200 ) {
321
- throw new Error ( `${ res . status } status code downloading ${ name } ` )
322
- }
325
+ const dir = path . resolve ( tarExtractDir , arch )
326
+ const targetLibPath = path . resolve ( dir , release . name + '.lib' )
327
+ const { libUrl, libPath } = release [ arch ]
328
+ const name = `${ arch } ${ release . name } .lib`
329
+ log . verbose ( name , 'dir' , dir )
330
+ log . verbose ( name , 'url' , libUrl )
331
+
332
+ await fs . promises . mkdir ( dir , { recursive : true } )
333
+ log . verbose ( 'streaming' , name , 'to:' , targetLibPath )
334
+
335
+ const res = await download ( gyp , libUrl )
336
+
337
+ // Since only required node.lib is downloaded throw error if it is not fetched
338
+ if ( res . status !== 200 ) {
339
+ throw new Error ( `${ res . status } status code downloading ${ name } ` )
340
+ }
323
341
324
- return streamPipeline (
325
- res . body ,
326
- new ShaSum ( ( _ , checksum ) => {
327
- contentShasums [ libPath ] = checksum
328
- log . verbose ( 'content checksum' , libPath , checksum )
329
- } ) ,
330
- fs . createWriteStream ( targetLibPath )
331
- )
332
- } )
342
+ return streamPipeline (
343
+ res . body ,
344
+ new ShaSum ( ( _ , checksum ) => {
345
+ contentShasums [ libPath ] = checksum
346
+ log . verbose ( 'content checksum' , libPath , checksum )
347
+ } ) ,
348
+ fs . createWriteStream ( targetLibPath )
349
+ )
333
350
} // downloadNodeLib()
334
351
} // go()
335
352
0 commit comments