UNPKG

extract-base-iterator

Version:

Base iterator for extract iterators like tar-iterator and zip-iterator

75 lines (74 loc) 3.43 kB
import { rm } from 'fs-remove-compat'; import fs from 'graceful-fs'; import mkdirp from 'mkdirp-classic'; import path from 'path'; import Queue from 'queue-cb'; import chmod from './fs/chmod.js'; import chown from './fs/chown.js'; import utimes from './fs/utimes.js'; import { objectAssign } from './shared/index.js'; import safeJoinPath from './shared/safeJoinPath.js'; import stripPath from './shared/stripPath.js'; import validateAttributes from './validateAttributes.js'; import waitForAccess from './waitForAccess.js'; const MANDATORY_ATTRIBUTES = [ 'mode', 'mtime', 'path' ]; let FileEntry = class FileEntry { create(dest, options, callback) { callback = typeof options === 'function' ? options : callback; options = typeof options === 'function' ? {} : options || {}; if (typeof callback === 'function') { try { const normalizedPath = path.normalize(this.path); const fullPath = safeJoinPath(dest, stripPath(normalizedPath, options)); const queue = new Queue(1); if (options.force) { queue.defer((callback)=>{ rm(fullPath, (err)=>{ err && err.code !== 'ENOENT' ? callback(err) : callback(); }); }); } else { // Check if file exists - throw EEXIST if it does queue.defer((callback)=>{ fs.stat(fullPath, (err)=>{ if (!err) { const existsErr = new Error(`EEXIST: file already exists, open '${fullPath}'`); existsErr.code = 'EEXIST'; existsErr.path = fullPath; return callback(existsErr); } // ENOENT means file doesn't exist - that's what we want if (err.code === 'ENOENT') return callback(); // Other errors should be reported callback(err); }); }); } queue.defer((cb)=>mkdirp(path.dirname(fullPath), (err)=>cb(err))); queue.defer(this._writeFile.bind(this, fullPath, options)); queue.defer((cb)=>waitForAccess(fullPath, cb)); queue.defer((cb)=>chmod(fullPath, this, options, (err)=>cb(err))); queue.defer((cb)=>chown(fullPath, this, options, (err)=>cb(err))); queue.defer((cb)=>utimes(fullPath, this, options, (err)=>cb(err))); queue.await(callback); } catch (err) { callback(err); } return; } return new Promise((resolve, reject)=>this.create(dest, options, (err)=>err ? reject(err) : resolve(true))); } destroy() {} constructor(attributes){ validateAttributes(attributes, MANDATORY_ATTRIBUTES); objectAssign(this, attributes); if (this.basename === undefined) this.basename = path.basename(this.path); if (this.type === undefined) this.type = 'file'; if (this._writeFile === undefined) throw new Error('File this missing _writeFile. Please implement this method in your subclass'); } }; export { FileEntry as default };