Skip to content
50 changes: 43 additions & 7 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var Archiver = function(format, options) {
this._module = false;
this._pending = 0;
this._pointer = 0;
this._followSymlinks = options.followSymlinks;

this._entriesCount = 0;
this._entriesProcessedCount = 0;
Expand Down Expand Up @@ -91,12 +92,13 @@ Archiver.prototype._abort = function() {
* @param {EntryData} data The entry data.
* @return void
*/
Archiver.prototype._append = function(filepath, data) {
Archiver.prototype._append = function(filepath, data, recursive) {
data = data || {};

var task = {
source: null,
filepath: filepath
filepath: filepath,
recursive: recursive || false
};

if (!data.name) {
Expand Down Expand Up @@ -439,7 +441,34 @@ Archiver.prototype._onStatQueueTask = function(task, callback) {
this._queue.push(task);
}

setImmediate(callback);
if (task.recursive && task.data.type === 'directory') {
fs.readdir(task.filepath, function(err, files) {
if (this._state.aborted) {
setImmediate(callback);
return;
}

if (err) {
this.emit('warning', err);
setImmediate(callback);
return;
}

files.forEach(function(filename) {
if (filename === '.' || filename === '..') {
return;
}

this._append(path.join(task.filepath, filename), {
name: path.join(task.data.name, filename)
}, true);
}.bind(this));

setImmediate(callback);
}.bind(this));
} else {
setImmediate(callback);
}
}.bind(this));
};

Expand Down Expand Up @@ -493,10 +522,17 @@ Archiver.prototype._updateQueueTaskWithStats = function(task, stats) {
} else if (stats.isSymbolicLink() && this._moduleSupports('symlink')) {
var linkPath = fs.readlinkSync(task.filepath);
var dirName = path.dirname(task.filepath);
task.data.type = 'symlink';
task.data.linkname = path.relative(dirName, path.resolve(dirName, linkPath));
task.data.sourceType = 'buffer';
task.source = Buffer.concat([]);

if (this._followSymlinks) {
task.filepath = path.resolve(dirName, linkPath);
task.recursive = true;
return this._updateQueueTaskWithStats(task, fs.lstatSync(task.filepath));
} else {
task.data.type = 'symlink';
task.data.linkname = path.relative(dirName, path.resolve(dirName, linkPath));
task.data.sourceType = 'buffer';
task.source = Buffer.concat([]);
}
} else {
if (stats.isDirectory()) {
this.emit('warning', new ArchiverError('DIRECTORYNOTSUPPORTED', task.data));
Expand Down