mirror of
https://gitlab.silvrtree.co.uk/martind2000/nci.git
synced 2025-02-14 07:39:17 +00:00
add base scm class, mercurial class with tests
This commit is contained in:
parent
a51adc69d4
commit
dc00488eea
72
lib/scm/base.js
Normal file
72
lib/scm/base.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var spawn = require('child_process').spawn,
|
||||||
|
EventEmitter = require('events').EventEmitter,
|
||||||
|
inherits = require('util').inherits;
|
||||||
|
|
||||||
|
function BaseScm(config) {
|
||||||
|
var self = this;
|
||||||
|
self.config = config;
|
||||||
|
['src'].forEach(function(key) {
|
||||||
|
if (key in self.config === false) throw new Error(key + ' is not set');
|
||||||
|
self[key] = self.config[key];
|
||||||
|
});
|
||||||
|
self.cwd = config.cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BaseScm;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone repository to the `dst` update to `rev` and set `this.cwd` to `dst`
|
||||||
|
*/
|
||||||
|
BaseScm.prototype.clone = function(dst, rev, callback) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull changes from remote repository without update
|
||||||
|
*/
|
||||||
|
BaseScm.prototype.pull = function(rev, callback) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns string id of current revision
|
||||||
|
*/
|
||||||
|
BaseScm.prototype.getId = function(callback) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns array of changes between revisions
|
||||||
|
*/
|
||||||
|
BaseScm.prototype.getChanges = function(rev1, rev2, callback) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates to revision
|
||||||
|
*/
|
||||||
|
BaseScm.prototype.update = function(rev, callback) {
|
||||||
|
};
|
||||||
|
|
8
lib/scm/index.js
Normal file
8
lib/scm/index.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
exports.createScm = function(config) {
|
||||||
|
var Constructor = require(path.join(__dirname, config.type));
|
||||||
|
return new Constructor(config);
|
||||||
|
};
|
53
lib/scm/mercurial.js
Normal file
53
lib/scm/mercurial.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var BaseScm = require('./base'),
|
||||||
|
inherits = require('util').inherits;
|
||||||
|
|
||||||
|
function MercurialScm(config) {
|
||||||
|
BaseScm.call(this, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = MercurialScm;
|
||||||
|
|
||||||
|
inherits(MercurialScm, BaseScm);
|
||||||
|
|
||||||
|
MercurialScm.prototype.defaultRev = 'default';
|
||||||
|
|
||||||
|
MercurialScm.prototype.clone = function(dst, rev, callback) {
|
||||||
|
var self = this;
|
||||||
|
this._exec('hg', ['clone', '--rev', rev, this.src, dst], function(err) {
|
||||||
|
self.cwd = dst;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MercurialScm.prototype.pull = function(rev, callback) {
|
||||||
|
this._exec('hg', ['pull', '--rev', rev], callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
MercurialScm.prototype.getId = function(callback) {
|
||||||
|
this._exec('hg', ['id', '--id'], function(err, stdout) {
|
||||||
|
callback(err, !err && stdout.replace('\n', ''));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MercurialScm.prototype.getChanges = function(rev1, rev2, callback) {
|
||||||
|
this._exec('hg', [
|
||||||
|
'log', '--rev', rev2 + ':' + rev1,
|
||||||
|
'--template', '{node|short};;;{author};;;{date|date};;;{desc}\n'
|
||||||
|
], function(err, stdout) {
|
||||||
|
callback(err, !err && stdout.split('\n').slice(0, -2).map(function(str) {
|
||||||
|
var parts = str.split(';;;');
|
||||||
|
return {
|
||||||
|
id: parts[0],
|
||||||
|
author: parts[1],
|
||||||
|
date: new Date(parts[2]).getTime(),
|
||||||
|
comment: parts[3]
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
MercurialScm.prototype.update = function(rev, callback) {
|
||||||
|
this._exec('hg', ['up', rev], callback);
|
||||||
|
};
|
35
package.json
Normal file
35
package.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "nci",
|
||||||
|
"version": "0.1.0-alpha",
|
||||||
|
"description": "Continuous integration server written in node.js",
|
||||||
|
"bin": {
|
||||||
|
"nci": "bin/nci"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --bail --reporter=spec test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/okv/nci.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"continuous",
|
||||||
|
"integration",
|
||||||
|
"server",
|
||||||
|
"ci",
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"author": "Oleg Korobenko <oleg.korobenko@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/okv/nci/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/okv/nci",
|
||||||
|
"dependencies": {
|
||||||
|
"twostep": "0.4.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"expect.js": "0.3.1",
|
||||||
|
"mocha": "1.18.2"
|
||||||
|
}
|
||||||
|
}
|
BIN
test/repos/.hg/00changelog.i
Normal file
BIN
test/repos/.hg/00changelog.i
Normal file
Binary file not shown.
1
test/repos/.hg/branch
Normal file
1
test/repos/.hg/branch
Normal file
@ -0,0 +1 @@
|
|||||||
|
default
|
2
test/repos/.hg/cache/branchheads-served
vendored
Normal file
2
test/repos/.hg/cache/branchheads-served
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
98e3a18d8193d36caf143e9b57f5123bfd5878c9 1
|
||||||
|
98e3a18d8193d36caf143e9b57f5123bfd5878c9 default
|
2
test/repos/.hg/cache/tags
vendored
Normal file
2
test/repos/.hg/cache/tags
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
1 98e3a18d8193d36caf143e9b57f5123bfd5878c9
|
||||||
|
|
BIN
test/repos/.hg/dirstate
Normal file
BIN
test/repos/.hg/dirstate
Normal file
Binary file not shown.
4
test/repos/.hg/requires
Normal file
4
test/repos/.hg/requires
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
dotencode
|
||||||
|
fncache
|
||||||
|
revlogv1
|
||||||
|
store
|
BIN
test/repos/.hg/store/00changelog.i
Normal file
BIN
test/repos/.hg/store/00changelog.i
Normal file
Binary file not shown.
BIN
test/repos/.hg/store/00manifest.i
Normal file
BIN
test/repos/.hg/store/00manifest.i
Normal file
Binary file not shown.
BIN
test/repos/.hg/store/data/rev0.txt.i
Normal file
BIN
test/repos/.hg/store/data/rev0.txt.i
Normal file
Binary file not shown.
BIN
test/repos/.hg/store/data/rev1.txt.i
Normal file
BIN
test/repos/.hg/store/data/rev1.txt.i
Normal file
Binary file not shown.
2
test/repos/.hg/store/fncache
Normal file
2
test/repos/.hg/store/fncache
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
data/rev0.txt.i
|
||||||
|
data/rev1.txt.i
|
0
test/repos/.hg/store/phaseroots
Normal file
0
test/repos/.hg/store/phaseroots
Normal file
BIN
test/repos/.hg/store/undo
Normal file
BIN
test/repos/.hg/store/undo
Normal file
Binary file not shown.
0
test/repos/.hg/store/undo.phaseroots
Normal file
0
test/repos/.hg/store/undo.phaseroots
Normal file
0
test/repos/.hg/undo.bookmarks
Normal file
0
test/repos/.hg/undo.bookmarks
Normal file
1
test/repos/.hg/undo.branch
Normal file
1
test/repos/.hg/undo.branch
Normal file
@ -0,0 +1 @@
|
|||||||
|
default
|
3
test/repos/.hg/undo.desc
Normal file
3
test/repos/.hg/undo.desc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
0
|
||||||
|
pull
|
||||||
|
file:///mnt/data/home/oleg/work/repository/git-hub/nci/test/repos/mercurial
|
0
test/repos/.hg/undo.dirstate
Normal file
0
test/repos/.hg/undo.dirstate
Normal file
BIN
test/repos/mercurial/.hg/00changelog.i
Normal file
BIN
test/repos/mercurial/.hg/00changelog.i
Normal file
Binary file not shown.
2
test/repos/mercurial/.hg/cache/branchheads-served
vendored
Normal file
2
test/repos/mercurial/.hg/cache/branchheads-served
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
9d7d08445f4ce095c22a98a902a391973cf07f37 2
|
||||||
|
9d7d08445f4ce095c22a98a902a391973cf07f37 default
|
2
test/repos/mercurial/.hg/cache/tags
vendored
Normal file
2
test/repos/mercurial/.hg/cache/tags
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
2 9d7d08445f4ce095c22a98a902a391973cf07f37
|
||||||
|
|
BIN
test/repos/mercurial/.hg/dirstate
Normal file
BIN
test/repos/mercurial/.hg/dirstate
Normal file
Binary file not shown.
1
test/repos/mercurial/.hg/last-message.txt
Normal file
1
test/repos/mercurial/.hg/last-message.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
third revision
|
4
test/repos/mercurial/.hg/requires
Normal file
4
test/repos/mercurial/.hg/requires
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
dotencode
|
||||||
|
fncache
|
||||||
|
revlogv1
|
||||||
|
store
|
BIN
test/repos/mercurial/.hg/store/00changelog.i
Normal file
BIN
test/repos/mercurial/.hg/store/00changelog.i
Normal file
Binary file not shown.
BIN
test/repos/mercurial/.hg/store/00manifest.i
Normal file
BIN
test/repos/mercurial/.hg/store/00manifest.i
Normal file
Binary file not shown.
BIN
test/repos/mercurial/.hg/store/data/rev0.txt.i
Normal file
BIN
test/repos/mercurial/.hg/store/data/rev0.txt.i
Normal file
Binary file not shown.
BIN
test/repos/mercurial/.hg/store/data/rev1.txt.i
Normal file
BIN
test/repos/mercurial/.hg/store/data/rev1.txt.i
Normal file
Binary file not shown.
BIN
test/repos/mercurial/.hg/store/data/rev2.txt.i
Normal file
BIN
test/repos/mercurial/.hg/store/data/rev2.txt.i
Normal file
Binary file not shown.
3
test/repos/mercurial/.hg/store/fncache
Normal file
3
test/repos/mercurial/.hg/store/fncache
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
data/rev0.txt.i
|
||||||
|
data/rev1.txt.i
|
||||||
|
data/rev2.txt.i
|
1
test/repos/mercurial/.hg/store/phaseroots
Normal file
1
test/repos/mercurial/.hg/store/phaseroots
Normal file
@ -0,0 +1 @@
|
|||||||
|
1 da2762e71e87935198a25b0fceab0a364ad2e6d7
|
BIN
test/repos/mercurial/.hg/store/undo
Normal file
BIN
test/repos/mercurial/.hg/store/undo
Normal file
Binary file not shown.
1
test/repos/mercurial/.hg/store/undo.phaseroots
Normal file
1
test/repos/mercurial/.hg/store/undo.phaseroots
Normal file
@ -0,0 +1 @@
|
|||||||
|
1 da2762e71e87935198a25b0fceab0a364ad2e6d7
|
0
test/repos/mercurial/.hg/undo.bookmarks
Normal file
0
test/repos/mercurial/.hg/undo.bookmarks
Normal file
1
test/repos/mercurial/.hg/undo.branch
Normal file
1
test/repos/mercurial/.hg/undo.branch
Normal file
@ -0,0 +1 @@
|
|||||||
|
default
|
2
test/repos/mercurial/.hg/undo.desc
Normal file
2
test/repos/mercurial/.hg/undo.desc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
2
|
||||||
|
commit
|
BIN
test/repos/mercurial/.hg/undo.dirstate
Normal file
BIN
test/repos/mercurial/.hg/undo.dirstate
Normal file
Binary file not shown.
0
test/repos/mercurial/rev0.txt
Normal file
0
test/repos/mercurial/rev0.txt
Normal file
0
test/repos/mercurial/rev1.txt
Normal file
0
test/repos/mercurial/rev1.txt
Normal file
0
test/repos/mercurial/rev2.txt
Normal file
0
test/repos/mercurial/rev2.txt
Normal file
0
test/repos/rev0.txt
Normal file
0
test/repos/rev0.txt
Normal file
0
test/repos/rev1.txt
Normal file
0
test/repos/rev1.txt
Normal file
116
test/scm.js
Normal file
116
test/scm.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var expect = require('expect.js'),
|
||||||
|
path = require('path'),
|
||||||
|
fs = require('fs'),
|
||||||
|
createScm = require('../lib/scm').createScm;
|
||||||
|
|
||||||
|
|
||||||
|
['mercurial'].forEach(function(type) {
|
||||||
|
describe(type, function() {
|
||||||
|
var data = getTestData(type),
|
||||||
|
repositoryName = 'test-repository',
|
||||||
|
repositoryPath = path.join(path.join(__dirname, 'repos'), repositoryName);
|
||||||
|
|
||||||
|
it('remove test repository dir if it exists', function(done) {
|
||||||
|
if (fs.exists(repositoryPath, function(isExists) {
|
||||||
|
if (isExists) {
|
||||||
|
scm._exec('rm', ['-R', repositoryPath], done);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
var scm = createScm({
|
||||||
|
type: type,
|
||||||
|
src: path.join(__dirname, 'repos', type)
|
||||||
|
});
|
||||||
|
|
||||||
|
var currentRev = data.rev0.id;
|
||||||
|
it('clone rev0 to dst without errors', function(done) {
|
||||||
|
scm.clone(repositoryPath, data.rev0.id, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('expect scm.cwd equals to dst', function() {
|
||||||
|
expect(scm.cwd).equal(repositoryPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('expect current id equals to rev0', function(done) {
|
||||||
|
scm.getId(function(err, id) {
|
||||||
|
if (err) return done(err);
|
||||||
|
expect(id).equal(data.rev0.id);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('expect none changes from rev0 to default revision', function(done) {
|
||||||
|
scm.getChanges(data.rev0.id, scm.defaultRev, function(err, changes) {
|
||||||
|
if (err) return done(err);
|
||||||
|
expect(changes).ok();
|
||||||
|
expect(changes).length(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pull to default revision without errors', function(done) {
|
||||||
|
scm.pull(scm.defaultRev, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('now (after pull) expect rev1 and rev2 as new changes (in reverse ' +
|
||||||
|
'order) from rev0 to default revision', function(done) {
|
||||||
|
scm.getChanges(data.rev0.id, scm.defaultRev, function(err, changes) {
|
||||||
|
if (err) return done(err);
|
||||||
|
expect(changes).ok();
|
||||||
|
expect(changes).length(2);
|
||||||
|
expect(changes).eql([data.rev2, data.rev1]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('update to default revision (should update to rev2) without error',
|
||||||
|
function(done) {
|
||||||
|
scm.update(scm.defaultRev, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('expect current revision equals to rev2', function(done) {
|
||||||
|
scm.getId(function(err, id) {
|
||||||
|
if (err) return done(err);
|
||||||
|
expect(id).equal(data.rev2.id);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('remove test repository dir', function(done) {
|
||||||
|
scm._exec('rm', ['-R', repositoryPath], done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function getTestData(type) {
|
||||||
|
if (type === 'mercurial') return getMercurialData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMercurialData() {
|
||||||
|
return {
|
||||||
|
rev0: {
|
||||||
|
id: 'da2762e71e87',
|
||||||
|
author: 'kotbegemot',
|
||||||
|
date: new Date('Fri May 09 22:36:41 2014 +0400').getTime(),
|
||||||
|
comment: 'zero revision'
|
||||||
|
},
|
||||||
|
rev1: {
|
||||||
|
id: '98e3a18d8193',
|
||||||
|
author: 'kotbegemot',
|
||||||
|
date: new Date('Fri May 09 22:37:19 2014 +0400').getTime(),
|
||||||
|
comment: 'first revision'
|
||||||
|
},
|
||||||
|
rev2: {
|
||||||
|
id: '9d7d08445f4c',
|
||||||
|
author: 'kotbegemot',
|
||||||
|
date: new Date('Sat May 10 03:18:20 2014 +0400').getTime(),
|
||||||
|
comment: 'third revision'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user