create.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. 'use strict'
  2. // tar -c
  3. const hlo = require('./high-level-opt.js')
  4. const Pack = require('./pack.js')
  5. const fsm = require('fs-minipass')
  6. const t = require('./list.js')
  7. const path = require('path')
  8. module.exports = (opt_, files, cb) => {
  9. if (typeof files === 'function')
  10. cb = files
  11. if (Array.isArray(opt_))
  12. files = opt_, opt_ = {}
  13. if (!files || !Array.isArray(files) || !files.length)
  14. throw new TypeError('no files or directories specified')
  15. files = Array.from(files)
  16. const opt = hlo(opt_)
  17. if (opt.sync && typeof cb === 'function')
  18. throw new TypeError('callback not supported for sync tar functions')
  19. if (!opt.file && typeof cb === 'function')
  20. throw new TypeError('callback only supported with file option')
  21. return opt.file && opt.sync ? createFileSync(opt, files)
  22. : opt.file ? createFile(opt, files, cb)
  23. : opt.sync ? createSync(opt, files)
  24. : create(opt, files)
  25. }
  26. const createFileSync = (opt, files) => {
  27. const p = new Pack.Sync(opt)
  28. const stream = new fsm.WriteStreamSync(opt.file, {
  29. mode: opt.mode || 0o666,
  30. })
  31. p.pipe(stream)
  32. addFilesSync(p, files)
  33. }
  34. const createFile = (opt, files, cb) => {
  35. const p = new Pack(opt)
  36. const stream = new fsm.WriteStream(opt.file, {
  37. mode: opt.mode || 0o666,
  38. })
  39. p.pipe(stream)
  40. const promise = new Promise((res, rej) => {
  41. stream.on('error', rej)
  42. stream.on('close', res)
  43. p.on('error', rej)
  44. })
  45. addFilesAsync(p, files)
  46. return cb ? promise.then(cb, cb) : promise
  47. }
  48. const addFilesSync = (p, files) => {
  49. files.forEach(file => {
  50. if (file.charAt(0) === '@') {
  51. t({
  52. file: path.resolve(p.cwd, file.substr(1)),
  53. sync: true,
  54. noResume: true,
  55. onentry: entry => p.add(entry),
  56. })
  57. } else
  58. p.add(file)
  59. })
  60. p.end()
  61. }
  62. const addFilesAsync = (p, files) => {
  63. while (files.length) {
  64. const file = files.shift()
  65. if (file.charAt(0) === '@') {
  66. return t({
  67. file: path.resolve(p.cwd, file.substr(1)),
  68. noResume: true,
  69. onentry: entry => p.add(entry),
  70. }).then(_ => addFilesAsync(p, files))
  71. } else
  72. p.add(file)
  73. }
  74. p.end()
  75. }
  76. const createSync = (opt, files) => {
  77. const p = new Pack.Sync(opt)
  78. addFilesSync(p, files)
  79. return p
  80. }
  81. const create = (opt, files) => {
  82. const p = new Pack(opt)
  83. addFilesAsync(p, files)
  84. return p
  85. }