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