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