diff --git a/lib/core.js b/lib/core.js index f7424885..4ae98d63 100644 --- a/lib/core.js +++ b/lib/core.js @@ -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; @@ -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) { @@ -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)); }; @@ -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));