introduce command classes

This commit is contained in:
oleg 2014-05-10 14:19:47 +04:00
parent da9d4a5c25
commit b1f91ebca4
6 changed files with 103 additions and 54 deletions

23
lib/command/base.js Normal file
View File

@ -0,0 +1,23 @@
'use strict';
var EventEmitter = require('events').EventEmitter,
inherits = require('util').inherits;
function Command(params) {
params = params || {};
this.isEmit = params.isEmit;
}
exports.BaseCommand = Command;
inherits(Command, EventEmitter);
Command.prototype.enableEmitter = function() {
this.isEmit = true;
return this;
};
Command.prototype.disableEmitter = function() {
this.isEmit = false;
return this;
};

37
lib/command/spawn.js Normal file
View File

@ -0,0 +1,37 @@
'use strict';
var spawn = require('child_process').spawn,
ParentCommand = require('./base').BaseCommand,
inherits = require('util').inherits;
function Command(params) {
params = params || {};
ParentCommand.call(this, params);
this.cwd = params.cwd;
}
exports.SpawnCommand = Command;
inherits(Command, ParentCommand);
Command.prototype.exec = function(params, callback) {
var self = this,
stdout = '';
var cmd = spawn(params.cmd, params.args, {cwd: this.cwd});
cmd.stdout.on('data', function(data) {
if (self.isEmit) self.emit('stdout', data);
stdout += data;
});
cmd.stderr.on('data', function(data) {
callback(new Error('Scm outputs to stderr: ' + data));
cmd.kill();
});
cmd.on('exit', function(code) {
var err = null;
if (code !== 0) err = new Error(
'Scm command exits with non-zero code: ' + code
);
callback(err, stdout);
});
return cmd;
};

View File

@ -1,70 +1,47 @@
'use strict';
var spawn = require('child_process').spawn,
EventEmitter = require('events').EventEmitter,
var ParentCommand = require('../command/spawn').SpawnCommand,
inherits = require('util').inherits;
function BaseScm(params) {
function Scm(params) {
ParentCommand.call(this, params);
this.repository = params.repository;
this.cwd = params.cwd;
if (!this.repository && !this.cwd) throw new Error(
'`repository` or `cwd` must be set'
);
}
module.exports = BaseScm;
exports.BaseScm = Scm;
inherits(BaseScm, EventEmitter);
BaseScm.prototype._exec = function(command, args, callback) {
var self = this,
stdout = '';
var cmd = spawn(command, args, {cwd: this.cwd});
cmd.stdout.on('data', function(data) {
if (self.isEmit) self.emit('stdout', data);
stdout += data;
});
cmd.stderr.on('data', function(data) {
callback(new Error('Scm outputs to stderr: ' + data));
cmd.kill();
});
cmd.on('exit', function(code) {
var err = null;
if (code !== 0) err = new Error(
'Scm command exits with non-zero code: ' + code
);
callback(err, stdout);
});
return cmd;
};
inherits(Scm, ParentCommand);
/**
* Clone repository to the `dst` update to `rev` and set `this.cwd` to `dst`
*/
BaseScm.prototype.clone = function(dst, rev, callback) {
Scm.prototype.clone = function(dst, rev, callback) {
};
/**
* Pull changes from remote repository without update
*/
BaseScm.prototype.pull = function(rev, callback) {
Scm.prototype.pull = function(rev, callback) {
};
/**
* Returns string id of current revision
*/
BaseScm.prototype.getId = function(callback) {
Scm.prototype.getId = function(callback) {
};
/**
* Returns array of changes between revisions
*/
BaseScm.prototype.getChanges = function(rev1, rev2, callback) {
Scm.prototype.getChanges = function(rev1, rev2, callback) {
};
/**
* Updates to revision
*/
BaseScm.prototype.update = function(rev, callback) {
Scm.prototype.update = function(rev, callback) {
};

View File

@ -2,7 +2,11 @@
var path = require('path');
var typesHash = {
'mercurial': require('./mercurial').MercurialScm
};
exports.createScm = function(config) {
var Constructor = require(path.join(__dirname, config.type));
var Constructor = typesHash[config.type];
return new Constructor(config);
};

View File

@ -1,41 +1,44 @@
'use strict';
var BaseScm = require('./base'),
var ParentScm = require('./base').BaseScm,
inherits = require('util').inherits;
function MercurialScm(params) {
BaseScm.call(this, params);
function Scm(params) {
ParentScm.call(this, params);
}
module.exports = MercurialScm;
exports.MercurialScm = Scm;
inherits(MercurialScm, BaseScm);
inherits(Scm, ParentScm);
MercurialScm.prototype.defaultRev = 'default';
Scm.prototype.defaultRev = 'default';
MercurialScm.prototype.clone = function(dst, rev, callback) {
Scm.prototype.clone = function(dst, rev, callback) {
var self = this;
this._exec('hg', ['clone', '--rev', rev, this.repository, dst], function(err) {
this.exec({
cmd: 'hg',
args: ['clone', '--rev', rev, this.repository, dst]
}, function(err) {
self.cwd = dst;
callback(err);
});
};
MercurialScm.prototype.pull = function(rev, callback) {
this._exec('hg', ['pull', '--rev', rev], callback);
Scm.prototype.pull = function(rev, callback) {
this.exec({cmd: 'hg', args: ['pull', '--rev', rev]}, callback);
};
MercurialScm.prototype.getId = function(callback) {
this._exec('hg', ['id', '--id'], function(err, stdout) {
Scm.prototype.getId = function(callback) {
this.exec({cmd: 'hg', args: ['id', '--id']}, function(err, stdout) {
callback(err, !err && stdout.replace('\n', ''));
});
};
MercurialScm.prototype.getChanges = function(rev1, rev2, callback) {
this._exec('hg', [
Scm.prototype.getChanges = function(rev1, rev2, callback) {
this.exec({cmd: 'hg', args: [
'log', '--rev', rev2 + ':' + rev1,
'--template', '{node|short};;;{author};;;{date|date};;;{desc}\n'
], function(err, stdout) {
]}, function(err, stdout) {
callback(err, !err && stdout.split('\n').slice(0, -2).map(function(str) {
var parts = str.split(';;;');
return {
@ -48,6 +51,6 @@ MercurialScm.prototype.getChanges = function(rev1, rev2, callback) {
});
};
MercurialScm.prototype.update = function(rev, callback) {
this._exec('hg', ['up', rev], callback);
Scm.prototype.update = function(rev, callback) {
this.exec({cmd: 'hg', args: ['up', rev]}, callback);
};

View File

@ -3,7 +3,8 @@
var expect = require('expect.js'),
path = require('path'),
fs = require('fs'),
createScm = require('../lib/scm').createScm;
createScm = require('../lib/scm').createScm,
SpawnCommand = require('../lib/command/spawn').SpawnCommand;
['mercurial'].forEach(function(type) {
@ -12,10 +13,14 @@ var expect = require('expect.js'),
repositoryName = 'test-repository',
repositoryPath = path.join(path.join(__dirname, 'repos'), repositoryName);
function rmdir(dir, callback) {
new SpawnCommand().exec({cmd: 'rm', args: ['-R', dir]}, callback);
}
it('remove test repository dir if it exists', function(done) {
if (fs.exists(repositoryPath, function(isExists) {
if (isExists) {
scm._exec('rm', ['-R', repositoryPath], done);
rmdir(repositoryPath, done);
} else {
done();
}
@ -101,7 +106,7 @@ var expect = require('expect.js'),
});
it('remove test repository dir', function(done) {
scm._exec('rm', ['-R', repositoryPath], done);
rmdir(repositoryPath, done);
});
});
});