161 lines
4.4 KiB
JavaScript
161 lines
4.4 KiB
JavaScript
var path = require('path')
|
|
var fs = require('fs')
|
|
var get = require('simple-get')
|
|
var pump = require('pump')
|
|
var tfs = require('tar-fs')
|
|
var noop = require('noop-logger')
|
|
var zlib = require('zlib')
|
|
var util = require('./util')
|
|
var error = require('./error')
|
|
var url = require('url')
|
|
var tunnel = require('tunnel-agent')
|
|
|
|
function downloadPrebuild (opts, cb) {
|
|
var downloadUrl = util.getDownloadUrl(opts)
|
|
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
|
|
var localPrebuild = util.localPrebuild(downloadUrl)
|
|
var tempFile = util.tempFile(cachedPrebuild)
|
|
|
|
var log = opts.log || noop
|
|
|
|
if (opts.nolocal) return download()
|
|
|
|
log.info('looking for local prebuild @', localPrebuild)
|
|
fs.exists(localPrebuild, function (exists) {
|
|
if (exists) {
|
|
log.info('found local prebuild')
|
|
cachedPrebuild = localPrebuild
|
|
return unpack()
|
|
}
|
|
|
|
download()
|
|
})
|
|
|
|
function download () {
|
|
ensureNpmCacheDir(function (err) {
|
|
if (err) return onerror(err)
|
|
|
|
log.info('looking for cached prebuild @', cachedPrebuild)
|
|
fs.exists(cachedPrebuild, function (exists) {
|
|
if (exists) {
|
|
log.info('found cached prebuild')
|
|
return unpack()
|
|
}
|
|
|
|
log.http('request', 'GET ' + downloadUrl)
|
|
var reqOpts = { url: downloadUrl }
|
|
var proxy = opts['https-proxy'] || opts.proxy
|
|
|
|
if (proxy) {
|
|
var parsedDownloadUrl = url.parse(downloadUrl)
|
|
var parsedProxy = url.parse(proxy)
|
|
var uriProtocol = (parsedDownloadUrl.protocol === 'https:' ? 'https' : 'http')
|
|
var proxyProtocol = (parsedProxy.protocol === 'https:' ? 'Https' : 'Http')
|
|
var tunnelFnName = [uriProtocol, proxyProtocol].join('Over')
|
|
reqOpts.agent = tunnel[tunnelFnName]({
|
|
proxy: {
|
|
host: parsedProxy.hostname,
|
|
port: +parsedProxy.port,
|
|
proxyAuth: parsedProxy.auth
|
|
}
|
|
})
|
|
}
|
|
|
|
var req = get(reqOpts, function (err, res) {
|
|
if (err) return onerror(err)
|
|
log.http(res.statusCode, downloadUrl)
|
|
if (res.statusCode !== 200) return onerror()
|
|
fs.mkdir(util.prebuildCache(), function () {
|
|
log.info('downloading to @', tempFile)
|
|
pump(res, fs.createWriteStream(tempFile), function (err) {
|
|
if (err) return onerror(err)
|
|
fs.rename(tempFile, cachedPrebuild, function (err) {
|
|
if (err) return cb(err)
|
|
log.info('renaming to @', cachedPrebuild)
|
|
unpack()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
req.setTimeout(30 * 1000, function () {
|
|
req.abort()
|
|
})
|
|
})
|
|
|
|
function onerror (err) {
|
|
fs.unlink(tempFile, function () {
|
|
cb(err || error.noPrebuilts(opts))
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
function unpack () {
|
|
var binaryName
|
|
|
|
var updateName = opts.updateName || function (entry) {
|
|
if (/\.node$/i.test(entry.name)) binaryName = entry.name
|
|
}
|
|
|
|
log.info('unpacking @', cachedPrebuild)
|
|
|
|
var options = {
|
|
readable: true,
|
|
writable: true,
|
|
hardlinkAsFilesFallback: true
|
|
}
|
|
var extract = tfs.extract(opts.path, options).on('entry', updateName)
|
|
|
|
pump(fs.createReadStream(cachedPrebuild), zlib.createGunzip(), extract,
|
|
function (err) {
|
|
if (err) return cb(err)
|
|
|
|
var resolved
|
|
if (binaryName) {
|
|
try {
|
|
resolved = path.resolve(opts.path || '.', binaryName)
|
|
} catch (err) {
|
|
return cb(err)
|
|
}
|
|
log.info('unpack', 'resolved to ' + resolved)
|
|
|
|
if (opts.abi === process.versions.modules) {
|
|
try {
|
|
require(resolved)
|
|
} catch (err) {
|
|
return cb(err)
|
|
}
|
|
log.info('unpack', 'required ' + resolved + ' successfully')
|
|
}
|
|
}
|
|
|
|
cb(null, resolved)
|
|
})
|
|
}
|
|
|
|
function ensureNpmCacheDir (cb) {
|
|
var cacheFolder = util.npmCache()
|
|
if (fs.access) {
|
|
fs.access(cacheFolder, fs.R_OK | fs.W_OK, function (err) {
|
|
if (err && err.code === 'ENOENT') {
|
|
return makeNpmCacheDir()
|
|
}
|
|
cb(err)
|
|
})
|
|
} else {
|
|
fs.exists(cacheFolder, function (exists) {
|
|
if (!exists) return makeNpmCacheDir()
|
|
cb()
|
|
})
|
|
}
|
|
|
|
function makeNpmCacheDir () {
|
|
log.info('npm cache directory missing, creating it...')
|
|
fs.mkdir(cacheFolder, cb)
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = downloadPrebuild
|