Permalink
Browse files

emit multiple events if commits and tags are pushed

  • Loading branch information...
1 parent 9647d90 commit 14b8e0ba06f0a70f3ede7ecf2535bb3f991ba761 @juliangruber juliangruber committed Oct 14, 2012
Showing with 52 additions and 40 deletions.
  1. +30 −28 lib/service.js
  2. +22 −12 test/repos.js
View
@@ -12,8 +12,8 @@ module.exports = function (opts, req, res) {
};
var headerRE = {
- 'receive-pack' : /^([0-9a-fA-F]+) ([0-9a-fA-F]+) refs\/(heads|tags)\/([^\s\0]+)/,
- 'upload-pack' : /^\S+ ([0-9a-fA-F]+)/
+ 'receive-pack' : '([0-9a-fA-F]+) ([0-9a-fA-F]+) refs\/(heads|tags)\/(.*?)( |00|\u0000)',
+ 'upload-pack' : '7bwant ([0-9a-fA-F]+)'
@distracteddev

distracteddev Nov 14, 2012

Contributor

Are we sure the upload-pack regex is correct? It seems whenever I call a git fetch, everything is called up to the point where it checks the regex but the regex never passes and I get a HTTP timeout.

Specifically, this is a string that is not captured by the above regex (for upload-pack): "006fwant \b77949aa72d2713b1cb690032cd017980945f842"

Ignore the '' before the hash, that is just there to stop github from auto-linking the sha.

Also, I am guessing you changed the above "/^\S+ ([0-9a-fA-F]+)/" regex because it wasn't working after you changed the regex's from literals to strings. That is because you are instantiating the regex using the RegExp() method, which requires double escaping.

After switching to:

'^\S+ ([0-9a-fA-F]+)'

all is working :)

@juliangruber

juliangruber Nov 14, 2012

Contributor

ah, didn't know that

@themightychris

themightychris Sep 14, 2016

@juliangruber @distracteddev I've been doing some work with git-http-backend and ran into this receive-pack regex causing two seperate problems:

  • it doesn't match when pushing refs that aren't tags or branches
  • it cuts off the ref name when any branch/tag/ref contains the string 00 due to the non-greedy .*? stopping as soon as it matches 00 as a possible next sequence

I made a commit (substack/git-http-backend@720ae78) to git-http-backend adjusting this regex so I could push arbitrary refs and branch names that might contain 00, but I left the 00 in ( |00|\u0000) because I couldn't explain it being there. I can't find/imagine any case where a ref name could be immediately followed by a 00 that wouldn't be part of the ref name

Based on the (relatively limited) git traffic I've seen, it seems like a good pattern would be: (refs\/((heads|tags)\/)?[^\s\u0000]+)[\s\u0000] -- have either of you seen cases where that wouldn't work?

};
function Service (opts, req, res) {
@@ -36,35 +36,37 @@ function Service (opts, req, res) {
buffered.push(buf);
data += buf;
- var m = data.match(headerRE[self.service]);
- if (!m) return;
+ var ops = data.match(new RegExp(headerRE[self.service], 'gi'));
+ if (!ops) return;
data = undefined;
- self.removeListener('data', ondata);
-
- if (self.service === 'receive-pack') {
- self.last = m[1];
- self.commit = m[2];
+
+ ops.forEach(function(op) {
+ var m = op.match(new RegExp(headerRE[self.service]));
+ if (self.service === 'receive-pack') {
+ self.last = m[1];
+ self.commit = m[2];
- if (m[3] == 'heads') {
- var type = 'branch';
- self.evName = 'push';
- } else {
- var type = 'version';
- self.evName = 'tag';
- }
+ if (m[3] == 'heads') {
+ var type = 'branch';
+ self.evName = 'push';
+ } else {
+ var type = 'version';
+ self.evName = 'tag';
+ }
- var headers = {
- last: self.last,
- commit : self.commit
- };
- headers[type] = self[type] = m[4];
- self.emit('header', headers);
- }
- else if (self.service === 'upload-pack') {
- self.commit = m[1];
- self.evName = 'fetch';
- self.emit('header', { commit : self.commit });
- }
+ var headers = {
+ last: self.last,
+ commit : self.commit
+ };
+ headers[type] = self[type] = m[4];
+ self.emit('header', headers);
+ }
+ else if (self.service === 'upload-pack') {
+ self.commit = m[1];
+ self.evName = 'fetch';
+ self.emit('header', { commit : self.commit });
+ }
+ });
});
self.once('accept', function () {
View
@@ -12,7 +12,7 @@ var http = require('http');
var seq = require('seq');
test('create, push to, and clone a repo', function (t) {
- t.plan(13);
+ t.plan(17);
var repoDir = '/tmp/' + Math.floor(Math.random() * (1<<30)).toString(16);
var srcDir = '/tmp/' + Math.floor(Math.random() * (1<<30)).toString(16);
@@ -46,6 +46,22 @@ test('create, push to, and clone a repo', function (t) {
})
.seq_(function (next) {
var ps = spawn('git', [ 'commit', '-am', 'a!!' ]);
+ ps.on('exit', this.ok);
+ ps.stdout.pipe(process.stdout, { end : false });
+ })
+ .seq(function () {
+ var ps = spawn('git', ['tag', '0.0.1']);
+ ps.stderr.pipe(process.stderr, { end : false });
+ ps.on('exit', this.ok);
+ })
+ .seq(function () {
+ fs.writeFile(srcDir + '/a.txt', 'efgh', this);
+ })
+ .seq(function () {
+ spawn('git', [ 'add', 'a.txt' ]).on('exit', this.ok)
+ })
+ .seq_(function (next) {
+ var ps = spawn('git', [ 'commit', '-am', 'a!!' ]);
ps.on('exit', function () {
exec('git log | head -n1', function (err, stdout) {
lastCommit = stdout.split(/\s+/)[1];
@@ -55,20 +71,13 @@ test('create, push to, and clone a repo', function (t) {
ps.stdout.pipe(process.stdout, { end : false });
})
.seq(function () {
- var ps = spawn('git', ['tag', '0.0.1']);
- ps.stderr.pipe(process.stderr, { end : false });
- ps.on('exit', this.ok);
- })
- .seq(function () {
- var ps = spawn('git', [
- 'push', 'http://localhost:' + port + '/doom', 'master'
- ]);
+ var ps = spawn('git', ['tag', '0.0.2']);
ps.stderr.pipe(process.stderr, { end : false });
ps.on('exit', this.ok);
})
.seq(function () {
var ps = spawn('git', [
- 'push', '--tags', 'http://localhost:' + port + '/doom'
+ 'push', '--tags', 'http://localhost:' + port + '/doom', 'master'
]);
ps.stderr.pipe(process.stderr, { end : false });
ps.on('exit', this.ok);
@@ -103,15 +112,16 @@ test('create, push to, and clone a repo', function (t) {
push.accept();
});
+ var firstTag = true;
repos.on('tag', function (tag) {
t.equal(tag.repo, 'doom', 'repo name');
- t.equal(tag.commit, lastCommit, 'commit ok');
- t.equal(tag.version, '0.0.1', 'tag received');
+ t.equal(tag.version, '0.0.' + (firstTag? 1 : 2), 'tag received');
t.equal(tag.headers.host, 'localhost:' + port, 'http host');
t.equal(tag.method, 'POST', 'is a post');
t.equal(tag.url, '/doom/git-receive-pack', 'receive pack');
tag.accept();
+ firstTag = false;
});
});

0 comments on commit 14b8e0b

Please sign in to comment.