1/* eslint-disable node/no-deprecated-api */ 2 3'use strict' 4 5const semver = require('semver') 6const url = require('url') 7const path = require('path') 8const log = require('npmlog') 9 10// versions where -headers.tar.gz started shipping 11const headersTarballRange = '>= 3.0.0 || ~0.12.10 || ~0.10.42' 12const bitsre = /\/win-(x86|x64|arm64)\// 13const bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" but should 14// have been "x86" 15 16// Captures all the logic required to determine download URLs, local directory and 17// file names. Inputs come from command-line switches (--target, --dist-url), 18// `process.version` and `process.release` where it exists. 19function processRelease (argv, gyp, defaultVersion, defaultRelease) { 20 var version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion 21 var versionSemver = semver.parse(version) 22 var overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl 23 var isDefaultVersion 24 var isNamedForLegacyIojs 25 var name 26 var distBaseUrl 27 var baseUrl 28 var libUrl32 29 var libUrl64 30 var libUrlArm64 31 var tarballUrl 32 var canGetHeaders 33 34 if (!versionSemver) { 35 // not a valid semver string, nothing we can do 36 return { version: version } 37 } 38 // flatten version into String 39 version = versionSemver.version 40 41 // defaultVersion should come from process.version so ought to be valid semver 42 isDefaultVersion = version === semver.parse(defaultVersion).version 43 44 // can't use process.release if we're using --target=x.y.z 45 if (!isDefaultVersion) { 46 defaultRelease = null 47 } 48 49 if (defaultRelease) { 50 // v3 onward, has process.release 51 name = defaultRelease.name.replace(/io\.js/, 'iojs') // remove the '.' for directory naming purposes 52 } else { 53 // old node or alternative --target= 54 // semver.satisfies() doesn't like prerelease tags so test major directly 55 isNamedForLegacyIojs = versionSemver.major >= 1 && versionSemver.major < 4 56 // isNamedForLegacyIojs is required to support Electron < 4 (in particular Electron 3) 57 // as previously this logic was used to ensure "iojs" was used to download iojs releases 58 // and "node" for node releases. Unfortunately the logic was broad enough that electron@3 59 // published release assets as "iojs" so that the node-gyp logic worked. Once Electron@3 has 60 // been EOL for a while (late 2019) we should remove this hack. 61 name = isNamedForLegacyIojs ? 'iojs' : 'node' 62 } 63 64 // check for the nvm.sh standard mirror env variables 65 if (!overrideDistUrl && process.env.NODEJS_ORG_MIRROR) { 66 overrideDistUrl = process.env.NODEJS_ORG_MIRROR 67 } 68 69 if (overrideDistUrl) { 70 log.verbose('download', 'using dist-url', overrideDistUrl) 71 } 72 73 if (overrideDistUrl) { 74 distBaseUrl = overrideDistUrl.replace(/\/+$/, '') 75 } else { 76 distBaseUrl = 'https://nodejs.org/dist' 77 } 78 distBaseUrl += '/v' + version + '/' 79 80 // new style, based on process.release so we have a lot of the data we need 81 if (defaultRelease && defaultRelease.headersUrl && !overrideDistUrl) { 82 baseUrl = url.resolve(defaultRelease.headersUrl, './') 83 libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x86', versionSemver.major) 84 libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x64', versionSemver.major) 85 libUrlArm64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'arm64', versionSemver.major) 86 tarballUrl = defaultRelease.headersUrl 87 } else { 88 // older versions without process.release are captured here and we have to make 89 // a lot of assumptions, additionally if you --target=x.y.z then we can't use the 90 // current process.release 91 baseUrl = distBaseUrl 92 libUrl32 = resolveLibUrl(name, baseUrl, 'x86', versionSemver.major) 93 libUrl64 = resolveLibUrl(name, baseUrl, 'x64', versionSemver.major) 94 libUrlArm64 = resolveLibUrl(name, baseUrl, 'arm64', versionSemver.major) 95 96 // making the bold assumption that anything with a version number >3.0.0 will 97 // have a *-headers.tar.gz file in its dist location, even some frankenstein 98 // custom version 99 canGetHeaders = semver.satisfies(versionSemver, headersTarballRange) 100 tarballUrl = url.resolve(baseUrl, name + '-v' + version + (canGetHeaders ? '-headers' : '') + '.tar.gz') 101 } 102 103 return { 104 version: version, 105 semver: versionSemver, 106 name: name, 107 baseUrl: baseUrl, 108 tarballUrl: tarballUrl, 109 shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'), 110 versionDir: (name !== 'node' ? name + '-' : '') + version, 111 ia32: { 112 libUrl: libUrl32, 113 libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path)) 114 }, 115 x64: { 116 libUrl: libUrl64, 117 libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path)) 118 }, 119 arm64: { 120 libUrl: libUrlArm64, 121 libPath: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrlArm64).path)) 122 } 123 } 124} 125 126function normalizePath (p) { 127 return path.normalize(p).replace(/\\/g, '/') 128} 129 130function resolveLibUrl (name, defaultUrl, arch, versionMajor) { 131 var base = url.resolve(defaultUrl, './') 132 var hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl)) 133 134 if (!hasLibUrl) { 135 // let's assume it's a baseUrl then 136 if (versionMajor >= 1) { 137 return url.resolve(base, 'win-' + arch + '/' + name + '.lib') 138 } 139 // prior to io.js@1.0.0 32-bit node.lib lives in /, 64-bit lives in /x64/ 140 return url.resolve(base, (arch === 'x86' ? '' : arch + '/') + name + '.lib') 141 } 142 143 // else we have a proper url to a .lib, just make sure it's the right arch 144 return defaultUrl.replace(versionMajor === 3 ? bitsreV3 : bitsre, '/win-' + arch + '/') 145} 146 147module.exports = processRelease 148