create.js 2.3 KB

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