-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
450 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
'use strict'; | ||
var os = require('os'); | ||
var path = require('path'); | ||
var process = require('child_process'); | ||
var events = require('events'); | ||
var util = require('util'); | ||
var spawn = require('win-spawn'); | ||
var Promise = require('promise'); | ||
|
||
// Create an Api class that extends the EventEmitter. | ||
function Api(name) { | ||
this.name = (name) ? name : '7z'; | ||
} | ||
util.inherits(Api, events.EventEmitter); | ||
|
||
function concatSwitches(switches) { | ||
var r = ''; | ||
var c = ''; | ||
for (var s in switches) { | ||
c = switches[s]; | ||
c = (c === true) ? '' : c; | ||
r += '-' + s + c; | ||
} | ||
} | ||
|
||
// Adds files to archive. | ||
Api.prototype.add = Promise.denodeify(function (archive, files, switches, cb) { | ||
|
||
// When no switches are speciied use the given function as the callback and | ||
// set switches as an empty object. | ||
if (typeof switches === 'function') { | ||
cb = switches; | ||
switches = {}; | ||
} | ||
archive = path.resolve(archive); | ||
|
||
|
||
}); | ||
|
||
|
||
// Test integrity of archive. | ||
Api.prototype.test = Promise.denodeify(function (archive, callback) { | ||
|
||
archive = path.resolve(archive); | ||
var cmd = '7z t ' + archive; | ||
process.exec(cmd, function (err, stdout) { | ||
if (err) return callback(err, null); | ||
// Parse each line of the stdout and build an array of files (and | ||
// directories) tested. The / is used in the result instead of the default | ||
// OS path separator. | ||
var r = []; | ||
stdout.split(os.EOL).forEach(function (_line) { | ||
if (_line.substr(0, 12) === 'Testing ') { | ||
r.push(_line.substr(12, _line.length).replace(path.sep, '/')); | ||
} | ||
}); | ||
return callback(null, r); | ||
}); | ||
|
||
}); | ||
|
||
|
||
// Extract with full paths. | ||
Api.prototype.extract = Promise.denodeify(function (archive, dest, callback) { | ||
|
||
archive = path.resolve(archive); | ||
dest = path.resolve(dest); | ||
var self = this; | ||
var err = null; | ||
var cmd = ('x ' + archive + ' -y -o' + dest).split(' '); | ||
var run = spawn('7z', cmd, { stdio: 'pipe' }); | ||
|
||
run.on('close', function (code) { | ||
if (err) return callback(err); | ||
return callback(null); | ||
}); | ||
|
||
run.stdout.on('data', function (data) { | ||
// When an stdout is emitted, parse it. If an error is detected in the body | ||
// of the stdout create an new error with the 7-Zip error message as the | ||
// error's message. Otherwise emit a `data` event with the processed files | ||
// and directories as an array. | ||
var files = []; | ||
var regex = new RegExp('Error:' + os.EOL + '(.*)', 'g'); | ||
var res = regex.exec(data.toString()); | ||
if (res) err = new Error(res[1]); | ||
data.toString().split(os.EOL).forEach(function (_line) { | ||
if (_line.substr(0, 12) === 'Extracting ') { | ||
files.push(_line.substr(12, _line.length).replace(path.sep, '/')); | ||
} | ||
}); | ||
self.emit('data', files); | ||
}); | ||
|
||
}); | ||
|
||
|
||
module.exports = Api; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
'use strict'; | ||
var Api = require('../index'); | ||
var expect = require('chai').expect; | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var rimraf = require('rimraf'); | ||
|
||
describe('The Api object', function () { | ||
|
||
after(function () { | ||
rimraf.sync('.tmp/test'); | ||
}); | ||
|
||
it('should respond to events methods', function () { | ||
var api = new Api(); | ||
expect(api).to.respondTo('emit'); | ||
expect(api).to.respondTo('on'); | ||
}); | ||
|
||
it('should have `7z` as default name', function () { | ||
var api = new Api(); | ||
expect(api.name).to.eql('7z'); | ||
}); | ||
|
||
it('should be nameable', function () { | ||
var api = new Api('testName'); | ||
expect(api.name).to.eql('testName'); | ||
}); | ||
|
||
}); | ||
|
||
describe('`add` function', function() { | ||
|
||
it('should get an error when 7z gets an error', function (done) { | ||
var api = new Api(); | ||
api.add('myArchive.7z', 'files', { i:'az', r: true }, function (s) { | ||
console.log(s); | ||
}); | ||
api.add('myArchive.7z', 'files', function (s) { | ||
console.log(s); | ||
}); | ||
done(); | ||
}); | ||
|
||
}); | ||
|
||
describe('`test` function', function(){ | ||
|
||
it('should get an error when 7z gets an error', function (done) { | ||
var api = new Api(); | ||
api.test('test/nothere.7z', function (err) { | ||
expect(err.message.substr(0, 14)).to.eql('Command failed'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should get a list of files and directories', function (done) { | ||
var api = new Api(); | ||
api.test('test/zip.7z', function (err, files) { | ||
expect(files.length).to.be.at.least(6); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should be compatible with Promise', function (done) { | ||
var api = new Api(); | ||
api.test('test/zip.7z').then(function (files) { | ||
expect(files.length).to.be.at.least(6); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); | ||
|
||
describe('`extract` function', function() { | ||
|
||
it('should get an error when 7z gets an error', function (done) { | ||
var api = new Api(); | ||
api.extract('test/nothere.7z', '.tmp/test', function (err) { | ||
expect(err.message).to.contain('archive'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should get a list of files and directories', function (done) { | ||
var api = new Api(); | ||
api.on('data', function (files) { | ||
expect(files).to.be.an('array'); | ||
done(); | ||
}); | ||
api.extract('test/zip.7z', '.tmp/test', function () {}); | ||
}); | ||
|
||
it('should get no error on success', function (done) { | ||
var api = new Api(); | ||
api.extract('test/zip.7z', '.tmp/test', function (err) { | ||
var file = path.resolve('.tmp/test/zip/file1.txt'); | ||
expect(fs.existsSync(file)).to.eql(true); | ||
expect(err).to.eql(null); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should be compatible with Promise', function (done) { | ||
var api = new Api(); | ||
api.extract('test/nothere.7z', '.tmp/test').then(null, function (err) { | ||
expect(err.message).to.contain('archive'); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
'use strict'; | ||
var path = require('path'); | ||
var Q = require('q'); | ||
var u = { | ||
run: require('../util/run') | ||
}; | ||
|
||
module.exports = function (archive, dest, options, cb) { | ||
return Q.Promise(function (resolve, reject, notify) { | ||
|
||
//TODO: parse options, -y always true? | ||
var opts = ''; | ||
var command = '7z x ' + archive + ' -o' + dest + ' ' + opts; | ||
u.run(command) | ||
|
||
// When a stdout is emitted, parse each line and search for a pattern. When | ||
// the pattern is found, extract the file (or directory) name from it and | ||
// pass it to an array. Finally returns this array. | ||
.progress(function (data) { | ||
var entries = []; | ||
data.split('\n').forEach(function (line) { | ||
if (line.substr(0, 12) === 'Extracting ') { | ||
entries.push(line.substr(12, line.length).replace(path.sep, '/')); | ||
} | ||
}); | ||
notify(entries); | ||
}) | ||
|
||
.then(function () { | ||
resolve(); | ||
}) | ||
|
||
.catch(function (err) { | ||
reject(err); | ||
}); | ||
|
||
}).nodeify(cb); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
'use strict'; | ||
|
||
module.exports = { | ||
extractFull: require('./extractFull') | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/*global describe, it, afterEach */ | ||
var expect = require('chai').expect; | ||
var fs = require('fs'); | ||
var rimraf = require('rimraf'); | ||
var extractFull = require('../../lib/extractFull'); | ||
|
||
describe('Module: `extractFull`', function () { | ||
|
||
afterEach(function () { rimraf.sync('.tmp/test'); }); | ||
|
||
it('should return an error on 7z error', function (done) { | ||
extractFull('test/nothere.7z', '.tmp/test') | ||
.catch(function (err) { | ||
expect(err).to.be.an.instanceof(Error); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return entries on progress', function (done) { | ||
extractFull('test/zip.7z', '.tmp/test') | ||
.progress(function (entries) { | ||
expect(entries.length).to.be.at.least(1); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should extract on the right path', function (done) { | ||
extractFull('test/zip.7z', '.tmp/test') | ||
.then(function () { | ||
expect(fs.existsSync('.tmp/test/zip')).to.be.eql(true); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
--recursive |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/*global describe, it */ | ||
var expect = require('chai').expect; | ||
var run = require('../../util/run'); | ||
|
||
describe('Util: `run`', function () { | ||
|
||
it('should return an error with invalid command type', function (done) { | ||
run(0).catch(function (err) { | ||
expect(err.message).to.eql('Command must be a string'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return an error on when 7z gets one', function (done) { | ||
run('7z ?').catch(function (err) { | ||
expect(err.message).to.eql('Incorrect command line'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should return an stdout on progress', function (done) { | ||
run('7z') | ||
.progress(function (data) { | ||
expect(data).to.be.a('string'); | ||
}) | ||
.then(function () { | ||
done(); | ||
}); | ||
}); | ||
|
||
it('should work as Node.js-style callback', function (done) { | ||
run(0, function (err) { | ||
expect(err.message).to.be.a('string'); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); |
Oops, something went wrong.