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