* Downloads and unpacks a given tarball or zip file at a given path. * @param {string} uri The path of the compressed file to download and extract. * @param {string} destPath The destination path for the compressed content. * @param {Function} callback Handler for when downloading and extraction
(uri, destPath, callback)
| 37 | * complete. |
| 38 | */ |
| 39 | async function downloadAndUnpackResource(uri, destPath, callback) { |
| 40 | const httpClient = uri.startsWith('https') ? https : http; |
| 41 | |
| 42 | // If HTTPS_PROXY, https_proxy, HTTP_PROXY, or http_proxy is set |
| 43 | const proxy = process.env['HTTPS_PROXY'] || process.env['https_proxy'] || |
| 44 | process.env['HTTP_PROXY'] || process.env['http_proxy'] || ''; |
| 45 | |
| 46 | // Using object destructuring to construct the options object for the |
| 47 | // http request. the '...url.parse(targetUri)' part fills in the host, |
| 48 | // path, protocol, etc from the targetUri and then we set the agent to the |
| 49 | // default agent which is overridden a few lines down if there is a proxy |
| 50 | const options = {...url.parse(uri), agent: httpClient.globalAgent}; |
| 51 | |
| 52 | if (proxy !== '') { |
| 53 | options.agent = new HttpsProxyAgent(proxy); |
| 54 | } |
| 55 | |
| 56 | const request = httpClient.get(options, response => { |
| 57 | const bar = new ProgressBar('[:bar] :rate/bps :percent :etas', { |
| 58 | complete: '=', |
| 59 | incomplete: ' ', |
| 60 | width: 30, |
| 61 | total: parseInt(response.headers['content-length'], 10) |
| 62 | }); |
| 63 | |
| 64 | if (uri.endsWith('.zip')) { |
| 65 | // Save zip file to disk, extract, and delete the downloaded zip file. |
| 66 | const tempFileName = path.join(__dirname, '_tmp.zip'); |
| 67 | const outputFile = fs.createWriteStream(tempFileName); |
| 68 | |
| 69 | response.on('data', chunk => bar.tick(chunk.length)) |
| 70 | .pipe(outputFile) |
| 71 | .on('close', async () => { |
| 72 | const zipFile = new zip(tempFileName); |
| 73 | zipFile.extractAllTo(destPath, true /* overwrite */); |
| 74 | |
| 75 | await unlink(tempFileName); |
| 76 | |
| 77 | if (callback !== undefined) { |
| 78 | callback(); |
| 79 | } |
| 80 | }); |
| 81 | } else if (uri.endsWith('.tar.gz')) { |
| 82 | response.on('data', chunk => bar.tick(chunk.length)) |
| 83 | .pipe(tar.x({C: destPath, strict: true})) |
| 84 | .on('close', () => { |
| 85 | if (callback !== undefined) { |
| 86 | callback(); |
| 87 | } |
| 88 | }); |
| 89 | } else { |
| 90 | throw new Error(`Unsupported packed resource: ${uri}`); |
| 91 | } |
| 92 | }); |
| 93 | request.end(); |
| 94 | } |
| 95 | |
| 96 | module.exports = {downloadAndUnpackResource}; |