Skip to content

Commit 938dd18

Browse files
committed
refactor for clarity, fix dist-url, add env var dist-url functionality
PR-URL: #711 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 9e9df66 commit 938dd18

File tree

7 files changed

+305
-91
lines changed

7 files changed

+305
-91
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
gyp/test
22
node_modules
3+
test/.node-gyp

lib/configure.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ function configure (gyp, argv, callback) {
145145
log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version)
146146
}
147147

148-
// make sure we have a valid version
149148
if (!release.semver) {
149+
// could not parse the version string with semver
150150
return callback(new Error('Invalid version number: ' + release.version))
151151
}
152152

@@ -304,9 +304,8 @@ function configure (gyp, argv, callback) {
304304
var addon_gypi = path.resolve(__dirname, '..', 'addon.gypi')
305305
var common_gypi = path.resolve(nodeDir, 'include/node/common.gypi')
306306
fs.stat(common_gypi, function (err, stat) {
307-
if (err || !stat.isFile()) {
307+
if (err)
308308
common_gypi = path.resolve(nodeDir, 'common.gypi')
309-
}
310309

311310
var output_dir = 'build'
312311
if (win) {

lib/install.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ function install (gyp, argv, callback) {
4545
// Determine which node dev files version we are installing
4646
log.verbose('install', 'input version string %j', release.version)
4747

48-
// parse the version to normalize and ensure it's valid
4948
if (!release.semver) {
49+
// could not parse the version string with semver
5050
return callback(new Error('Invalid version number: ' + release.version))
5151
}
5252

@@ -150,7 +150,7 @@ function install (gyp, argv, callback) {
150150
}
151151

152152
function getContentSha(res, callback) {
153-
var shasum = crypto.createHash(release.checksumAlgo)
153+
var shasum = crypto.createHash('sha256')
154154
res.on('data', function (chunk) {
155155
shasum.update(chunk)
156156
}).on('end', function () {
@@ -307,8 +307,8 @@ function install (gyp, argv, callback) {
307307
}
308308

309309
function downloadShasums(done) {
310-
log.verbose('check download content checksum, need to download `' + release.shasumsFile + '`...')
311-
var shasumsPath = path.resolve(devDir, release.shasumsFile)
310+
log.verbose('check download content checksum, need to download `SHASUMS256.txt`...')
311+
var shasumsPath = path.resolve(devDir, 'SHASUMS256.txt')
312312

313313
log.verbose('checksum url', release.shasumsUrl)
314314
var req = download(release.shasumsUrl)

lib/process-release.js

+60-34
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,75 @@
11
var semver = require('semver')
2-
var url = require('url')
3-
var path = require('path')
2+
, url = require('url')
3+
, path = require('path')
44

5-
var bitsre = /(x86|x64)/
6-
var bitsreV3 = /(x86|ia32|x64)/ // io.js v3.x.x shipped with "ia32" but should
7-
// have been "x86"
5+
, bitsre = /\/win-(x86|x64)\//
6+
, bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" but should
7+
// have been "x86"
88

99
// Captures all the logic required to determine download URLs, local directory and
10-
// file names and whether we need to use SHA-1 or 2. Inputs come from command-line
11-
// switches (--target), `process.version` and `process.release` where it exists.
10+
// file names. Inputs come from command-line switches (--target, --dist-url),
11+
// `process.version` and `process.release` where it exists.
1212
function processRelease (argv, gyp, defaultVersion, defaultRelease) {
1313
var version = argv[0] || gyp.opts.target || defaultVersion
14+
, isDefaultVersion = version === defaultVersion
15+
, versionSemver = semver.parse(version)
16+
, overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl
17+
, isIojs
18+
, name
19+
, distBaseUrl
20+
, baseUrl
21+
, libUrl32
22+
, libUrl64
1423

15-
// parse the version to normalize and ensure it's valid
16-
var versionSemver = semver.parse(version)
1724
if (!versionSemver) {
25+
// not a valid semver string, nothing we can do
1826
return { version: version }
1927
}
2028
// flatten version into String
2129
version = versionSemver.version
2230

23-
var overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl
24-
var iojs = !overrideDistUrl && !defaultRelease && semver.satisfies(version, '>=1.0.0 <4.0.0')
25-
var name = (defaultRelease && defaultRelease.name.replace(/\./g, '')) || (iojs ? 'iojs' : 'node') // io.js -> iojs
26-
var defaultDirUrl = (overrideDistUrl || iojs ? 'https://iojs.org/download/release' : 'https://nodejs.org/dist') + '/v' + version + '/'
27-
var baseUrl
28-
var libUrl32
29-
var libUrl64
31+
// can't use process.release if we're using --target=x.y.z
32+
if (!isDefaultVersion)
33+
defaultRelease = null
34+
35+
if (defaultRelease) {
36+
// v3 onward, has process.release
37+
name = defaultRelease.name.replace(/io\.js/, 'iojs') // remove the '.' for directory naming purposes
38+
isIojs = name === 'iojs'
39+
} else {
40+
// old node or alternative --target=
41+
isIojs = semver.satisfies(version, '>=1.0.0 <4.0.0')
42+
name = isIojs ? 'iojs' : 'node'
43+
}
44+
45+
// check for the nvm.sh standard mirror env variables
46+
if (!overrideDistUrl) {
47+
if (isIojs && process.env.NVM_IOJS_ORG_MIRROR)
48+
overrideDistUrl = process.env.NVM_IOJS_ORG_MIRROR
49+
else if (process.env.NVM_NODEJS_ORG_MIRROR)
50+
overrideDistUrl = process.env.NVM_NODEJS_ORG_MIRROR
51+
}
52+
53+
54+
if (overrideDistUrl)
55+
distBaseUrl = overrideDistUrl.replace(/\/+$/, '')
56+
else
57+
distBaseUrl = isIojs ? 'https://iojs.org/download/release' : 'https://nodejs.org/dist'
58+
distBaseUrl += '/v' + version + '/'
3059

3160
// new style, based on process.release so we have a lot of the data we need
3261
if (defaultRelease && defaultRelease.headersUrl && !overrideDistUrl) {
3362
baseUrl = url.resolve(defaultRelease.headersUrl, './')
34-
libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || defaultDirUrl, 'x86', version)
35-
libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || defaultDirUrl, 'x64', version)
63+
libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x86', version)
64+
libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x64', version)
3665

3766
return {
3867
version: version,
3968
semver: versionSemver,
4069
name: name,
4170
baseUrl: baseUrl,
4271
tarballUrl: defaultRelease.headersUrl,
43-
shasumsFile: 'SHASUMS256.txt',
4472
shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'),
45-
checksumAlgo: 'sha256',
4673
versionDir: (name !== 'node' ? name + '-' : '') + version,
4774
libUrl32: libUrl32,
4875
libUrl64: libUrl64,
@@ -52,25 +79,24 @@ function processRelease (argv, gyp, defaultVersion, defaultRelease) {
5279
}
5380

5481
// older versions without process.release are captured here and we have to make
55-
// a lot of assumptions
56-
57-
// distributions starting with 0.10.0 contain sha256 checksums
58-
var checksumAlgo = semver.gte(version, '0.10.0') ? 'sha256' : 'sha1'
59-
var shasumsFile = (checksumAlgo === 'sha256') ? 'SHASUMS256.txt' : 'SHASUMS.txt'
82+
// a lot of assumptions, additionally if you --target=x.y.z then we can't use the
83+
// current process.release
6084

61-
baseUrl = defaultDirUrl
85+
baseUrl = distBaseUrl
6286
libUrl32 = resolveLibUrl(name, baseUrl, 'x86', version)
6387
libUrl64 = resolveLibUrl(name, baseUrl, 'x64', version)
88+
// making the bold assumption that anything with a version number >3.0.0 will
89+
// have a *-headers.tar.gz file in its dist location, even some frankenstein
90+
// custom version
91+
tarballUrl = url.resolve(baseUrl, name + '-v' + version + (semver.satisfies(version, '>=3') ? '-headers' : '') + '.tar.gz')
6492

6593
return {
6694
version: version,
6795
semver: versionSemver,
6896
name: name,
6997
baseUrl: baseUrl,
70-
tarballUrl: baseUrl + name + '-v' + version + '.tar.gz',
71-
shasumsFile: shasumsFile,
72-
shasumsUrl: baseUrl + shasumsFile,
73-
checksumAlgo: checksumAlgo,
98+
tarballUrl: tarballUrl,
99+
shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'),
74100
versionDir: (name !== 'node' ? name + '-' : '') + version,
75101
libUrl32: libUrl32,
76102
libUrl64: libUrl64,
@@ -85,19 +111,19 @@ function normalizePath (p) {
85111

86112
function resolveLibUrl (name, defaultUrl, arch, version) {
87113
var base = url.resolve(defaultUrl, './')
88-
var isV3 = semver.satisfies(version, '^3')
89-
var hasLibUrl = bitsre.test(defaultUrl) || (isV3 && bitsreV3.test(defaultUrl))
114+
, isV3 = semver.satisfies(version, '^3')
115+
, hasLibUrl = bitsre.test(defaultUrl) || (isV3 && bitsreV3.test(defaultUrl))
90116

91117
if (!hasLibUrl) {
92118
// let's assume it's a baseUrl then
93119
if (semver.gte(version, '1.0.0'))
94120
return url.resolve(base, 'win-' + arch +'/' + name + '.lib')
95121
// prior to [email protected] 32-bit node.lib lives in /, 64-bit lives in /x64/
96-
return url.resolve(base, (arch == 'x64' ? 'x64/' : '') + name + '.lib')
122+
return url.resolve(base, (arch === 'x64' ? 'x64/' : '') + name + '.lib')
97123
}
98124

99125
// else we have a proper url to a .lib, just make sure it's the right arch
100-
return defaultUrl.replace(isV3 ? bitsreV3 : bitsre, arch)
126+
return defaultUrl.replace(isV3 ? bitsreV3 : bitsre, '/win-' + arch + '/')
101127
}
102128

103129
module.exports = processRelease

test/docker.sh

+75-18
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,50 @@
55
test_node_versions="0.8.28 0.10.40 0.12.7"
66
test_iojs_versions="1.8.4 2.4.0 3.3.0"
77

8+
__dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
dot_node_gyp=${__dirname}/.node-gyp/
10+
811
# borrows from https://github.com./rvagg/dnt/
912

1013
# Simple setup function for a container:
1114
# setup_container(image id, base image, commands to run to set up)
1215
setup_container() {
13-
local ID=$1
14-
local BASE=$2
15-
local RUN=$3
16+
local container_id="$1"
17+
local base_container="$2"
18+
local run_cmd="$3"
1619

1720
# Does this image exist? If yes, ignore
18-
docker inspect "$ID" &> /dev/null
21+
docker inspect "$container_id" &> /dev/null
1922
if [[ $? -eq 0 ]]; then
20-
echo "Found existing container [$ID]"
23+
echo "Found existing container [$container_id]"
2124
else
2225
# No such image, so make it
23-
echo "Did not find container [$ID], creating..."
24-
docker run -i $BASE /bin/bash -c "$RUN"
26+
echo "Did not find container [$container_id], creating..."
27+
docker run -i $base_container /bin/bash -c "$run_cmd"
2528
sleep 2
26-
docker commit $(docker ps -l -q) $ID
29+
docker commit $(docker ps -l -q) $container_id
2730
fi
2831
}
2932

3033
# Run tests inside each of the versioned containers, copy cwd into npm's copy of node-gyp
3134
# so it'll be invoked by npm when a compile is needed
3235
# run_tests(version, test-commands)
3336
run_tests() {
34-
local VERSION=$1
35-
local RUN=$2
37+
local version="$1"
38+
local run_cmd="$2"
3639

37-
RUN="rsync -aAXx --delete --exclude .git --exclude build /node-gyp-src/ /usr/lib/node_modules/npm/node_modules/node-gyp/;
38-
/bin/su -s /bin/bash node-gyp -c 'cd && ${RUN}'"
40+
run_cmd="rsync -aAXx --delete --exclude .git --exclude build /node-gyp-src/ /usr/lib/node_modules/npm/node_modules/node-gyp/;
41+
/bin/su -s /bin/bash node-gyp -c 'cd && ${run_cmd}'"
3942

40-
docker run --rm -v ~/.npm/:/dnt/.npm/ -v $(pwd):/node-gyp-src/:ro -i node-gyp-test/${VERSION} /bin/bash -c "$RUN"
41-
}
43+
rm -rf $dot_node_gyp
4244

45+
docker run \
46+
--rm -i \
47+
-v ~/.npm/:/node-gyp/.npm/ \
48+
-v ${dot_node_gyp}:/node-gyp/.node-gyp/ \
49+
-v $(pwd):/node-gyp-src/:ro \
50+
node-gyp-test/${version} /bin/bash -c "${run_cmd}"
51+
}
4352

4453
# A base image with build tools and a user account
4554
setup_container "node-gyp-test/base" "ubuntu:14.04" "
@@ -74,13 +83,61 @@ for v in $test_iojs_versions; do
7483
"
7584
done
7685

77-
7886
# Run the tests for all of the test images we've created,
7987
# we should see node-gyp doing its download, configure and run thing
8088
# _NOTE: bignum doesn't compile on 0.8 currently so it'll fail for that version only_
8189
for v in $test_node_versions $test_iojs_versions; do
8290
run_tests $v "
83-
cd node-buffertools && npm install --loglevel=info && npm test && cd &&
84-
cd node-bignum && npm install --loglevel=info && npm test
91+
cd node-buffertools && npm install --loglevel=info && npm test && cd
8592
"
86-
done
93+
# removed for now, too noisy: cd node-bignum && npm install --loglevel=info && npm test
94+
done
95+
96+
# Test use of --target=x.y.z to compile against alternate versions
97+
test_download_node_version() {
98+
local run_with_ver="$1"
99+
local expected_dir="$2"
100+
local expected_ver="$3"
101+
run_tests $run_with_ver "cd node-buffertools && npm install --loglevel=info --target=${expected_ver}"
102+
local node_ver=$(cat "${dot_node_gyp}${expected_dir}/node_version.h" | grep '#define NODE_\w*_VERSION [0-9]*$')
103+
node_ver=$(echo $node_ver | sed 's/#define NODE_[A-Z]*_VERSION //g' | sed 's/ /./g')
104+
if [ "X$(echo $node_ver)" != "X${expected_ver}" ]; then
105+
echo "Did not download v${expected_ver} using --target, instead got: $(echo $node_ver)"
106+
exit 1
107+
fi
108+
echo "Verified correct download of [v${node_ver}]"
109+
}
110+
111+
test_download_node_version "0.12.7" "0.10.30/src" "0.10.30"
112+
test_download_node_version "3.3.0" "iojs-1.8.4/src" "1.8.4"
113+
# should download the headers file
114+
test_download_node_version "3.3.0" "iojs-3.2.0/include/node" "3.2.0"
115+
116+
# TODO: test --dist-url by starting up a localhost server and serving up tarballs
117+
118+
# testing --dist-url, using simple-proxy.js to make localhost work as a distribution
119+
# point for tarballs
120+
# we can test whether it uses the proxy because after 2 connections the proxy will
121+
# die and therefore should not be running at the end of the test, `nc` can tell us this
122+
run_tests "3.3.0" "
123+
(node /node-gyp-src/test/simple-proxy.js 8080 /foobar/ https://iojs.org/dist/ &) &&
124+
cd node-buffertools &&
125+
/node-gyp-src/bin/node-gyp.js --loglevel=info --dist-url=http://localhost:8080/foobar/ rebuild &&
126+
nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\"
127+
"
128+
129+
run_tests "3.3.0" "
130+
(node /node-gyp-src/test/simple-proxy.js 8080 /doobar/ https://iojs.org/dist/ &) &&
131+
cd node-buffertools &&
132+
NVM_IOJS_ORG_MIRROR=http://localhost:8080/doobar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild &&
133+
nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\"
134+
"
135+
136+
run_tests "0.12.7" "
137+
(node /node-gyp-src/test/simple-proxy.js 8080 /boombar/ https://nodejs.org/dist/ &) &&
138+
cd node-buffertools &&
139+
NVM_NODEJS_ORG_MIRROR=http://localhost:8080/boombar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild &&
140+
nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\"
141+
"
142+
143+
rm -rf $dot_node_gyp

test/simple-proxy.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var http = require('http')
2+
, https = require('https')
3+
, server = http.createServer(handler)
4+
, port = +process.argv[2]
5+
, prefix = process.argv[3]
6+
, upstream = process.argv[4]
7+
, calls = 0
8+
9+
server.listen(port)
10+
11+
function handler (req, res) {
12+
if (req.url.indexOf(prefix) != 0)
13+
throw new Error('request url [' + req.url + '] does not start with [' + prefix + ']')
14+
15+
var upstreamUrl = upstream + req.url.substring(prefix.length)
16+
console.log(req.url + ' -> ' + upstreamUrl)
17+
https.get(upstreamUrl, function (ures) {
18+
ures.on('end', function () {
19+
if (++calls == 2)
20+
server.close()
21+
})
22+
ures.pipe(res)
23+
})
24+
}

0 commit comments

Comments
 (0)