2016-10-29 17:10:46 +02:00
|
|
|
import { Promise, map, fromNode, promisify } from 'bluebird';
|
|
|
|
import { resolve, basename, dirname, join } from 'path';
|
|
|
|
import { createReadStream, createWriteStream, writeFile } from 'fs';
|
|
|
|
import { createGunzip } from 'zlib';
|
|
|
|
import { Extract } from 'tar';
|
|
|
|
import { fromFile } from 'check-hash';
|
|
|
|
import wreck from 'wreck';
|
|
|
|
import { mkdirp } from 'mkdirp';
|
2015-08-14 20:53:26 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const mkdirpAsync = promisify(mkdirp);
|
|
|
|
const wreckGetAsync = promisify(wreck.get, wreck);
|
|
|
|
const checkHashFromFileAsync = promisify(fromFile);
|
|
|
|
const writeFileAsync = promisify(writeFile);
|
2015-08-14 20:53:26 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
export default function downloadNodeBuilds(grunt) {
|
|
|
|
const platforms = grunt.config.get('platforms');
|
|
|
|
const downloadLimit = 3;
|
2015-08-14 20:53:26 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const shaSums = {};
|
|
|
|
const getShaSums = () => {
|
|
|
|
const nodeVersion = grunt.config.get('nodeVersion');
|
|
|
|
const shaSumsUri = `https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt`;
|
2015-08-14 20:53:26 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
return wreckGetAsync(shaSumsUri).then(([resp, payload]) => {
|
|
|
|
if (resp.statusCode !== 200) {
|
|
|
|
throw new Error(`${shaSumsUri} failed with a ${resp.statusCode} response`);
|
|
|
|
}
|
|
|
|
payload
|
|
|
|
.toString('utf8')
|
|
|
|
.split('\n')
|
|
|
|
.forEach(line => {
|
|
|
|
const [sha, platform] = line.split(' ');
|
|
|
|
shaSums[platform] = sha;
|
2015-08-14 20:53:26 +02:00
|
|
|
});
|
2015-08-14 06:16:54 +02:00
|
|
|
});
|
2016-10-29 17:10:46 +02:00
|
|
|
};
|
2015-08-14 06:16:54 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const checkShaSum = (platform) => {
|
|
|
|
const file = basename(platform.nodeUrl);
|
|
|
|
const downloadDir = join(platform.nodeDir, '..');
|
|
|
|
const filePath = resolve(downloadDir, file);
|
|
|
|
const expected = {
|
|
|
|
hash: 'sha256',
|
|
|
|
expected: platform.win ? shaSums[basename(dirname(platform.nodeUrl)) + '/' + file] : shaSums[file]
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!grunt.file.isFile(filePath)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return checkHashFromFileAsync(filePath, expected).then(([passed, actual]) => {
|
|
|
|
if (!passed) {
|
|
|
|
grunt.log.error(`${platform.name} shasum check failed`);
|
2015-08-14 06:16:54 +02:00
|
|
|
}
|
2016-10-29 17:10:46 +02:00
|
|
|
return passed;
|
|
|
|
});
|
|
|
|
};
|
2015-08-14 06:16:54 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const getNodeBuild = (platform) => {
|
|
|
|
const downloadDir = join(platform.nodeDir, '..');
|
|
|
|
const file = basename(platform.nodeUrl);
|
|
|
|
const filePath = resolve(downloadDir, file);
|
|
|
|
|
|
|
|
if (grunt.file.isFile(filePath)) {
|
|
|
|
grunt.file.delete(filePath);
|
|
|
|
}
|
2015-08-14 06:16:54 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
return wreckGetAsync(platform.nodeUrl)
|
|
|
|
.then(([resp, payload]) => {
|
|
|
|
if (resp.statusCode !== 200) {
|
|
|
|
throw new Error(`${platform.nodeUrl} failed with a ${resp.statusCode} response`);
|
|
|
|
}
|
|
|
|
return payload;
|
|
|
|
})
|
|
|
|
.then(payload => writeFileAsync(filePath, payload));
|
2015-08-14 06:16:54 +02:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const start = async (platform) => {
|
|
|
|
const downloadDir = join(platform.nodeDir, '..');
|
|
|
|
let downloadCounter = 0;
|
|
|
|
let isDownloadValid = false;
|
|
|
|
|
|
|
|
await mkdirpAsync(downloadDir);
|
|
|
|
if (grunt.option('skip-node-download')) {
|
|
|
|
grunt.log.ok(`Verifying sha sum of ${platform.name}`);
|
|
|
|
isDownloadValid = await checkShaSum(platform);
|
|
|
|
if (!isDownloadValid) {
|
|
|
|
throw new Error(`${platform.name} sha verification failed.`);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!isDownloadValid && (downloadCounter < downloadLimit)) {
|
|
|
|
grunt.log.ok(`Downloading ${platform.name} and corresponding sha`);
|
|
|
|
await getNodeBuild(platform);
|
|
|
|
isDownloadValid = await checkShaSum(platform);
|
|
|
|
++downloadCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isDownloadValid) {
|
|
|
|
throw new Error(`${platform.name} download failed`);
|
|
|
|
}
|
|
|
|
|
|
|
|
grunt.log.ok(`${platform.name} downloaded and verified`);
|
|
|
|
};
|
|
|
|
|
|
|
|
grunt.registerTask('_build:downloadNodeBuilds', function () {
|
|
|
|
const done = this.async();
|
|
|
|
getShaSums()
|
|
|
|
.then(() => map(platforms, start))
|
|
|
|
.nodeify(done);
|
2015-08-14 20:53:26 +02:00
|
|
|
});
|
2015-08-14 06:16:54 +02:00
|
|
|
|
2016-10-29 17:10:46 +02:00
|
|
|
const extractNodeBuild = async (platform) => {
|
|
|
|
const file = basename(platform.nodeUrl);
|
|
|
|
const downloadDir = join(platform.nodeDir, '..');
|
|
|
|
const filePath = resolve(downloadDir, file);
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
createReadStream(filePath)
|
|
|
|
.pipe(createGunzip())
|
|
|
|
.on('error', reject)
|
2016-12-14 21:29:32 +01:00
|
|
|
.pipe(new Extract({ path: platform.nodeDir, strip: 1 }))
|
2016-10-29 17:10:46 +02:00
|
|
|
.on('error', reject)
|
|
|
|
.on('end', resolve);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const extract = async(platform) => {
|
|
|
|
const file = basename(platform.nodeUrl);
|
|
|
|
const downloadDir = join(platform.nodeDir, '..');
|
|
|
|
const filePath = resolve(downloadDir, file);
|
|
|
|
|
|
|
|
if (grunt.file.isDir(platform.nodeDir)) {
|
|
|
|
grunt.file.delete(platform.nodeDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (platform.win) {
|
|
|
|
grunt.file.mkdir(platform.nodeDir);
|
|
|
|
grunt.file.copy(filePath, resolve(platform.nodeDir, file));
|
|
|
|
} else {
|
|
|
|
await extractNodeBuild(platform);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
grunt.registerTask('_build:extractNodeBuilds', function () {
|
|
|
|
map(platforms, extract).nodeify(this.async());
|
2015-08-14 06:16:54 +02:00
|
|
|
});
|
2016-10-29 17:10:46 +02:00
|
|
|
|
2016-12-14 02:17:47 +01:00
|
|
|
}
|