• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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