codekingpro/portable-devtools
115k
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(new URL(baseUrl).pathname, new URL(libUrl32).pathname))
113 },
114 x64: {
115 libUrl: libUrl64,
116 libPath: normalizePath(path.relative(new URL(baseUrl).pathname, new URL(libUrl64).pathname))
117 },
118 arm64: {
119 libUrl: libUrlArm64,
120 libPath: normalizePath(path.relative(new URL(baseUrl).pathname, new URL(libUrlArm64).pathname))
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 