catch revs by comment

This commit is contained in:
oleg 2015-06-23 22:18:13 +03:00
parent 96a7509280
commit 5428347bfe
8 changed files with 233 additions and 86 deletions

View File

@ -4,6 +4,9 @@ scm:
repository: ./test/repos/mercurial
rev: default
# catchRev:
# comment: !!js/regexp //
notify:
on:
# - done

View File

@ -48,4 +48,39 @@ Executor.prototype.run = function(params, callback) {
},
callback
);
};
};
// Returns target rev and filtered changes according to `catchRev`
Executor.prototype._getTarget = function(rev, changes) {
var result = {rev: rev, changes: changes},
catchRev = this.project.catchRev;
if (catchRev) {
// reverse before search
changes = changes.reverse();
var index;
var comment = catchRev.comment;
if (comment) {
index = _(changes).findIndex(function(change) {
if (_(comment).isRegExp()) {
return comment.test(change.comment);
} else {
return comment === change.comment;
}
});
}
if (index !== -1) {
result.rev = changes[index].id;
result.changes = changes.slice(0, index);
result.changes.reverse();
}
// reverse back before return
changes = changes.reverse();
}
return result;
};

View File

@ -53,18 +53,29 @@ Executor.prototype._getSources = function(params, callback) {
}
},
function() {
if (!isFirstRun) {
scm.update(params.rev, this.slot());
} else {
this.pass(null);
}
},
function() {
scm.getCurrent(this.slot());
scm.getChanges(oldRev && oldRev.id, params.rev, this.slot());
},
function(err, rev, changes) {
this.pass({rev: rev, changes: changes});
function(err, changes) {
var target = self._getTarget(params.rev, changes);
this.pass(target.changes);
scm.update(target.rev, this.slot());
},
function(err, changes) {
scm.getCurrent(this.slot());
this.pass(changes);
scm.getRev(params.rev, this.slot());
},
function(err, rev, changes, latestRev) {
// add current rev to the lates changes (if it's not yet there)
if (changes.length && changes[0].id !== rev.id) {
changes.unshift(rev);
}
this.pass({
rev: rev,
changes: changes,
isLatest: changes.length && changes[0].id === latestRev.id
});
},
callback
);

View File

@ -40,6 +40,15 @@ Scm.prototype.getCurrent = function(callback) {
Scm.prototype.getChanges = function(rev1, rev2, callback) {
};
/**
* Returns info (in changes format) about target revision
*/
Scm.prototype.getRev = function(rev, callback) {
this.getChanges(rev, rev, function(err, changes) {
callback(err, !err && changes[0]);
});
};
/**
* Updates to revision
*/

View File

@ -1,7 +1,9 @@
'use strict';
var ParentScm = require('./base').Scm,
inherits = require('util').inherits;
inherits = require('util').inherits,
Steppy = require('twostep').Steppy,
_ = require('underscore');
function Scm(params) {
ParentScm.call(this, params);
@ -29,13 +31,16 @@ Scm.prototype._parseRev = function(str) {
Scm.prototype.clone = function(dst, rev, callback) {
var self = this;
this.run({
cmd: 'hg',
args: ['clone', '--rev', rev, this.repository, dst]
}, function(err) {
self.cwd = dst;
callback(err);
});
Steppy(
function() {
self.run({
cmd: 'hg',
args: ['clone', '--rev', rev, self.repository, dst]
}, this.slot());
self.cwd = dst;
},
callback
);
};
Scm.prototype.pull = function(rev, callback) {
@ -44,23 +49,41 @@ Scm.prototype.pull = function(rev, callback) {
Scm.prototype.getCurrent = function(callback) {
var self = this;
self.run({cmd: 'hg', args: [
'parent', '--template', self._revTemplate
]}, function(err, stdout) {
callback(err, !err && self._parseRev(stdout));
});
Steppy(
function() {
self.run({cmd: 'hg', args: [
'parent', '--template', self._revTemplate
]}, this.slot());
},
function(err, stdout) {
this.pass(self._parseRev(stdout));
},
callback
);
};
Scm.prototype.getChanges = function(rev1, rev2, callback) {
var self = this;
self.run({cmd: 'hg', args: [
'log', '--rev', rev2 + ':' + rev1,
'--template', self._revTemplate + '\n'
]}, function(err, stdout) {
callback(err, !err && stdout.split('\n').slice(0, -2).map(function(str) {
return self._parseRev(str);
}));
});
Steppy(
function() {
self.run({cmd: 'hg', args: [
'log', '--rev', rev2 + ':' + rev1,
'--template', self._revTemplate + '\n'
]}, this.slot());
},
function(err, stdout) {
// always skip last line - it's empty and also skip first
// rev if we see range
var rows = stdout.split('\n').slice(0, rev1 === rev2 ? -1 : -2);
var changes = _(rows).map(function(str) {
return self._parseRev(str);
});
this.pass(changes);
},
callback
);
};
Scm.prototype.update = function(rev, callback) {

View File

@ -4,33 +4,34 @@ var expect = require('expect.js'),
path = require('path'),
fs = require('fs'),
createExecutor = require('../lib/executor').createExecutor,
SpawnCommand = require('../lib/command/spawn').Command;
SpawnCommand = require('../lib/command/spawn').Command,
_ = require('underscore'),
mercurialRevs = _(require('./helpers').mercurialRevs).clone();
['local'].forEach(function(type) {
describe(type + ' executor', function() {
var workspacePath = path.join(__dirname, 'workspace');
function rmdir(dir, callback) {
var removeDir = function (dir, callback) {
new SpawnCommand().run({cmd: 'rm', args: ['-R', dir]}, callback);
}
it('remove test workspace dir if it exists', function(done) {
var clearWorkspace = function (done) {
if (fs.exists(workspacePath, function(isExists) {
if (isExists) {
rmdir(workspacePath, done);
removeDir(workspacePath, done);
} else {
done();
}
}));
});
}
var executor;
it('instance should be created without errors', function() {
executor = createExecutor({
var makeExecutorParams = function(params) {
params = params || {};
return {
type: type,
project: {
project: _({
dir: __dirname,
name: 'test project',
scm: {
@ -42,22 +43,81 @@ var expect = require('expect.js'),
{type: 'shell', cmd: 'echo 1'},
{type: 'shell', cmd: 'echo 2'}
]
}
}).extend(params.project)
};
};
var executor, scmData;
describe('with scm rev default and without catch rev', function() {
before(clearWorkspace);
it('instance should be created without errors', function() {
executor = createExecutor(makeExecutorParams());
});
it('should run without errors', function(done) {
executor.run({}, function(err) {
expect(err).not.ok();
done();
});
executor.on('scmData', function(data) {
scmData = data;
});
});
it('scm data should be rev: 2, changes: [0-2], latest', function() {
expect(scmData).eql({
rev: mercurialRevs[2],
changes: mercurialRevs.slice().reverse(),
isLatest: true
});
});
});
it('should run', function() {
executor.run({}, function(err) {
expect(err).not.ok();
});
});
describe('with scm rev default and catch rev "first revision"', function() {
before(clearWorkspace);
it('should emit scm data', function(done) {
executor.on('scmData', function(scmData) {
expect(scmData).have.keys('rev', 'changes');
done();
it('instance should be created without errors', function() {
executor = createExecutor(makeExecutorParams({
project: {
catchRev: {comment: 'first revision'}
}
}));
});
it('should run without errors', function(done) {
executor.run({}, function(err) {
expect(err).not.ok();
done();
});
executor.on('scmData', function(data) {
scmData = data;
});
});
it('scm data should be rev: 1, changes: [0, 1], not latest',
function() {
expect(scmData).eql({
rev: mercurialRevs[1],
changes: mercurialRevs.slice(0, 2).reverse(),
isLatest: false
});
});
it('should run it again without errors', function(done) {
executor.run({}, done);
});
it('scm data should be rev: 2, changes: [2], latest', function() {
expect(scmData).eql({
rev: mercurialRevs[2],
changes: mercurialRevs.slice(2, 3).reverse(),
isLatest: true
});
});
});
});
});

20
test/helpers.js Normal file
View File

@ -0,0 +1,20 @@
'use strict';
// revisions for the test mercurial repo
exports.mercurialRevs = [{
id: 'da2762e71e87',
author: 'kotbegemot',
date: new Date('Fri May 09 22:36:41 2014 +0400').getTime(),
comment: 'zero revision'
}, {
id: '98e3a18d8193',
author: 'kotbegemot',
date: new Date('Fri May 09 22:37:19 2014 +0400').getTime(),
comment: 'first revision'
}, {
id: '9d7d08445f4c',
author: 'kotbegemot',
date: new Date('Sat May 10 03:18:20 2014 +0400').getTime(),
comment: 'third revision'
}];

View File

@ -4,7 +4,8 @@ var expect = require('expect.js'),
path = require('path'),
fs = require('fs'),
createScm = require('../lib/scm').createScm,
SpawnCommand = require('../lib/command/spawn').Command;
SpawnCommand = require('../lib/command/spawn').Command,
mercurialRevs = require('./helpers').mercurialRevs;
['mercurial'].forEach(function(type) {
@ -36,9 +37,9 @@ var expect = require('expect.js'),
});
});
var currentRev = data.rev0.id;
var currentRev = data[0].id;
it('clone rev0 to dst without errors', function(done) {
scm.clone(repositoryPath, data.rev0.id, done);
scm.clone(repositoryPath, data[0].id, done);
});
it('expect scm.cwd equals to dst', function() {
@ -48,13 +49,21 @@ var expect = require('expect.js'),
it('expect current revision equals to rev0', function(done) {
scm.getCurrent(function(err, rev) {
if (err) return done(err);
expect(rev).eql(data.rev0);
expect(rev).eql(data[0]);
done();
});
});
it('expect rev0 info is good', function(done) {
scm.getRev(mercurialRevs[0].id, function(err, rev) {
if (err) return done(err);
expect(rev).eql(mercurialRevs[0]);
done();
});
});
it('expect none changes from rev0 to default revision', function(done) {
scm.getChanges(data.rev0.id, scm.defaultRev, function(err, changes) {
scm.getChanges(data[0].id, scm.defaultRev, function(err, changes) {
if (err) return done(err);
expect(changes).ok();
expect(changes).length(0);
@ -68,11 +77,11 @@ var expect = require('expect.js'),
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) {
scm.getChanges(data[0].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]);
expect(changes).eql([data[2], data[1]]);
done();
});
});
@ -85,7 +94,7 @@ var expect = require('expect.js'),
it('expect current revision equals to rev2', function(done) {
scm.getCurrent(function(err, rev) {
if (err) return done(err);
expect(rev).eql(data.rev2);
expect(rev).eql(data[2]);
done();
});
});
@ -96,11 +105,11 @@ var expect = require('expect.js'),
it('expect repository log from rev0 to default revision equals to ' +
'rev1 and rev2 (in reverse order)', function(done) {
scm.getChanges(data.rev0.id, scm.defaultRev, function(err, changes) {
scm.getChanges(data[0].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]);
expect(changes).eql([data[2], data[1]]);
done();
});
});
@ -113,28 +122,5 @@ var expect = require('expect.js'),
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'
}
};
if (type === 'mercurial') return mercurialRevs;
}