From b1f91ebca4f00b3e266e4d35e2439a709a9a5c9b Mon Sep 17 00:00:00 2001 From: oleg Date: Sat, 10 May 2014 14:19:47 +0400 Subject: [PATCH] introduce command classes --- lib/command/base.js | 23 +++++++++++++++++++++++ lib/command/spawn.js | 37 +++++++++++++++++++++++++++++++++++++ lib/scm/base.js | 43 ++++++++++--------------------------------- lib/scm/index.js | 6 +++++- lib/scm/mercurial.js | 37 ++++++++++++++++++++----------------- test/scm.js | 11 ++++++++--- 6 files changed, 103 insertions(+), 54 deletions(-) create mode 100644 lib/command/base.js create mode 100644 lib/command/spawn.js diff --git a/lib/command/base.js b/lib/command/base.js new file mode 100644 index 0000000..68ddfee --- /dev/null +++ b/lib/command/base.js @@ -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; +}; diff --git a/lib/command/spawn.js b/lib/command/spawn.js new file mode 100644 index 0000000..38c79fc --- /dev/null +++ b/lib/command/spawn.js @@ -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; +}; diff --git a/lib/scm/base.js b/lib/scm/base.js index 055659d..d25c76a 100644 --- a/lib/scm/base.js +++ b/lib/scm/base.js @@ -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) { }; diff --git a/lib/scm/index.js b/lib/scm/index.js index dc3046f..5672f10 100644 --- a/lib/scm/index.js +++ b/lib/scm/index.js @@ -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); }; diff --git a/lib/scm/mercurial.js b/lib/scm/mercurial.js index d603add..ca469b7 100644 --- a/lib/scm/mercurial.js +++ b/lib/scm/mercurial.js @@ -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); }; diff --git a/test/scm.js b/test/scm.js index 374051d..d9bdbb0 100644 --- a/test/scm.js +++ b/test/scm.js @@ -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); }); }); });