tar-iterator
Version:
Extract contents from tar archive type using an iterator API using streams or paths. Use stream interface and pipe transforms to add decompression algorithms
55 lines (54 loc) • 2.29 kB
JavaScript
import once from 'call-once-fn';
import { DirectoryEntry, LinkEntry, SymbolicLinkEntry } from 'extract-base-iterator';
import compact from 'lodash.compact';
import path from 'path';
import FileEntry from './FileEntry.js';
export default function nextEntry(next, iterator, callback) {
const extract = iterator.extract;
if (!extract) return callback(new Error('Extract missing'));
const nextCallback = once((err, entry, next)=>{
extract.removeListener('entry', onEntry);
extract.removeListener('error', onError);
extract.removeListener('finish', onEnd);
// keep processing
if (entry) iterator.push(nextEntry.bind(null, next));
err ? callback(err) : callback(null, entry ? {
done: false,
value: entry
} : {
done: true,
value: null
});
});
const onError = callback;
const onEnd = callback.bind(null, null);
const onEntry = function onEntry(header, stream, next) {
if (iterator.isDone()) return nextCallback(null, null, next);
const attributes = {
...header
};
attributes.path = compact(header.name.split(path.sep)).join(path.sep);
attributes.mtime = new Date(attributes.mtime);
switch(attributes.type){
case 'directory':
stream.resume(); // drain stream
return nextCallback(null, new DirectoryEntry(attributes), next);
case 'symlink':
stream.resume(); // drain stream
attributes.linkpath = header.linkname;
return nextCallback(null, new SymbolicLinkEntry(attributes), next);
case 'link':
stream.resume(); // drain stream
attributes.linkpath = header.linkname;
return nextCallback(null, new LinkEntry(attributes), next);
case 'file':
return nextCallback(null, new FileEntry(attributes, stream, iterator.lock), next);
}
stream.resume(); // drain stream
return nextCallback(new Error(`Unrecognized entry type: ${attributes.type}`), null, next);
};
extract.on('entry', onEntry);
extract.on('error', onError);
extract.on('finish', onEnd);
if (next) next();
}