Skip to content

Commit

Permalink
Add switches utility
Browse files Browse the repository at this point in the history
  • Loading branch information
q2s2t committed Aug 25, 2014
1 parent cc356f1 commit 170bc30
Show file tree
Hide file tree
Showing 11 changed files with 450 additions and 2 deletions.
98 changes: 98 additions & 0 deletions .old/index.js
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;
112 changes: 112 additions & 0 deletions .old/test.js
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();
});
});

});
38 changes: 38 additions & 0 deletions lib/extractFull.js
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);
};
5 changes: 5 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

module.exports = {
extractFull: require('./extractFull')
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "7z",
"version": "0.0.1",
"description": "A Node.js wrapper for 7-Zip",
"main": "index.js",
"main": "lib/index.js",
"scripts": {
"test": "mocha",
"coverage": "istanbul cover node_modules/mocha/bin/_mocha --dir .tmp/coverage",
Expand All @@ -25,7 +25,7 @@
},
"homepage": "http://quentinrossetti.github.io/node-7zip",
"dependencies": {
"promise": "^5.0.0",
"q": "^2.0.2",
"win-spawn": "^2.0.0"
},
"devDependencies": {
Expand Down
35 changes: 35 additions & 0 deletions test/lib/extractFull.js
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();
});
});

});
1 change: 1 addition & 0 deletions test/mocha.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--recursive
38 changes: 38 additions & 0 deletions test/util/run.js
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();
});
});

});
Loading

0 comments on commit 170bc30

Please sign in to comment.