tarball.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. 'use strict'
  2. const BB = require('bluebird')
  3. const fs = require('fs')
  4. const getStream = require('get-stream')
  5. const mkdirp = BB.promisify(require('mkdirp'))
  6. const npa = require('npm-package-arg')
  7. const optCheck = require('./lib/util/opt-check.js')
  8. const PassThrough = require('stream').PassThrough
  9. const path = require('path')
  10. const rimraf = BB.promisify(require('rimraf'))
  11. const withTarballStream = require('./lib/with-tarball-stream.js')
  12. module.exports = tarball
  13. function tarball (spec, opts) {
  14. opts = optCheck(opts)
  15. spec = npa(spec, opts.where)
  16. return withTarballStream(spec, opts, stream => getStream.buffer(stream))
  17. }
  18. module.exports.stream = tarballStream
  19. function tarballStream (spec, opts) {
  20. opts = optCheck(opts)
  21. spec = npa(spec, opts.where)
  22. const output = new PassThrough()
  23. let hasTouchedOutput = false
  24. let lastError = null
  25. withTarballStream(spec, opts, stream => {
  26. if (hasTouchedOutput && lastError) {
  27. throw lastError
  28. } else if (hasTouchedOutput) {
  29. throw new Error('abort, abort!')
  30. } else {
  31. return new BB((resolve, reject) => {
  32. stream.on('error', reject)
  33. output.on('error', reject)
  34. output.on('error', () => { hasTouchedOutput = true })
  35. output.on('finish', resolve)
  36. stream.pipe(output)
  37. stream.once('data', () => { hasTouchedOutput = true })
  38. }).catch(err => {
  39. lastError = err
  40. throw err
  41. })
  42. }
  43. })
  44. .catch(err => output.emit('error', err))
  45. return output
  46. }
  47. module.exports.toFile = tarballToFile
  48. function tarballToFile (spec, dest, opts) {
  49. opts = optCheck(opts)
  50. spec = npa(spec, opts.where)
  51. return mkdirp(path.dirname(dest))
  52. .then(() => withTarballStream(spec, opts, stream => {
  53. return rimraf(dest)
  54. .then(() => new BB((resolve, reject) => {
  55. const writer = fs.createWriteStream(dest)
  56. stream.on('error', reject)
  57. writer.on('error', reject)
  58. writer.on('close', resolve)
  59. stream.pipe(writer)
  60. }))
  61. }))
  62. }