mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-02 19:22:52 -05:00
68 lines
1.8 KiB
JavaScript
68 lines
1.8 KiB
JavaScript
'use strict'
|
|
const debug = require('debug')('pnpm:fetch')
|
|
const crypto = require('crypto')
|
|
const gunzip = require('gunzip-maybe')
|
|
const tar = require('tar-fs')
|
|
const fs = require('fs')
|
|
|
|
/*
|
|
* Fetches a tarball `tarball` and extracts it into `dir`
|
|
*/
|
|
|
|
module.exports = function fetch (dir, dist, opts) {
|
|
if (!dist.local) {
|
|
return opts.got.getStream(dist.tarball)
|
|
.then(stream => fetchStream(dir, dist.tarball, dist.shasum, opts.log, stream))
|
|
}
|
|
return unpackStream(fs.createReadStream(dist.tarball), dir)
|
|
}
|
|
|
|
function fetchStream (dir, tarball, shasum, log, stream) {
|
|
return new Promise((resolve, reject) => {
|
|
const actualShasum = crypto.createHash('sha1')
|
|
let size
|
|
let downloaded = 0
|
|
|
|
unpackStream(
|
|
stream
|
|
.on('response', start)
|
|
.on('data', _ => { actualShasum.update(_) })
|
|
.on('error', reject), dir
|
|
).then(finish)
|
|
|
|
function start (res) {
|
|
if (res.statusCode !== 200) {
|
|
return reject(new Error('' + tarball + ': invalid response ' + res.statusCode))
|
|
}
|
|
|
|
log('download-start')
|
|
if ('content-length' in res.headers) {
|
|
size = +res.headers['content-length']
|
|
res.on('data', chunk => {
|
|
downloaded += chunk.length
|
|
log('downloading', { done: downloaded, total: size })
|
|
})
|
|
}
|
|
}
|
|
|
|
function finish () {
|
|
const digest = actualShasum.digest('hex')
|
|
debug('finish %s %s', shasum, tarball)
|
|
if (shasum && digest !== shasum) {
|
|
return reject(new Error('' + tarball + ': incorrect shasum (expected ' + shasum + ', got ' + digest + ')'))
|
|
}
|
|
|
|
return resolve(dir)
|
|
}
|
|
})
|
|
}
|
|
|
|
function unpackStream (stream, dir) {
|
|
return new Promise((resolve, reject) => {
|
|
stream
|
|
.pipe(gunzip()).on('error', reject)
|
|
.pipe(tar.extract(dir, { strip: 1 })).on('error', reject)
|
|
.on('finish', resolve)
|
|
})
|
|
}
|