From 48db05395486946cf3ca4b109e33c5a0e082bb4d Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Mon, 17 Apr 2017 14:03:48 +0200 Subject: [PATCH] [WIP] Support symlinks --- lib/core.js | 19 ++++++++------ lib/plugins/json.js | 5 ++-- lib/plugins/tar.js | 5 ++-- lib/plugins/zip.js | 5 ++-- test/archiver.js | 4 ++- test/fixtures/directory/subdir/level0link.txt | 1 + test/plugins.js | 25 ++++++++++++------- 7 files changed, 40 insertions(+), 24 deletions(-) create mode 120000 test/fixtures/directory/subdir/level0link.txt diff --git a/lib/core.js b/lib/core.js index 10a9e597c..8d9cec743 100644 --- a/lib/core.js +++ b/lib/core.js @@ -109,7 +109,7 @@ Archiver.prototype._append = function(filepath, data) { if (data.stats && data.stats instanceof fs.Stats) { task = this._updateQueueTaskWithStats(task, data.stats); - this._queue.push(task); + if (task) this._queue.push(task); } else { this._statQueue.push(task); } @@ -398,14 +398,10 @@ Archiver.prototype._onStatQueueTask = function(task, callback) { task = this._updateQueueTaskWithStats(task, stats); - if (task.source !== null) { + if (task) { this._queue.push(task); - setImmediate(callback); - } else { - this.emit('error', new Error('unsupported entry: ' + task.filepath)); - setImmediate(callback); - return; } + setImmediate(callback); }.bind(this)); }; @@ -456,8 +452,14 @@ Archiver.prototype._updateQueueTaskWithStats = function(task, stats) { task.data.sourcePath = util.trailingSlashIt(task.filepath); task.data.sourceType = 'buffer'; task.source = new Buffer(0); + } else if (stats.isSymbolicLink() && this._moduleSupports('symlink')) { + task.data.type = 'symlink'; + task.data.linkname = fs.readlinkSync(task.filepath); + task.data.sourceType = 'buffer'; + task.source = new Buffer(0); } else { - return task; + this.emit('error', new Error('unsupported entry: ' + task.filepath)); + return null; } task.data = this._normalizeEntryData(task.data, stats); @@ -695,6 +697,7 @@ Archiver.prototype.directory = function(dirpath, destpath, data) { walker.on('error', onWalkError.bind(this)); walker.on('directory', onWalkPath.bind(this)); walker.on('file', onWalkPath.bind(this)); + walker.on('link', onWalkPath.bind(this)); walker.on('end', onWalkEnd.bind(this)); return this; diff --git a/lib/plugins/json.js b/lib/plugins/json.js index b96a90fff..caf63de94 100644 --- a/lib/plugins/json.js +++ b/lib/plugins/json.js @@ -25,7 +25,8 @@ var Json = function(options) { Transform.call(this, options); this.supports = { - directory: true + directory: true, + symlink: true }; this.files = []; @@ -106,4 +107,4 @@ module.exports = Json; /** * @typedef {Object} JsonOptions * @global - */ \ No newline at end of file + */ diff --git a/lib/plugins/tar.js b/lib/plugins/tar.js index 7f2ec9c08..41e70b9cb 100644 --- a/lib/plugins/tar.js +++ b/lib/plugins/tar.js @@ -28,7 +28,8 @@ var Tar = function(options) { } this.supports = { - directory: true + directory: true, + symlink: true }; this.engine = engine.pack(options); @@ -163,4 +164,4 @@ module.exports = Tar; * TarStream Module * @external TarStream * @see {@link https://github.com/mafintosh/tar-stream} - */ \ No newline at end of file + */ diff --git a/lib/plugins/zip.js b/lib/plugins/zip.js index 75364d014..8eea00d47 100644 --- a/lib/plugins/zip.js +++ b/lib/plugins/zip.js @@ -29,7 +29,8 @@ var Zip = function(options) { }); this.supports = { - directory: true + directory: true, + symlink: false }; this.engine = new engine(options); @@ -112,4 +113,4 @@ module.exports = Zip; * ZipStream Module * @external ZipStream * @see {@link https://archiverjs.com/zip-stream/ZipStream.html} - */ \ No newline at end of file + */ diff --git a/test/archiver.js b/test/archiver.js index cb3814132..4f6a989c2 100644 --- a/test/archiver.js +++ b/test/archiver.js @@ -179,6 +179,7 @@ describe('archiver', function() { assert.property(entries, 'test/fixtures/directory/level0.txt'); assert.property(entries, 'test/fixtures/directory/subdir/'); assert.property(entries, 'test/fixtures/directory/subdir/level1.txt'); + assert.property(entries, 'test/fixtures/directory/subdir/level0link.txt'); assert.property(entries, 'test/fixtures/directory/subdir/subsub/'); assert.property(entries, 'test/fixtures/directory/subdir/subsub/level2.txt'); assert.propertyVal(entries['test/fixtures/directory/level0.txt'], 'date', '2013-01-03T14:26:38.000Z'); @@ -187,6 +188,7 @@ describe('archiver', function() { assert.property(entries, 'directory/level0.txt'); assert.property(entries, 'directory/subdir/'); assert.property(entries, 'directory/subdir/level1.txt'); + assert.property(entries, 'directory/subdir/level0link.txt'); assert.property(entries, 'directory/subdir/subsub/'); assert.property(entries, 'directory/subdir/subsub/level2.txt'); }); @@ -360,4 +362,4 @@ describe('archiver', function() { }); }); -}); \ No newline at end of file +}); diff --git a/test/fixtures/directory/subdir/level0link.txt b/test/fixtures/directory/subdir/level0link.txt new file mode 120000 index 000000000..b9f3a4723 --- /dev/null +++ b/test/fixtures/directory/subdir/level0link.txt @@ -0,0 +1 @@ +../level0.txt \ No newline at end of file diff --git a/test/plugins.js b/test/plugins.js index bfb74413a..86f3243d7 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -49,13 +49,14 @@ describe('plugins', function() { archive .append(testBuffer, { name: 'buffer.txt', date: testDate }) .append(fs.createReadStream('test/fixtures/test.txt'), { name: 'stream.txt', date: testDate }) - .append(null, { name: 'directory/', date: testDate }) + .append(null, { name: 'folder/', date: testDate }) + .directory('test/fixtures/directory', 'directory') .finalize(); }); it('should append multiple entries', function() { assert.isArray(actual); - assert.lengthOf(actual, 3); + assert.lengthOf(actual, 9); }); it('should append buffer', function() { @@ -74,12 +75,18 @@ describe('plugins', function() { assert.propertyVal(entries['stream.txt'].props, 'size', 19); }); - it('should append directory', function() { - assert.property(entries, 'directory/'); - assert.propertyVal(entries['directory/'].props, 'path', 'directory/'); - assert.propertyVal(entries['directory/'].props, 'type', '5'); - assert.propertyVal(entries['directory/'].props, 'mode', 493); - assert.propertyVal(entries['directory/'].props, 'size', 0); + it('should append folder', function() { + assert.property(entries, 'folder/'); + assert.propertyVal(entries['folder/'].props, 'path', 'folder/'); + assert.propertyVal(entries['folder/'].props, 'type', '5'); + assert.propertyVal(entries['folder/'].props, 'mode', 493); + assert.propertyVal(entries['folder/'].props, 'size', 0); + }); + + it('should append via directory', function() { + assert.property(entries, 'directory/subdir/level1.txt'); + assert.property(entries, 'directory/subdir/level0link.txt'); + assert.propertyVal(entries['directory/subdir/level0link.txt'].props, 'linkpath', '../level0.txt'); }); }); @@ -166,4 +173,4 @@ describe('plugins', function() { assert.equal('archive comment', zipComment); }); }); -}); \ No newline at end of file +});