Skip to content

Commit

Permalink
Fixed master merge
Browse files Browse the repository at this point in the history
  • Loading branch information
davglass committed Jun 13, 2012
2 parents 2055539 + c77db99 commit 5930d09
Show file tree
Hide file tree
Showing 21 changed files with 816 additions and 369 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/lib/hub/view/public/sockjs-*
/dep/
/doc/quick-start/index.mustache
/api/
Expand Down
189 changes: 105 additions & 84 deletions Jakefile.js
Original file line number Diff line number Diff line change
@@ -1,127 +1,148 @@
var fs = require('fs');
var execute = require('child_process').exec;
var ronn = require('ronn').Ronn;
var version = require('./lib/package').readPackageSync().version;
var rimraf = require('rimraf');
var walk = require('walk');

function exec(command, onComplete) {
execute(command, function (err, stdout, stderr) {
if (typeof(onComplete) !== "function" && stdout) {
console.log(stdout);
}
if (stderr) {
console.log(stderr);
/*global task, desc, fail, complete */

"use strict";

var fs = require("fs");
var child_process = require("child_process");

var Ronn = require("ronn").Ronn;
var rimraf = require("rimraf");
var walk = require("walk");

var version = require("./lib/package").readPackageSync().version;

function nuke(dir, completer) {
rimraf(dir, function (err) {
if (err) {
fail(err);
} else if ("function" === typeof completer) {
completer();
}
if (typeof(onComplete) === "function") {
onComplete(stdout);
});
}

function spawn(command, args, completer) {
child_process.spawn(command, args, {
stdio: "inherit",
customFds: [0, 1, 2]
}).on("exit", function (code) {
if (code !== 0) {
fail(command + " " + args.join(" ") +
" failed with " + code);
} else if ("function" === typeof completer) {
completer();
}
});
}

function getTestFiles(path) {
var jsFilter = new RegExp('.js$'),
jsTestFiles = fs.readdirSync(path).filter(function(elem, index, arr) {
function bin(name, args, completer) {
if (!args) {
args = [];
}
spawn("node", ["node_modules/.bin/" + name].concat(args), completer);
}

function getTestFiles() {
var path = "test",
jsFilter = new RegExp(".js$"),
jsTestFiles = fs.readdirSync(path).filter(function (elem, index, arr) {
return jsFilter.test(elem);
}).map(function (file) {
return "test/" + file;
});

return jsTestFiles;
}

function getJsFiles(path, cb) {
var files = [],
jsFilter = new RegExp('.js$');
walker = walk.walk(path, { followLInks: false });
jsFilter = new RegExp(".js$"),
walker = walk.walk(path, {
followLinks: false
});

walker.on('file', function(root, stat, next) {
walker.on("file", function (root, stat, next) {
if (jsFilter.test(stat.name)) {
files.push(root + '/' + stat.name);
files.push(root + "/" + stat.name);
}
next();
});

walker.on('end', function() {
walker.on("end", function () {
cb(files);
});
});
}

desc('Default: install all modules including devDependencies');
task('default', function () {
exec('npm install .');
});
desc("Default: install all modules including devDependencies");
task("default", ["install"]);

desc('Install all modules including devDependencies');
task('install', function () {
exec('npm install .');
desc("Install all modules including devDependencies");
task("install", function () {
spawn("npm", ["install"], complete);
}, {
async: true
});

desc('Run all of Yeti\'s unit tests');
task('test', function () {
// RegExp for JavaScript test files (used for Windows compatibility)
var index, jsTestFiles = getTestFiles('test');

for (index = 0; index < jsTestFiles.length; index++) {
exec('node node_modules/vows/bin/vows test/' + jsTestFiles[index],
{ customFds: [0,1,2] });
}
desc("Run all of Yeti's unit tests");
task("test", function () {
bin("vows", getTestFiles(), complete);
}, {
async: true
});

desc('Run all of Yeti\'s unit tests with the \'--spec\' flag');
task('spec', function () {
var index, jsTestFiles = getTestFiles('test');

for (index = 0; index < jsTestFiles.length; index++) {
exec('node node_modules/vows/bin/vows --spec test/' + jsTestFiles[index],
{ customFds: [0,1,2] });
}
desc("Run all of Yeti's unit tests with the '--spec' flag");
task("spec", function () {
bin("vows", ["--spec"].concat(getTestFiles()), complete);
}, {
async: true
});

desc('Build coverage tools and write out test coverage HTML page');
task('coverage', function () {
// nodejs-coverage may not work well on Windows so just use the original
exec('scripts/coverage.sh');
desc("Build coverage tools and write out test coverage HTML page");
task("coverage", function () {
spawn("bash", ["scripts/coverage.sh"], complete);
}, {
async: true
});

desc('Build HTML documentation');
task('html', function() {
fs.readFile('README.md', function (err, data) {
desc("Build HTML documentation");
task("html", function () {
fs.readFile("README.md", "utf8", function (err, data) {
var md, html;
// Remove Travis info
var markdown = data.toString().substr(124);
var html = new ronn(markdown).html();
var moddedHtml = html.replace(/<[\/]*html>/, '')
.replace('<pre>', '<pre class="code"');
fs.writeFileSync('doc/quick-start/index.mustache', moddedHtml);
exec('node node_modules/selleck/bin/selleck');
md = data.split("\n").slice(4).join("\n"),
html = new Ronn(md).html()
.replace(/<[\/]*html>/, "")
.replace("<pre>", '<pre class="code"');
fs.writeFileSync("doc/quick-start/index.mustache", html);
bin("selleck", [], complete);
});
}, {
async: true
});

desc('Build API documentation');
task('html-api', ['html'], function () {
exec('node node_modules/yuidocjs/lib/cli.js --project-version ' + version);
desc("Build API documentation");
task("html-api", ["html"], function () {
bin("yuidoc", ["--project-version", version], complete);
}, {
async: true
});

desc('Run JSLint on all files, or a specific given file');
task('lint', function () {
getJsFiles('./lib', function (files) {
exec('node node_modules/jshint/bin/hint ' + files.join(' '));
desc("Run JSLint on all files, or a specific given file");
task("lint", function () {
getJsFiles("./lib", function (files) {
bin("jshint", files, complete);
});
}, {
async: true
});

desc('Remove build documentation');
task('clean', function () {
rimraf('build_docs', function (err) {
if (err) {
console.log(err);
}
});
desc("Remove build documentation");
task("clean", function () {
nuke("build_docs");
});

desc('Remove development tools');
task('maintainer-clean', function () {
exec('npm rm webkit-devtools-agent');
rimraf('tools', function (err) {
if (err) {
console.log(err);
}
});
desc("Remove development tools");
task("maintainer-clean", function () {
spawn("rpm", ["rm", "webkit-devtools-agent"]);
nuke("tools");
});
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ html-api:

lint:
# Problem? Type `make install` first.
find lib test -name "*.js" -print0 | xargs -0 ./go lint
find lib test -name "*.js" \! -name "*min.js" -print0 | xargs -0 ./go lint
.PHONY: lint

clean:
Expand Down
1 change: 0 additions & 1 deletion doc/api/index.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ You may include Yeti scripts like this:
</p>

```
<script src="/yeti/socket.io/socket.io.js"></script>
<!-- If you provided a route to hub.attachServer, replace "/yeti" with that route: -->
<script src="/yeti/public/inject.js"></script>
```
Expand Down
50 changes: 6 additions & 44 deletions lib/blizzard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ var http = require("http");
var util = require("util");
var urlParser = require("url");

var hijack = require("../hijack");

var BlizzardSession = require("./session");

var EventEmitter2 = require("eventemitter2").EventEmitter2;
Expand Down Expand Up @@ -177,50 +179,10 @@ Blizzard.prototype.connect = function (url, cb) {
* @param {HTTPServer} httpServer
*/
Blizzard.prototype.listen = function (httpServer) {
var self = this,
listeners = httpServer.listeners("upgrade");

httpServer.removeAllListeners("upgrade");

httpServer.on("upgrade", function (req, socket, head) {

// First, attempt to upgrade to Blizzard.
var success = self.serverUpgrade(req, socket, head),
written = false,
originalWrite;

if (!success) {
// Blizzard was not the protocol asked for.

// If data is written to the socket,
// the connection was upgraded.
originalWrite = socket.write;
socket.write = function (string, encoding, fd) {
written = true;
originalWrite.call(this, string, encoding, fd);
};

// Try other upgrade listeners, e.g. Socket.io.
listeners.forEach(function (fn) {
fn(req, socket, head);
});

// Restore original write.
socket.write = originalWrite;

// No listener wrote to the socket.
// Destroy the connection.
if (!written && socket.writable) {
socket.write([
"HTTP/1.1 400 Bad Request",
"X-Reason: Protocol not supported",
"Connection: close",
"Content-Length: 0",
"", ""
].join("\r\n"));
socket.end();
}
}
var self = this;

hijack(httpServer, "upgrade", function (req, socket, head) {
return self.serverUpgrade(req, socket, head);
});

return this;
Expand Down
2 changes: 1 addition & 1 deletion lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ function runBatch(options) {

error("Waiting for agents to connect at " + url + ".");

rl.question("When ready, press Enter to begin testing.", function () {
rl.question("When ready, press Enter to begin testing.\n", function () {
rl.close();
process.stdin.destroy();
submitBatch(client, files);
Expand Down
1 change: 1 addition & 0 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ ClientBatch.prototype.onAck = function (err, id) {
self.batchSession.incomingBridge(self, "complete");
self.batchSession.incomingBridge(self, "agentComplete");
self.batchSession.incomingBridge(self, "agentResult");
self.batchSession.incomingBridge(self, "agentBeat");
self.batchSession.incomingBridge(self, "agentError");
self.batchSession.incomingBridge(self, "agentScriptError");

Expand Down
58 changes: 58 additions & 0 deletions lib/hijack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use strict";

/**
* @module hijack
*/

/**
* Attach the provided function as the first
* listener of the given EventEmitter event.
*
* All listeners of the event will be removed
* and replaced with a listener that will run
* the provided function first, followed by
* the original listeners if the function
* returned false.
*
* Works with Node.js v0.7+ where the array
* returned by `ee.listeners()` is a reference.
*
* @method hijack
* @param {EventEmitter} ee Emitter.
* @param {String} event Event name.
* @param {Function} firstFn Function to run first.
*/
module.exports = function hijack(ee, event, firstFn) {
var listeners = ee.listeners(event),
i = 0,
length = listeners.length,
originalListeners = [];

// Note: listeners is a reference in Node v0.7.
// Calling `removeAllListeners` no longer destroys
// the listener array, which causes it survive
// as a reference. See joyent/node commits:
// - 78dc13fbf97e2e3003e6f3baacdd5ff60e8de3f7
// - 928ea564d16da47e615ddac627e0b4d4a40d8196
//
// Make a copy first.
for (; i < length; i += 1) {
originalListeners[i] = listeners[i];
}

ee.removeAllListeners(event);

ee.on(event, function () {
var args = Array.prototype.slice.call(arguments),
stack = [firstFn].concat(originalListeners),
handled;

handled = firstFn.apply(ee, args);

if (!handled) {
originalListeners.forEach(function (fn) {
fn.apply(ee, args);
});
}
});
};
Loading

0 comments on commit 5930d09

Please sign in to comment.