extract-base-iterator
Version:
Base iterator for extract iterators like tar-iterator and zip-iterator
78 lines (77 loc) • 3.41 kB
JavaScript
import path from 'path';
import fs from 'graceful-fs';
import isAbsolute from 'is-absolute';
import mkdirp from 'mkdirp-classic';
import objectAssign from 'object-assign';
import Queue from 'queue-cb';
import rimraf2 from 'rimraf2';
import chmod from './fs/chmod.mjs';
import chown from './fs/chown.mjs';
import lstatReal from './fs/lstatReal.mjs';
import utimes from './fs/utimes.mjs';
import stripPath from './stripPath.mjs';
import validateAttributes from './validateAttributes.mjs';
function symlinkWin32(linkFullPath, linkpath, fullPath, callback) {
lstatReal(linkFullPath, (err, targetStat)=>{
if (err || !targetStat) return callback(err || new Error(`Symlink path does not exist${linkFullPath}`));
const type = targetStat.isDirectory() ? 'dir' : 'file';
fs.symlink(linkpath, fullPath, type, callback);
});
}
const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE);
const MANDATORY_ATTRIBUTES = [
'mode',
'mtime',
'path',
'linkpath'
];
export default function SymbolicLinkEntry(attributes) {
validateAttributes(attributes, MANDATORY_ATTRIBUTES);
objectAssign(this, attributes);
if (this.basename === undefined) this.basename = path.basename(this.path);
if (this.type === undefined) this.type = 'symlink';
}
SymbolicLinkEntry.prototype.create = function create(dest, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
const self = this;
if (typeof callback === 'function') {
options = options || {};
try {
const normalizedPath = path.normalize(self.path);
const fullPath = path.join(dest, stripPath(normalizedPath, options));
let normalizedLinkpath = path.normalize(self.linkpath);
let linkFullPath = path.join(dest, stripPath(normalizedLinkpath, options));
if (!isAbsolute(normalizedLinkpath)) {
const linkRelativePath = path.join(path.dirname(normalizedPath), self.linkpath);
linkFullPath = path.join(dest, stripPath(linkRelativePath, options));
normalizedLinkpath = path.relative(path.dirname(fullPath), linkFullPath);
}
const queue = new Queue(1);
if (options.force) {
queue.defer((callback)=>{
rimraf2(fullPath, {
disableGlob: true
}, (err)=>{
err && err.code !== 'ENOENT' ? callback(err) : callback();
});
});
}
queue.defer(mkdirp.bind(null, path.dirname(fullPath)));
if (isWindows) queue.defer(symlinkWin32.bind(null, linkFullPath, normalizedLinkpath, fullPath));
else queue.defer(fs.symlink.bind(fs, normalizedLinkpath, fullPath));
queue.defer(chmod.bind(null, fullPath, self, options));
queue.defer(chown.bind(null, fullPath, self, options));
queue.defer(utimes.bind(null, fullPath, self, options));
return queue.await(callback);
} catch (err) {
return callback(err);
}
}
return new Promise(function createPromise(resolve, reject) {
self.create(dest, options, (err, done)=>err ? reject(err) : resolve(done));
});
};
SymbolicLinkEntry.prototype.destroy = function destroy() {};