<commit_before>var express = require('express');
var fs = require('fs');
//var url = require('url');
//var querystring = require('querystring');
var util = require('util');
var nconf = require('nconf');
var childp = require('child_process');

var testsMod = require('./testsMod');
var TestDesc = testsMod.TestDesc;

nconf.argv().env().file({file: __dirname+'/config.json'});

nconf.defaults({
    "webServer":{"port": 3000},
    "appz":{
    	"max2010": "",
    	"max2011": "",
		"max2012": "C:/Program Files/Autodesk/3ds Max 2012/3dsmax.exe"
	}
});

var server_port = nconf.get('webServer:port');

var appz = nconf.get('appz');

var app = express.createServer();

app.configure('development', function(){
   // have everything in the public directory available to requesters as static data
   // this means that one can request by name anything in the public directory
   // such as images, css, etc...
   //app.use(express.static(__dirname + '/public'));
   app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
   app.use(express.bodyParser());
});

app.register('.html', require('ejs'));
app.set('view engine', 'ejs');
app.set("view options", { layout: false })

// app.get('/scripts/main.js', function(req, res){
//  fs.readFile( "plan.txt", 'utf8', function( err, mainData ) {
//        res.send(mainData );
//        });
// });

app.get('/404', function(req, res) {
  	res.send('NOT FOUND '+req.url);
});

app.listen(server_port);
console.log( "listening on port: "+server_port);

var getTestFullPath = function(path){
	return [__dirname, '/Tests', path].join('');
};

var testPath = [__dirname, "/Tests"].join('');

var testList = [];

var readTestDir = function(path, list){

	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			readTestDir(filePath, list);
		}
		else if(stats.isFile()){
			if(files[i] === 'testParams.json'){ //we have found a folder that contains a test

				//console.log("reading "+filePath)

				var data = fs.readFileSync(filePath);

				if(data.length > 0 ){
					//console.log("data: \n"+data);

	          		var aJSON = JSON.parse(data);

	          		var slen = aJSON.tasks.length;
	          		for(s=0; s<slen; s++){
	          			var script = aJSON.tasks[s];
	          			script.testpath = path;
	          			testList.push(script);
	          		}

				}
			}
		}
		else{
			console.log("Error: not a directory or file");
		}

	}

}

var cleanTestDir = function(path){

	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			cleanTestDir(filePath);
		}
		else if(stats.isFile()){
			if(	files[i].search(".ats") != -1 ||
				files[i].search("_Render") != -1 ||
				files[i].search(".tabc") != -1
				){ //we have found a folder that contains a test

				var res = fs.unlinkSync(filePath);
				//console.log("deleted " + path + " = " + res);
			}
		}
		else{
			console.log("Error: not a directory or file");
		}

	}

}

// - can call with the entire test folder as path to gather all test results
//OR
// - can call with a single test folder to gather results of a single test
var buildTestResults = function(path, testResults, atsname, errcode){
	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			buildTestResults(filePath, testResults);
		}
		else if(stats.isFile()){

			var bReturn = false;
			if(atsname !== undefined){
				bReturn = true;
			}

			atsname = atsname || ".ats";

			if( files[i].search(atsname) !== -1){ //we have found a folder that contains a test

				var testName = path.substring(__dirname.length + 6);

				var result = testResults[testName];
				if(result === undefined){
					result = {
						tasks:{}
					};
					testResults[testName] = result;
				}
				console.log('READING ats file: ' + filePath);

				var data = fs.readFileSync(filePath, 'ascii');

				if(data.length > 0){
					console.log(data + "\n");

					var tokens =  data.split('\n');

					if(tokens.length == 0){
						//result.tasks will be empty
						console.log("no data in ats file:" + filePath);
					}
					else{

						var namesToken = tokens[0].split("=");
						if(namesToken.length > 1 && namesToken[0] == "names"){

							var names = namesToken[1].split(",");

							var crashStr = "POSSIBLE CRASH";
							//console.log("cec: "+errcode);
							if(errcode == -1){
								crashStr = "CRASH";
							}

							for(var n=0; n<names.length; n++){
								result.tasks[names[n].trim()] = {status: crashStr};
							}

							//console.log("result: "+JSON.stringify(result)+"\n");

							for(var t=1; t<tokens.length-1; t++){
								var tokenTask = tokens[t].split(':');
								if(tokenTask.length == 2){

									var task = result.tasks[tokenTask[0]];
									if( task == undefined ){
										result.tasks[tokenTask[0].trim()] = {status: " --- UNREPORTED --- " + tokenTask[1].trim()};
									}
									else{
										task.status = tokenTask[1].trim();
									}

								}
							}

							//console.log("result: "+JSON.stringify(result)+"\n");
						}
						else{
							console.log("task names token not found: token[0] = "+tokens[0] + "   split = " + JSON.stringify(namesToken));
						}

					}
				}

				if(bReturn){
					return result;
				}
			}
		}
		else{
			console.log("Error: not a directory or file.");
		}

	}

}

var equalFiles = function(bpath, rpath){

	//try{

	var bfd = fs.readFileSync(bpath);
	var rfd = fs.readFileSync(rpath);

	// }
	// catch(err){

	 	console.log("bfd: "+bpath);
	 	console.log("rfd: "+rpath);
	// 	return false;
	// }

	if(bfd.length != rfd.length){
		console.log("lengths not equal");
		return false;
	}
	else{

		for(var i=0; i<bfd.length; i++){

			if(bfd[i] != rfd[i]){
				console.log("byte not equal");
				return false;
			}

		}

		return true;
	}

}

var TestManager = function(maxpath, includePath){

	this.maxpath = maxpath;
	this.includePath = includePath;
	this.tests = [];
	this.currTestIndex = 0;
	this.results = {};
};

var tmProto = TestManager.prototype;

tmProto.getAtsName = function(){
	var test = this.tests[this.currTestIndex];
	var name = test.scriptName.replace(".ms", ".ats");
	return test.app + "_" + name;
}

tmProto.getRenderedImagePath = function(){
	var test = this.tests[this.currTestIndex];
	return [test.testdir, "/", test.app, "_", test.obj, "_Render.jpg"].join('');
}

tmProto.getBaselineImagePath = function(){
	var test = this.tests[this.currTestIndex];
	return [test.testdir, "/", test.app, "_", test.obj, "_Baseline.jpg"].join('');
}

tmProto.testComplete = function(tDesc){

	var result = buildTestResults(tDesc.testdir, this.results, this.getAtsName(), tDesc.errcode);

	if(result !== undefined){

		var rt = result.tasks["render"];
		if(rt !== undefined){

			if( equalFiles(this.getBaselineImagePath(), this.getRenderedImagePath()) ){
				rt.status = 'PASS';
			}
			else{
				rt.status = "FAIL";
			}
		}
	}

	this.currTestIndex++;
	if(this.currTestIndex < this.tests.length){

		// var path = [this.tests[this.currTestIndex], getAtsName()].join('');

		// var res = fs.unlinkSync(path);

		// console.log("unlink: "+res);

		this.tests[this.currTestIndex].execute();
	}
	else{
		// console.log(JSON.stringify(this.results) + "\n");

		// var results = this.results;

		// for(var name in results){
		// 	if(!results.hasOwnProperty(name)) continue;

		// 	console.log("name: "+name);

		// 	var tasks = results[name].tasks;

		// 	for(var t in tasks){
		// 		console.log(t + ":" + tasks[t].status + "\n");
		// 	}

		// }

	}
}

var splitPathAndFile = function(pathfile){

	var index = pathfile.lastIndexOf('/');
	var indexb = pathfile.lastIndexOf('\\');
	if(indexb > index){
		index = indexb;
	}

	return{
	 	path: __dirname + pathfile.substring(0, index+1), // "/3DSMax/pathfiles/"
	 	file: pathfile.substring(index+1)
	}
}

tmProto.build = function(list){

	for(i=0; i<list.length; i++){

		var runEnv ={
			includePath: this.includePath,
			genBaseline: 'true'
		};
		for(var v in list[i].inputs){
			if(!list[i].inputs.hasOwnProperty(v)) continue;
			runEnv[v] = list[i].inputs[v];
		}

		var script = list[i].script;
		var scriptPath = '';
		var scriptName = '';
		if(script.indexOf('/') === -1 && scripts.indexOf('\\') === -1){//the script file is in the local directory
			scriptName = script;
		}
		else{
			var pf = splitPathAndFile(script);
			scriptPath = pf.path;
			scriptName = pf.file;
		}

		var params = {
			genBaseline: false,
			app: list[i].inputs.app,
			obj: list[i].inputs.obj,
			exepath: appz[list[i].inputs.app],
			testdir: list[i].testpath,
			arguments: '',//-silent',
			scriptPath: scriptPath,
			scriptName: scriptName,
			runEnvVars: runEnv,
			completionContext: this,
			completionCallback: this.testComplete
		}

		this.tests.push( new TestDesc(params) );
	}
}

tmProto.runAll = function(){
	if(this.currTestIndex < this.tests.length){
		this.tests[this.currTestIndex].execute();
	}
}

tmProto.print = function(){
	for(i=0; i<this.tests.length; i++){

		console.log(this.tests[i]);
	}
}

var testMan = new TestManager("", __dirname+"/3DSMax/includes");

app.get('/Results', function(req, res){

	//testMan.results

 	res.render(__dirname+'/testResults.html', {results: testMan.results});

});

cleanTestDir(testPath);
readTestDir(testPath);
testMan.build(testList);
testMan.runAll();

// var bpath = [__dirname, '/max2012_Sphere001_Baseline.jpg'].join('');
// var rpath = [__dirname, '/max2012_Sphere001_Render.jpg'].join('');

// if( equalFiles(bpath, rpath) ){

// 	console.log('files are equal');

// }
// else{

// 	console.log('files are not equal');
// }

<commit_msg>- deal with missing files<commit_after>var express = require('express');
var fs = require('fs');
//var url = require('url');
//var querystring = require('querystring');
var util = require('util');
var nconf = require('nconf');
var childp = require('child_process');

var testsMod = require('./testsMod');
var TestDesc = testsMod.TestDesc;

nconf.argv().env().file({file: __dirname+'/config.json'});

nconf.defaults({
    "webServer":{"port": 3000},
    "appz":{
    	"max2010": "",
    	"max2011": "",
		"max2012": "C:/Program Files/Autodesk/3ds Max 2012/3dsmax.exe"
	}
});

var server_port = nconf.get('webServer:port');

var appz = nconf.get('appz');

var app = express.createServer();

app.configure('development', function(){
   // have everything in the public directory available to requesters as static data
   // this means that one can request by name anything in the public directory
   // such as images, css, etc...
   //app.use(express.static(__dirname + '/public'));
   app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
   app.use(express.bodyParser());
});

app.register('.html', require('ejs'));
app.set('view engine', 'ejs');
app.set("view options", { layout: false })

// app.get('/scripts/main.js', function(req, res){
//  fs.readFile( "plan.txt", 'utf8', function( err, mainData ) {
//        res.send(mainData );
//        });
// });

app.get('/404', function(req, res) {
  	res.send('NOT FOUND '+req.url);
});

app.listen(server_port);
console.log( "listening on port: "+server_port);

var getTestFullPath = function(path){
	return [__dirname, '/Tests', path].join('');
};

var testPath = [__dirname, "/Tests"].join('');

var testList = [];

var readTestDir = function(path, list){

	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			readTestDir(filePath, list);
		}
		else if(stats.isFile()){
			if(files[i] === 'testParams.json'){ //we have found a folder that contains a test

				//console.log("reading "+filePath)

				var data = fs.readFileSync(filePath);

				if(data.length > 0 ){
					//console.log("data: \n"+data);

	          		var aJSON = JSON.parse(data);

	          		var slen = aJSON.tasks.length;
	          		for(s=0; s<slen; s++){
	          			var script = aJSON.tasks[s];
	          			script.testpath = path;
	          			testList.push(script);
	          		}

				}
			}
		}
		else{
			console.log("Error: not a directory or file");
		}

	}

}

var cleanTestDir = function(path){

	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			cleanTestDir(filePath);
		}
		else if(stats.isFile()){
			if(	files[i].search(".ats") != -1 ||
				files[i].search("_Render") != -1 ||
				files[i].search(".tabc") != -1
				){ //we have found a folder that contains a test

				var res = fs.unlinkSync(filePath);
				//console.log("deleted " + path + " = " + res);
			}
		}
		else{
			console.log("Error: not a directory or file");
		}

	}

}

// - can call with the entire test folder as path to gather all test results
//OR
// - can call with a single test folder to gather results of a single test
var buildTestResults = function(path, testResults, atsname, errcode){
	//console.log('Reading test dir: '+path);

	var files = fs.readdirSync(path);

	var len = files.length;
	//console.log("numFiles: "+len);
	for(var i=0; i<len; i++){

		var filePath = [path, '/', files[i]].join('');

		//console.log("reading file: "+filePath);

		var stats = fs.lstatSync(filePath);
		if(stats.isDirectory()){
			buildTestResults(filePath, testResults);
		}
		else if(stats.isFile()){

			var bReturn = false;
			if(atsname !== undefined){
				bReturn = true;
			}

			atsname = atsname || ".ats";

			if( files[i].search(atsname) !== -1){ //we have found a folder that contains a test

				var testName = path.substring(__dirname.length + 6);

				var result = testResults[testName];
				if(result === undefined){
					result = {
						tasks:{}
					};
					testResults[testName] = result;
				}
				console.log('READING ats file: ' + filePath);

				var data = fs.readFileSync(filePath, 'ascii');

				if(data.length > 0){
					console.log(data + "\n");

					var tokens =  data.split('\n');

					if(tokens.length == 0){
						//result.tasks will be empty
						console.log("no data in ats file:" + filePath);
					}
					else{

						var namesToken = tokens[0].split("=");
						if(namesToken.length > 1 && namesToken[0] == "names"){

							var names = namesToken[1].split(",");

							var crashStr = "POSSIBLE CRASH";
							//console.log("cec: "+errcode);
							if(errcode == -1){
								crashStr = "CRASH";
							}

							for(var n=0; n<names.length; n++){
								result.tasks[names[n].trim()] = {status: crashStr};
							}

							//console.log("result: "+JSON.stringify(result)+"\n");

							for(var t=1; t<tokens.length-1; t++){
								var tokenTask = tokens[t].split(':');
								if(tokenTask.length == 2){

									var task = result.tasks[tokenTask[0]];
									if( task == undefined ){
										result.tasks[tokenTask[0].trim()] = {status: " --- UNREPORTED --- " + tokenTask[1].trim()};
									}
									else{
										task.status = tokenTask[1].trim();
									}

								}
							}

							//console.log("result: "+JSON.stringify(result)+"\n");
						}
						else{
							console.log("task names token not found: token[0] = "+tokens[0] + "   split = " + JSON.stringify(namesToken));
						}

					}
				}

				if(bReturn){
					return result;
				}
			}
		}
		else{
			console.log("Error: not a directory or file.");
		}

	}

}

var equalFiles = function(bpath, rpath){

	try{

	var bfd = fs.readFileSync(bpath);
	var rfd = fs.readFileSync(rpath);

	}
	 catch(err){

	 	console.log("bfd: "+bpath);
	 	console.log("rfd: "+rpath);
	 	return false;
	}

	if(bfd.length != rfd.length){
		console.log("lengths not equal");
		return false;
	}
	else{

		for(var i=0; i<bfd.length; i++){

			if(bfd[i] != rfd[i]){
				console.log("byte not equal");
				return false;
			}

		}

		return true;
	}

}

var TestManager = function(maxpath, includePath){

	this.maxpath = maxpath;
	this.includePath = includePath;
	this.tests = [];
	this.currTestIndex = 0;
	this.results = {};
};

var tmProto = TestManager.prototype;

tmProto.getAtsName = function(){
	var test = this.tests[this.currTestIndex];
	var name = test.scriptName.replace(".ms", ".ats");
	return test.app + "_" + name;
}

tmProto.getRenderedImagePath = function(){
	var test = this.tests[this.currTestIndex];
	return [test.testdir, "/", test.app, "_", test.obj, "_Render.jpg"].join('');
}

tmProto.getBaselineImagePath = function(){
	var test = this.tests[this.currTestIndex];
	return [test.testdir, "/", test.app, "_", test.obj, "_Baseline.jpg"].join('');
}

tmProto.testComplete = function(tDesc){

	var result = buildTestResults(tDesc.testdir, this.results, this.getAtsName(), tDesc.errcode);

	if(result !== undefined){

		var rt = result.tasks["render"];
		if(rt !== undefined){

			if( equalFiles(this.getBaselineImagePath(), this.getRenderedImagePath()) ){
				rt.status = 'PASS';
			}
			else{
				rt.status = "FAIL";
			}
		}
	}

	this.currTestIndex++;
	if(this.currTestIndex < this.tests.length){

		// var path = [this.tests[this.currTestIndex], getAtsName()].join('');

		// var res = fs.unlinkSync(path);

		// console.log("unlink: "+res);

		this.tests[this.currTestIndex].execute();
	}
	else{
		// console.log(JSON.stringify(this.results) + "\n");

		// var results = this.results;

		// for(var name in results){
		// 	if(!results.hasOwnProperty(name)) continue;

		// 	console.log("name: "+name);

		// 	var tasks = results[name].tasks;

		// 	for(var t in tasks){
		// 		console.log(t + ":" + tasks[t].status + "\n");
		// 	}

		// }

	}
}

var splitPathAndFile = function(pathfile){

	var index = pathfile.lastIndexOf('/');
	var indexb = pathfile.lastIndexOf('\\');
	if(indexb > index){
		index = indexb;
	}

	return{
	 	path: __dirname + pathfile.substring(0, index+1), // "/3DSMax/pathfiles/"
	 	file: pathfile.substring(index+1)
	}
}

tmProto.build = function(list){

	for(i=0; i<list.length; i++){

		var runEnv ={
			includePath: this.includePath,
			genBaseline: 'true'
		};
		for(var v in list[i].inputs){
			if(!list[i].inputs.hasOwnProperty(v)) continue;
			runEnv[v] = list[i].inputs[v];
		}

		var script = list[i].script;
		var scriptPath = '';
		var scriptName = '';
		if(script.indexOf('/') === -1 && scripts.indexOf('\\') === -1){//the script file is in the local directory
			scriptName = script;
		}
		else{
			var pf = splitPathAndFile(script);
			scriptPath = pf.path;
			scriptName = pf.file;
		}

		var params = {
			genBaseline: false,
			app: list[i].inputs.app,
			obj: list[i].inputs.obj,
			exepath: appz[list[i].inputs.app],
			testdir: list[i].testpath,
			arguments: '',//-silent',
			scriptPath: scriptPath,
			scriptName: scriptName,
			runEnvVars: runEnv,
			completionContext: this,
			completionCallback: this.testComplete
		}

		this.tests.push( new TestDesc(params) );
	}
}

tmProto.runAll = function(){
	if(this.currTestIndex < this.tests.length){
		this.tests[this.currTestIndex].execute();
	}
}

tmProto.print = function(){
	for(i=0; i<this.tests.length; i++){

		console.log(this.tests[i]);
	}
}

var testMan = new TestManager("", __dirname+"/3DSMax/includes");

app.get('/Results', function(req, res){

	//testMan.results

 	res.render(__dirname+'/testResults.html', {results: testMan.results});

});

cleanTestDir(testPath);
readTestDir(testPath);
testMan.build(testList);
testMan.runAll();

// var bpath = [__dirname, '/max2012_Sphere001_Baseline.jpg'].join('');
// var rpath = [__dirname, '/max2012_Sphere001_Render.jpg'].join('');

// if( equalFiles(bpath, rpath) ){

// 	console.log('files are equal');

// }
// else{

// 	console.log('files are not equal');
// }

<|endoftext|>


<commit_before>if(!window.rb){
	window.rb = {};
}

if(!window.rb.$){
	window.rb.$ = window.jQuery || window.dom;
}

/*! focus-within polyfill */
(function(window, document){
	'use strict';

	var requestAnimationFrame = window.requestAnimationFrame || setTimeout;
	var running = false;
	var isClass = 'is-focus-within';
	var isClassSelector = '.' + isClass;

	function updateFocus(){
		var oldFocusParents, i, len;

		var parent = document.activeElement;
		var newFocusParents = [];

		while((parent = parent.parentNode) && parent.classList && !parent.classList.contains(isClass)){
			newFocusParents.push(parent);
		}

		if((oldFocusParents = parent.querySelectorAll && parent.querySelectorAll(isClassSelector))){
			for(i = 0, len = oldFocusParents.length; i < len; i++){
				oldFocusParents[i].classList.remove(isClass);
			}
		}
		for(i = 0, len = newFocusParents.length; i < len; i++){
			newFocusParents[i].classList.add(isClass);
		}

		running = false;
	}

	function update(){
		if(!running){
			running = true;
			requestAnimationFrame(updateFocus);
		}
	}

	document.addEventListener('focus', update, true);
	document.addEventListener('blur', update, true);

})(window, document);

/* keyboard-focus */
(function(window, document){
	'use strict';
	var keyboardBlocktimer;
	var isKeyboardBlocked = false;
	var root = document.documentElement;
	var dom = rb.$;

	var unblockKeyboardFocus = function(){
		isKeyboardBlocked = false;
	};
	var blockKeyboadFocus = function(){
		isKeyboardBlocked = true;
		clearTimeout(keyboardBlocktimer);
		keyboardBlocktimer = setTimeout(unblockKeyboardFocus, 66);
	};
	var removeKeyBoadFocus = function(){
		root.classList.remove('is-keyboardfocus');
		blockKeyboadFocus();
	};
	var setKeyboardFocus = function(){
		if(!isKeyboardBlocked){
			root.classList.add('is-keyboardfocus');
		}
	};
	var pointerEvents = (window.PointerEvent) ?
			['pointerdown', 'pointerup'] :
			['mousedown', 'mouseup', 'touchstart', 'touchend']
		;

	root.addEventListener('focus', setKeyboardFocus, true);

	pointerEvents.forEach(function(eventName){
		document.addEventListener(eventName, removeKeyBoadFocus, true);
	});

	document.addEventListener('click', blockKeyboadFocus, true);

	window.addEventListener('focus', blockKeyboadFocus);
	document.addEventListener('focus', blockKeyboadFocus);

	if(dom){
		dom(document).on('rbscriptfocus', blockKeyboadFocus);
	}

})(window, document);

/* rbSlideUp / rbSlideDown */
(function(){
	'use strict';
	var $ = rb.$;

	$.fn.rbSlideUp = function(options){
		if(!options){
			options = {};
		}

		this
			.stop()
			.css({overflow: 'hidden', display: 'block', visibility: 'visible'})
			.animate({height: 0}, {
				duration: options.duration || 400,
				easing: options.easing,
				always: function(){
					this.style.display = '';
					this.style.visibility = '';

					if(options.always){
						return options.always.apply(this, arguments);
					}
				},
			})
		;
	};

	$.fn.rbSlideDown = function(options){
		if(!options){
			options = {};
		}

		return this.each(function(){
			var endValue;
			var $panel = $(this);
			var startHeight = this.clientHeight + 'px';

			$panel.css({overflow: 'hidden', display: 'block', height: 'auto', visibility: 'visible'});

			endValue = this.clientHeight;

			$panel
				.css({height: startHeight})
				.animate({height: endValue}, {
					duration: options.duration || 400,
					easing: options.easing,
					always: function(){
						this.style.overflow = '';
						this.style.height = '';

						if(options.always){
							return options.always.apply(this, arguments);
						}
					},
				})
			;
		});
	};
})();

/* scrollIntoView */
(function(window){
	'use strict';
	var document = window.document;
	var $ = rb.$;

	var getScrollingElement = function(){
		var bH, dH, isCompat;
		var scrollingElement = document.scrollingElement;

		if(!scrollingElement){
			bH = document.body.scrollHeight;
			dH = document.documentElement.scrollHeight;
			isCompat = document.compatMode == 'BackCompat';
			scrollingElement = (dH <= bH || isCompat) ?
				document.body :
				document.documentElement;

			if(scrollingElement && (dH != bH || isCompat)){
				document.scrollingElement = scrollingElement;
			}
		}

		return scrollingElement;
	};

	$.fn.scrollIntoView = function(options){
		var bbox, distance, scrollingElement;
		var elem = this.get(0);

		if(elem){
			options = options || {};
			bbox = elem.getBoundingClientRect();
			distance = Math.max(Math.abs(bbox.top), Math.abs(bbox.left));
			scrollingElement = getScrollingElement();

			$(scrollingElement).animate(
				{
					scrollTop: scrollingElement.scrollTop + bbox.top + (options.offsetTop || 0),
					scrollLeft: scrollingElement.scrollLeft + bbox.left + (options.offsetLeft || 0),
				},
				{
					duration: options.duration || Math.min(1700, Math.max(99, distance * 0.6)),
					always: function(){
						if(options.focus){
							try {
								options.focus.focus();
							} catch(e){}
						}

						if(options.hash){
							location.hash = typeof options.hash == 'string' ?
								options.hash :
								elem.id || elem.name
							;
						}

						if(options.always){
							options.always.call(elem);
						}
					},
					easing: options.easing
				}
			);
		}
		return this;
	};
})(window);

/* throttle */
(function(){
	'use strict';
	var setImmediate = window.setImmediate || setTimeout;
	var requestAnimationFrame = requestAnimationFrame || setTimeout;

	rb.throttle = function(fn, options){
		var running, that, args;
		var lastTime = 0;
		var Date = window.Date;
		var run = function(){
			running = false;
			lastTime = Date.now();
			fn.apply(that, args);
		};
		var afterAF = function(){
			setImmediate(run);
		};
		var getAF = function(){
			requestAnimationFrame(afterAF);
		};

		if(!options){
			options = {};
		}

		if(!options.delay){
			options.delay = 200;
		}

		if(options.write){
			afterAF = run;
		}

		return function(){
			if(running){
				return;
			}
			var delay = options.delay - (Date.now() - lastTime);
			running =  true;

			if(delay < 6){
				delay = 6;
			}
			that = options.that || this;
			args = arguments;
			setTimeout(getAF, delay);
		};
	};
})();

/* resize */
(function(){
	'use strict';

	var iWidth, cHeight, installed;
	var docElem = document.documentElement;
	rb.resize = {
		fns: [],
		setup: function(){
			if(!installed){
				installed = true;
				setTimeout(function(){
					iWidth = innerWidth;
					cHeight = docElem.clientHeight;
				});
				window.addEventListener('resize', this.run);
			}
		},
		teardown: function(){
			if(installed && !this.fns.length){
				installed = false;
				window.removeEventListener('resize', this.run);
			}
		},
		on: function(fn, thisArg){
			this.fns.push(fn);
			this.setup();
		},
		off: function(fn){
			var index = this.fns.indexOf(fn);
			if(index != -1){
				this.fns.splice(index, 1);
				this.teardown();
			}
		},
	};

	rb.resize.run = rb.throttle(function(){
		var i, len;
		if(iWidth != innerWidth || cHeight != docElem.clientHeight){
			iWidth = innerWidth;
			cHeight = docElem.clientHeight;

			for(i = 0, len = this.fns.length; i < len; i++){
				this.fns[i]();
			}
		}
	}, {that:rb.resize});
})();

(function(){
	'use strict';
	var $ = rb.$;
	$.fn.elementResize = function(action, fn, options){
		if(!options){
			options = {};
		}
		var add = function(){
			var width, height;
			var iframe = $(document.createElement('iframe'))
					.addClass('js-element-resize')
					.css({
						position: 'absolute',
						top: '0px',
						left: '0px',
						bottom: '0px',
						right: '0px',
						visibility: 'visible',
						'min-width': '100%',
						'min-height': '100%',
						'z-index': '-1',
						border: 'none',
						background: 'transparent',
						opacity: 0
					})
					.attr({
						role: 'presentation',
						tabindex: '-1',
						frameborder: '0',
					})
					.get(0)
				;

			$(this).css({position: 'relative'});
			this.appendChild(iframe);

			setTimeout(function(){
				width = iframe.offsetWidth;
				height = iframe.offsetHeight;
				iframe.contentWindow.addEventListener('resize', function(){
					if( (!options.noWidth && width != iframe.offsetWidth)  || (!options.noHeight && height != iframe.offsetHeight)){
						width = iframe.offsetWidth;
						height = iframe.offsetHeight;
						fn();
					}
				});
			});
		};
		var remove = function(){
			$(this).find('iframe.js-element-resize').remove();
		};

		return this.each(action == 'remove' ? remove : add);
	};
})();

(function(){
	'use strict';
	rb.getCSSNumbers = function(element, styles, onlyPositive){
		var i, value;
		var $element = rb.$(element);
		var numbers = 0;
		if(!Array.isArray(styles)){
			styles = [styles];
		}

		for(i = 0; i < styles.length; i++){
			value = parseFloat($element.css(styles[i])) || 0;

			if(!onlyPositive || value > 0){
				numbers += value;
			}
		}

		return numbers;
	};
})();

(function(){
	'use strict';
	rb.rAf = function(fn, thisArg){
		var running, args;
		var run = function(){
			fn.apply(thisArg || window, args);
		};
		return function(){
			args = arguments;
			if(!running){
				running = true;
				window.requestAnimationFrame(run);
			}
		};
	};
})();

/* rbWidget */
(function(undefined){
	'use strict';
	var $ = rb.$;

	$.fn.rbWidget = function(name, args){
		var ret;

		this.each(function(){
			if(ret === undefined){
				ret = rb.life.getWidget(this, name, args);
			}
		});

		return ret === undefined ?
			this :
			ret
		;
	};

})();
<commit_msg>improvements<commit_after>if(!window.rb){
	window.rb = {};
}

if(!window.rb.$){
	window.rb.$ = window.jQuery || window.dom;
}

/*! focus-within polyfill */
(function(window, document){
	'use strict';

	var requestAnimationFrame = window.requestAnimationFrame || setTimeout;
	var running = false;
	var isClass = 'is-focus-within';
	var isClassSelector = '.' + isClass;

	function updateFocus(){
		var oldFocusParents, i, len;

		var parent = document.activeElement;
		var newFocusParents = [];

		while((parent = parent.parentNode) && parent.classList && !parent.classList.contains(isClass)){
			newFocusParents.push(parent);
		}

		if((oldFocusParents = parent.querySelectorAll && parent.querySelectorAll(isClassSelector))){
			for(i = 0, len = oldFocusParents.length; i < len; i++){
				oldFocusParents[i].classList.remove(isClass);
			}
		}
		for(i = 0, len = newFocusParents.length; i < len; i++){
			newFocusParents[i].classList.add(isClass);
		}

		running = false;
	}

	function update(){
		if(!running){
			running = true;
			requestAnimationFrame(updateFocus);
		}
	}

	document.addEventListener('focus', update, true);
	document.addEventListener('blur', update, true);

})(window, document);

/* keyboard-focus */
(function(window, document){
	'use strict';
	var keyboardBlocktimer;
	var isKeyboardBlocked = false;
	var root = document.documentElement;
	var dom = rb.$;

	var unblockKeyboardFocus = function(){
		isKeyboardBlocked = false;
	};
	var blockKeyboadFocus = function(){
		isKeyboardBlocked = true;
		clearTimeout(keyboardBlocktimer);
		keyboardBlocktimer = setTimeout(unblockKeyboardFocus, 66);
	};
	var removeKeyBoadFocus = function(){
		root.classList.remove('is-keyboardfocus');
		blockKeyboadFocus();
	};
	var setKeyboardFocus = function(){
		if(!isKeyboardBlocked){
			root.classList.add('is-keyboardfocus');
		}
	};
	var pointerEvents = (window.PointerEvent) ?
			['pointerdown', 'pointerup'] :
			['mousedown', 'mouseup', 'touchstart', 'touchend']
		;

	root.addEventListener('focus', setKeyboardFocus, true);

	pointerEvents.forEach(function(eventName){
		document.addEventListener(eventName, removeKeyBoadFocus, true);
	});

	document.addEventListener('click', blockKeyboadFocus, true);

	window.addEventListener('focus', blockKeyboadFocus);
	document.addEventListener('focus', blockKeyboadFocus);

	if(dom){
		dom(document).on('rbscriptfocus', blockKeyboadFocus);
	}

})(window, document);

/* rbSlideUp / rbSlideDown */
(function(){
	'use strict';
	var $ = rb.$;

	$.fn.rbSlideUp = function(options){
		if(!options){
			options = {};
		}

		this
			.stop()
			.css({overflow: 'hidden', display: 'block', visibility: 'visible'})
			.animate({height: 0}, {
				duration: options.duration || 400,
				easing: options.easing,
				always: function(){
					this.style.display = '';
					this.style.visibility = '';

					if(options.always){
						return options.always.apply(this, arguments);
					}
				},
			})
		;
	};

	$.fn.rbSlideDown = function(options){
		if(!options){
			options = {};
		}

		return this.each(function(){
			var endValue;
			var $panel = $(this);
			var startHeight = this.clientHeight + 'px';

			$panel.css({overflow: 'hidden', display: 'block', height: 'auto', visibility: 'visible'});

			endValue = this.clientHeight;

			$panel
				.css({height: startHeight})
				.animate({height: endValue}, {
					duration: options.duration || 400,
					easing: options.easing,
					always: function(){
						this.style.overflow = '';
						this.style.height = '';

						if(options.always){
							return options.always.apply(this, arguments);
						}
					},
				})
			;
		});
	};
})();

/* scrollIntoView */
(function(window){
	'use strict';
	var document = window.document;
	var $ = rb.$;

	var getScrollingElement = function(){
		var bH, dH, isCompat;
		var scrollingElement = document.scrollingElement;

		if(!scrollingElement){
			bH = document.body.scrollHeight;
			dH = document.documentElement.scrollHeight;
			isCompat = document.compatMode == 'BackCompat';
			scrollingElement = (dH <= bH || isCompat) ?
				document.body :
				document.documentElement;

			if(scrollingElement && (dH != bH || isCompat)){
				document.scrollingElement = scrollingElement;
			}
		}

		return scrollingElement;
	};

	$.fn.scrollIntoView = function(options){
		var bbox, distance, scrollingElement;
		var elem = this.get(0);

		if(elem){
			options = options || {};
			bbox = elem.getBoundingClientRect();
			distance = Math.max(Math.abs(bbox.top), Math.abs(bbox.left));
			scrollingElement = getScrollingElement();

			$(scrollingElement).animate(
				{
					scrollTop: scrollingElement.scrollTop + bbox.top + (options.offsetTop || 0),
					scrollLeft: scrollingElement.scrollLeft + bbox.left + (options.offsetLeft || 0),
				},
				{
					duration: options.duration || Math.min(1700, Math.max(99, distance * 0.6)),
					always: function(){
						if(options.focus){
							try {
								options.focus.focus();
							} catch(e){}
						}

						if(options.hash){
							location.hash = typeof options.hash == 'string' ?
								options.hash :
								elem.id || elem.name
							;
						}

						if(options.always){
							options.always.call(elem);
						}
					},
					easing: options.easing
				}
			);
		}
		return this;
	};
})(window);

/* throttle */
(function(){
	'use strict';
	var setImmediate = window.setImmediate || setTimeout;
	var requestAnimationFrame = requestAnimationFrame || setTimeout;

	rb.throttle = function(fn, options){
		var running, that, args;
		var lastTime = 0;
		var Date = window.Date;
		var run = function(){
			running = false;
			lastTime = Date.now();
			fn.apply(that, args);
		};
		var afterAF = function(){
			setImmediate(run);
		};
		var getAF = function(){
			requestAnimationFrame(afterAF);
		};

		if(!options){
			options = {};
		}

		if(!options.delay){
			options.delay = 200;
		}

		if(options.write){
			afterAF = run;
		}

		return function(){
			if(running){
				return;
			}
			var delay = options.delay - (Date.now() - lastTime);
			running =  true;

			if(delay < 6){
				delay = 6;
			}
			that = options.that || this;
			args = arguments;
			setTimeout(getAF, delay);
		};
	};
})();

/* resize */
(function(){
	'use strict';

	var iWidth, cHeight, installed;
	var docElem = document.documentElement;
	rb.resize = {
		fns: [],
		setup: function(){
			if(!installed){
				installed = true;
				setTimeout(function(){
					iWidth = innerWidth;
					cHeight = docElem.clientHeight;
				});
				window.addEventListener('resize', this.run);
			}
		},
		teardown: function(){
			if(installed && !this.fns.length){
				installed = false;
				window.removeEventListener('resize', this.run);
			}
		},
		on: function(fn, thisArg){
			this.fns.push(fn);
			this.setup();
		},
		off: function(fn){
			var index = this.fns.indexOf(fn);
			if(index != -1){
				this.fns.splice(index, 1);
				this.teardown();
			}
		},
	};

	rb.resize.run = rb.throttle(function(){
		var i, len;
		if(iWidth != innerWidth || cHeight != docElem.clientHeight){
			iWidth = innerWidth;
			cHeight = docElem.clientHeight;

			for(i = 0, len = this.fns.length; i < len; i++){
				this.fns[i]();
			}
		}
	}, {that:rb.resize});
})();

(function(){
	'use strict';
	var $ = rb.$;
	$.fn.elementResize = function(action, fn, options){
		if(!options){
			options = {};
		}
		var add = function(){
			var width, height;
			var iframe = $(document.createElement('iframe'))
					.addClass('js-element-resize')
					.css({
						position: 'absolute',
						top: '0px',
						left: '0px',
						bottom: '0px',
						right: '0px',
						visibility: 'visible',
						'min-width': '100%',
						'min-height': '100%',
						'z-index': '-1',
						border: 'none',
						background: 'transparent',
						opacity: 0
					})
					.attr({
						role: 'presentation',
						tabindex: '-1',
						frameborder: '0',
					})
					.get(0)
				;

			if($(this).find('iframe.js-element-resize').length){
				console.error('only one element resize handler allowed');
			}

			$(this).css({position: 'relative'});
			this.appendChild(iframe);

			setTimeout(function(){
				width = iframe.offsetWidth;
				height = iframe.offsetHeight;
				iframe.contentWindow.addEventListener('resize', function(){
					if( (!options.noWidth && width != iframe.offsetWidth)  || (!options.noHeight && height != iframe.offsetHeight)){
						width = iframe.offsetWidth;
						height = iframe.offsetHeight;
						fn();
					}
				});
			});
		};
		var remove = function(){
			$(this).find('iframe.js-element-resize').remove();
		};

		return this.each(action == 'remove' ? remove : add);
	};
})();

(function(){
	'use strict';
	rb.getCSSNumbers = function(element, styles, onlyPositive){
		var i, value;
		var $element = rb.$(element);
		var numbers = 0;
		if(!Array.isArray(styles)){
			styles = [styles];
		}

		for(i = 0; i < styles.length; i++){
			value = parseFloat($element.css(styles[i])) || 0;

			if(!onlyPositive || value > 0){
				numbers += value;
			}
		}

		return numbers;
	};
})();

(function(){
	'use strict';
	rb.rAF = function(fn, thisArg){
		var running, args;
		var run = function(){
			fn.apply(thisArg || window, args);
		};
		return function(){
			args = arguments;
			if(!running){
				running = true;
				window.requestAnimationFrame(run);
			}
		};
	};
})();

/* rbWidget */
(function(undefined){
	'use strict';
	var $ = rb.$;

	$.fn.rbWidget = function(name, args){
		var ret;

		this.each(function(){
			if(ret === undefined){
				ret = rb.life.getWidget(this, name, args);
			}
		});

		return ret === undefined ?
			this :
			ret
		;
	};

})();
<|endoftext|>


<commit_before>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';
let log = require("../net2/logger.js")(__filename);

let Firewalla = require('../net2/Firewalla.js');

let Promise = require('bluebird');
let cp = require('child_process');

const cpp = require('child-process-promise');
const fs = require("fs");
const platform = require('../platform/PlatformLoader.js').getPlatform();

let instance = null;
class DeviceMgmtTool {
  constructor() {
    if (!instance) {
      instance = this;
    }
    return instance;
  }

  _getOverlayUpperDirectory() {
    return Firewalla.getOverlayUpperDirPartition() + "/overlay";
  }

  _getOverlayUpperWorkDirectory() {
    return Firewalla.getOverlayUpperDirPartition() + "/overlay-workdir";
  }

  async deleteGroup(eptcloud, gid) {
    log.info("Delete group " + gid);
    await eptcloud.deleteGroup(gid)
    log.info("Group " + gid + " is deleted.");
  }

  async resetGold() {
    log.info("Resetting Gold...")
    try {
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
    } catch(err) {
      log.error("Got error when resetting gold, err:", err);
    }
  }

  async resetGoldAndShutdown() {
    log.info("Resetting Gold and Shutdown...")
    try {
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
    } catch(err) {
      log.error("Got error when resetting gold and shutdown, err:", err);
    }
  }

  switchCleanSupportFlag(op=true) {
    const onOff = op ? "ON" : "OFF";
    log.info(`Switch ${onOff} clean support flag`);
    const CLEAN_SUPPORT_FLAG_FILE = '/dev/shm/clean_support.touch'
    try {
      if ( op ) {
        fs.closeSync(fs.openSync(CLEAN_SUPPORT_FLAG_FILE,'w'));
      } else {
        fs.unlinkSync(CLEAN_SUPPORT_FLAG_FILE);
      }
    } catch (err) {
      log.error(`failed to switch ${onOff} clean support flag(${CLEAN_SUPPORT_FLAG_FILE}):`,err);
    }
  }

  resetDevice(config) {
    log.info("Resetting device to factory defaults...");

    if (config) {
      this.switchCleanSupportFlag(config.clean_support);
    }

    if(platform.getName() === 'gold') {
      if(config && config.shutdown) {
        return this.resetGoldAndShutdown();
      } else {
        return this.resetGold();
      }
    }

    if(Firewalla.isOverlayFS()) {
      log.info("OverlayFS is enabled");
      return new Promise((resolve, reject) => {
        let cmd = ((config && config.shutdown) ? "FIREWALLA_POST_RESET_OP=shutdown " : "") + Firewalla.getFirewallaHome() + "/scripts/"+platform.getSystemResetAllOverlayfsScriptName();
        log.info("cmd: ",cmd);
        cp.exec(cmd, (err) => {
          if(err) {
            log.error("Failed to rename overlay upper work directory to backup:", err);
          }
          log.info("Resetting with cmd ",cmd);
          resolve();
        });
      });
    } else {
      log.info("Regular filesystem without OverlayFS");
      let cmd = ((config && config.shutdown) ? "FIREWALLA_POST_RESET_OP=shutdown " : "") + Firewalla.getFirewallaHome() + "/scripts/system-reset-all";
      return new Promise((resolve, reject) => {
        cp.exec(cmd, (err, stdout, stderr) => {
          if(err) {
            reject(err);
            return;
          }
          resolve();
        });
      });
    }
  }
}

module.exports = new DeviceMgmtTool();
<commit_msg>handle undefined config<commit_after>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';
let log = require("../net2/logger.js")(__filename);

let Firewalla = require('../net2/Firewalla.js');

let Promise = require('bluebird');
let cp = require('child_process');

const cpp = require('child-process-promise');
const fs = require("fs");
const platform = require('../platform/PlatformLoader.js').getPlatform();

let instance = null;
class DeviceMgmtTool {
  constructor() {
    if (!instance) {
      instance = this;
    }
    return instance;
  }

  _getOverlayUpperDirectory() {
    return Firewalla.getOverlayUpperDirPartition() + "/overlay";
  }

  _getOverlayUpperWorkDirectory() {
    return Firewalla.getOverlayUpperDirPartition() + "/overlay-workdir";
  }

  async deleteGroup(eptcloud, gid) {
    log.info("Delete group " + gid);
    await eptcloud.deleteGroup(gid)
    log.info("Group " + gid + " is deleted.");
  }

  async resetGold() {
    log.info("Resetting Gold...")
    try {
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR1 firereset");
    } catch(err) {
      log.error("Got error when resetting gold, err:", err);
    }
  }

  async resetGoldAndShutdown() {
    log.info("Resetting Gold and Shutdown...")
    try {
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
      await cpp.exec("sudo pkill -x -SIGUSR2 firereset");
    } catch(err) {
      log.error("Got error when resetting gold and shutdown, err:", err);
    }
  }

  switchCleanSupportFlag(op=true) {
    const onOff = op ? "ON" : "OFF";
    log.info(`Switch ${onOff} clean support flag`);
    const CLEAN_SUPPORT_FLAG_FILE = '/dev/shm/clean_support.touch'
    try {
      if ( op ) {
        fs.closeSync(fs.openSync(CLEAN_SUPPORT_FLAG_FILE,'w'));
      } else {
        fs.unlinkSync(CLEAN_SUPPORT_FLAG_FILE);
      }
    } catch (err) {
      log.error(`failed to switch ${onOff} clean support flag(${CLEAN_SUPPORT_FLAG_FILE}):`,err);
    }
  }

  resetDevice(config) {
    log.info("Resetting device to factory defaults...");

    this.switchCleanSupportFlag(config && config.clean_support);

    if(platform.getName() === 'gold') {
      if(config && config.shutdown) {
        return this.resetGoldAndShutdown();
      } else {
        return this.resetGold();
      }
    }

    if(Firewalla.isOverlayFS()) {
      log.info("OverlayFS is enabled");
      return new Promise((resolve, reject) => {
        let cmd = ((config && config.shutdown) ? "FIREWALLA_POST_RESET_OP=shutdown " : "") + Firewalla.getFirewallaHome() + "/scripts/"+platform.getSystemResetAllOverlayfsScriptName();
        log.info("cmd: ",cmd);
        cp.exec(cmd, (err) => {
          if(err) {
            log.error("Failed to rename overlay upper work directory to backup:", err);
          }
          log.info("Resetting with cmd ",cmd);
          resolve();
        });
      });
    } else {
      log.info("Regular filesystem without OverlayFS");
      let cmd = ((config && config.shutdown) ? "FIREWALLA_POST_RESET_OP=shutdown " : "") + Firewalla.getFirewallaHome() + "/scripts/system-reset-all";
      return new Promise((resolve, reject) => {
        cp.exec(cmd, (err, stdout, stderr) => {
          if(err) {
            reject(err);
            return;
          }
          resolve();
        });
      });
    }
  }
}

module.exports = new DeviceMgmtTool();
<|endoftext|>


<commit_before>"use strict";

// self.table('tableAlias')
//     .query('primaryKeyValue', 'optionalRangeValue')
//     .fetch()
//     .then(function(){
//     });
// this.query('edit', id)
//     .fetch()
//     .then(d.resolve);

// this.query('edit', id)
//     .remove().then(d.resolve);

// this.put('edit', id, range)
//     .set({})
//     .then(d.resolve);

// this.query('edit', id)
//     .update()
//     .set()
//     .commit().then(d.resolve);

// this.batch()
//     .add('edit');

var UpdateQuery = require('./update-query');

function Query(model, alias, hash, range){
    if(!model.schema(alias).range){
        throw new TypeError('Query only for hash/range tables.  Should call Model.get.');
    }
    this.model = model;
    this.alias = alias;
    this.hash = hash;
    this.range = range;
    this.fieldNames = null;
    this.consistentRead = false;
    this._limit = -1;
    this.scanForward = false;
    this.startKey = null;
    this.filter = {};
}

// @todo (lucas) Add where to implement range key conditions.
Query.prototype.start = function(hash, range){
    this.startKey = [hash, range];
    return this;
};

Query.prototype.limit = function(l){
    this._limit = l;
    return this;
};

Query.prototype.consistent = function(){
    this.consistentRead = true;
    return this;
};

Query.prototype.reverse = function(){
    this.scanForward = true;
    return this;
};

Query.prototype.fields = function(fieldNames){
    this.fieldNames = fieldNames;
    return this;
};

Query.prototype.update = function(){
    return new UpdateQuery(this.model, this.alias, this.hash, this.range);
};

Query.prototype.fetch = function(){
    var opts = {},
        schema = this.model.schema(this.alias);

    if(this._limit > -1){
        opts.limit = this._limit;
    }

    if(this.consistentRead){
        opts.consistentRead = this.consistentRead;
    }

    if(this.scanForward){
        opts.scanIndexForward = this.scanForward;
    }

    if(this.fieldNames){
        opts.attributesToGet =  this.fieldNames;
    }

    if(this.filter){
        Object.keys(this.filter).forEach(function(key){
            var f = new Filter(schema, key, this.filter[key]);
            opts.rangeKeyCondition = f.export();
        }.bind(this));
    }

    return this.model.query(this.alias, this.hash, opts);
};

// module.exports.query('song')
//     // .where('id', 'IN', [1, 2, 3])
//     // .where('loves', '<', 1)
//     // .where('trending', '=', null)
//     // .where('title', '!=', null)
//     // .where('bio', 'NULL')
//     // .where('location', 'NOT_NULL')
//     // .where('started', 'BETWEEN', [1990, 1992])
//     // .fetch()
//     // .then(function(results){
//     // });
Query.prototype.where = function(key, operator, value){
    operator = expandOperator(operator) || operator;
    var f = {};
    f[operator] = value;
    this.filter[key] = f;
    return this;
};

function expandOperator(op){
    switch(op){
        case '>':
            return 'GT';

        case '>=':
            return 'GE';

        case '<':
            return 'LT';

        case '<=':
            return 'LE';

        case '!=':
            return 'NE';

        case '=' || '==' || '===':
            return 'EQ';

        default:
            return undefined;
    }
}

var opToArgLength = {
    'EQ': 1,
    'NE': 1,
    'LE': 1,
    'LT': 1,
    'GE': 1,
    'GT': 1,
    'NOT_NULL': 0,
    'NULL': 0,
    'CONTAINS': 1,
    'NOT_CONTAINS': 1,
    'BEGINS_WITH': 1,
    'IN': null,
    'BETWEEN': 2
};

function Filter(schema, key, data){
    this.schema = schema;
    this.field = schema.field(key);
    this.operator = undefined;
    this.value = [];

    if(data === new Object(data)){
        this.operator = Object.keys(data)[0];
        this.value = data[this.operator];
        if(!Array.isArray(this.value)){
            this.value = [this.value];
        }
    }
    else {
        this.operator = data;
        // @todo (lucas) Assert its actually a valueles condition.
    }
    var expectLen = opToArgLength[this.operator];
    if(expectLen !== null && this.value.length !== expectLen){
        throw new Error('Invalid number of args for ' +
            key + ' filter: ' +this.operator + ' ' + this.value);
    }
}

Filter.prototype.export = function(){
    var ret = {
        'AttributeValueList': [],
        'ComparisonOperator': 'EQ'
    };
    if(this.value){
        ret.AttributeValueList = this.value.map(function(val){
            var ret = {};
            ret[this.field.shortType] = this.field.export(val);
            return ret;
        }.bind(this));
    }
    if(this.operator){
        ret.ComparisonOperator = this.operator;
    }

    return ret;
};

module.exports = Query;<commit_msg>Set ScanIndexForward only if false. true is default.<commit_after>"use strict";

// self.table('tableAlias')
//     .query('primaryKeyValue', 'optionalRangeValue')
//     .fetch()
//     .then(function(){
//     });
// this.query('edit', id)
//     .fetch()
//     .then(d.resolve);

// this.query('edit', id)
//     .remove().then(d.resolve);

// this.put('edit', id, range)
//     .set({})
//     .then(d.resolve);

// this.query('edit', id)
//     .update()
//     .set()
//     .commit().then(d.resolve);

// this.batch()
//     .add('edit');

var UpdateQuery = require('./update-query');

function Query(model, alias, hash, range){
    if(!model.schema(alias).range){
        throw new TypeError('Query only for hash/range tables.  Should call Model.get.');
    }
    this.model = model;
    this.alias = alias;
    this.hash = hash;
    this.range = range;
    this.fieldNames = null;
    this.consistentRead = false;
    this._limit = -1;
    this.scanForward = false;
    this.startKey = null;
    this.filter = {};
}

// @todo (lucas) Add where to implement range key conditions.
Query.prototype.start = function(hash, range){
    this.startKey = [hash, range];
    return this;
};

Query.prototype.limit = function(l){
    this._limit = l;
    return this;
};

Query.prototype.consistent = function(){
    this.consistentRead = true;
    return this;
};

Query.prototype.reverse = function(){
    this.scanForward = true;
    return this;
};

Query.prototype.fields = function(fieldNames){
    this.fieldNames = fieldNames;
    return this;
};

Query.prototype.update = function(){
    return new UpdateQuery(this.model, this.alias, this.hash, this.range);
};

Query.prototype.fetch = function(){
    var opts = {},
        schema = this.model.schema(this.alias);

    if(this._limit > -1){
        opts.limit = this._limit;
    }

    if(this.consistentRead){
        opts.consistentRead = this.consistentRead;
    }

    if(!this.scanForward){
        opts.scanIndexForward = this.scanForward;
    }

    if(this.fieldNames){
        opts.attributesToGet =  this.fieldNames;
    }

    if(this.filter){
        Object.keys(this.filter).forEach(function(key){
            var f = new Filter(schema, key, this.filter[key]);
            opts.rangeKeyCondition = f.export();
        }.bind(this));
    }

    return this.model.query(this.alias, this.hash, opts);
};

// module.exports.query('song')
//     // .where('id', 'IN', [1, 2, 3])
//     // .where('loves', '<', 1)
//     // .where('trending', '=', null)
//     // .where('title', '!=', null)
//     // .where('bio', 'NULL')
//     // .where('location', 'NOT_NULL')
//     // .where('started', 'BETWEEN', [1990, 1992])
//     // .fetch()
//     // .then(function(results){
//     // });
Query.prototype.where = function(key, operator, value){
    operator = expandOperator(operator) || operator;
    var f = {};
    f[operator] = value;
    this.filter[key] = f;
    return this;
};

function expandOperator(op){
    switch(op){
        case '>':
            return 'GT';

        case '>=':
            return 'GE';

        case '<':
            return 'LT';

        case '<=':
            return 'LE';

        case '!=':
            return 'NE';

        case '=' || '==' || '===':
            return 'EQ';

        default:
            return undefined;
    }
}

var opToArgLength = {
    'EQ': 1,
    'NE': 1,
    'LE': 1,
    'LT': 1,
    'GE': 1,
    'GT': 1,
    'NOT_NULL': 0,
    'NULL': 0,
    'CONTAINS': 1,
    'NOT_CONTAINS': 1,
    'BEGINS_WITH': 1,
    'IN': null,
    'BETWEEN': 2
};

function Filter(schema, key, data){
    this.schema = schema;
    this.field = schema.field(key);
    this.operator = undefined;
    this.value = [];

    if(data === new Object(data)){
        this.operator = Object.keys(data)[0];
        this.value = data[this.operator];
        if(!Array.isArray(this.value)){
            this.value = [this.value];
        }
    }
    else {
        this.operator = data;
        // @todo (lucas) Assert its actually a valueles condition.
    }
    var expectLen = opToArgLength[this.operator];
    if(expectLen !== null && this.value.length !== expectLen){
        throw new Error('Invalid number of args for ' +
            key + ' filter: ' +this.operator + ' ' + this.value);
    }
}

Filter.prototype.export = function(){
    var ret = {
        'AttributeValueList': [],
        'ComparisonOperator': 'EQ'
    };
    if(this.value){
        ret.AttributeValueList = this.value.map(function(val){
            var ret = {};
            ret[this.field.shortType] = this.field.export(val);
            return ret;
        }.bind(this));
    }
    if(this.operator){
        ret.ComparisonOperator = this.operator;
    }

    return ret;
};

module.exports = Query;<|endoftext|>


<commit_before>var Job = require('./job');

module.exports = Queue;

function Queue(connection, name, options) {
    if (typeof name === 'options' && options === undefined) {
        options = name;
        name = undefined;
    }

    options || (options = {});
    options.collection || (options.collection = 'jobs');

    this.connection = connection;
    this.name = name || 'default';
    this.options = options;

    this.collection = connection.db.collection(this.options.collection);
}

Queue.prototype.job = function(data) {
    return new Job(this.collection, data);
};

Queue.prototype.enqueue = function(name, params, callback) {
    var job = this.job({
        name: name,
        params: params,
        queue: this.name,
        status: 'queued',
        enqueued: new Date()
    });

    job.save(callback);
};

Queue.prototype.dequeue = function(callback) {
    var self = this;

    var query = { status: 'queued', queue: this.name };
    var sort = { enqueued: 1 };
    var update = { '$set': { status: 'dequeued', dequeued: new Date() }};
    var options = { new: true };

    this.collection.findAndModify(query, sort, update, options, function(err, doc) {
        if (err) return callback(err);
        if (!doc) return callback();

        callback(null, self.job(doc));
    });
};<commit_msg>Create index automatically for poling dequeue query<commit_after>var Job = require('./job');

module.exports = Queue;

function Queue(connection, name, options) {
    if (typeof name === 'options' && options === undefined) {
        options = name;
        name = undefined;
    }

    options || (options = {});
    options.collection || (options.collection = 'jobs');

    this.connection = connection;
    this.name = name || 'default';
    this.options = options;

    this.collection = connection.db.collection(this.options.collection);

    if(!options.dontCreateIndex){
        this.ensureIndex();
    }
}

Queue.prototype.job = function(data) {
    return new Job(this.collection, data);
};

Queue.prototype.enqueue = function(name, params, callback) {
    var job = this.job({
        name: name,
        params: params,
        queue: this.name,
        status: 'queued',
        enqueued: new Date()
    });

    job.save(callback);
};

Queue.prototype.dequeue = function(callback) {
    var self = this;

    var query = { status: 'queued', queue: this.name };
    var sort = { enqueued: 1 };
    var update = { '$set': { status: 'dequeued', dequeued: new Date() }};
    var options = { new: true };

    this.collection.findAndModify(query, sort, update, options, function(err, doc) {
        if (err) return callback(err);
        if (!doc) return callback();

        callback(null, self.job(doc));
    });
};

Queue.prototype.ensureIndex = function(){
    //Ensures there's a reasonable index for the poling dequeue
    //Status is first b/c querying by status = queued should be very selective
    this.collection.ensureIndex({ status: 1, queue: 1, enqueued: 1 });
};<|endoftext|>


<commit_before>/* eslint-disable no-useless-return */

'use strict'

const pump = require('pump')
const validation = require('./validation')
const serialize = validation.serialize
const statusCodes = require('http').STATUS_CODES
const flatstr = require('flatstr')

const isError = Symbol('is-error')

function Reply (res, context, request) {
  this.res = res
  this.context = context
  this[isError] = false
  this.sent = false
  this._serializer = null
  this._errored = false
  this.request = request
}

/**
 * Instead of using directly res.end(), we are using setImmediate(…)
 * This because we have observed that with this technique we are faster at responding to the various requests,
 * since the setImmediate forwards the res.end at the end of the poll phase of libuv in the event loop.
 * So we can gather multiple requests and then handle all the replies in a different moment,
 * causing a general improvement of performances, ~+10%.
 */
Reply.prototype.send = function (payload) {
  if (this.sent) {
    this.res.log.warn(new Error('Reply already sent'))
    return
  }

  this.sent = true

  var _isError = this[isError]

  if (payload === undefined && _isError !== true) {
    this.res.setHeader('Content-Length', '0')
    if (!this.res.getHeader('Content-Type')) {
      this.res.setHeader('Content-Type', 'text/plain')
    }
    setImmediate(handleReplyEnd, this, '')
    return
  }

  if (payload && payload.isBoom) {
    this.res.log.error(payload)
    this.res.statusCode = payload.output.statusCode

    this.res.setHeader('Content-Type', 'application/json')
    this.headers(payload.output.headers)

    setImmediate(
      handleReplyEnd,
      this,
      payload.output.payload
    )
    return
  }

  if (payload instanceof Error || _isError === true) {
    handleError(this, payload, wrapHandleReplyEnd)
    return
  }

  if (payload && payload._readableState) {
    if (!this.res.getHeader('Content-Type')) {
      this.res.setHeader('Content-Type', 'application/octet-stream')
    }
    pump(payload, this.res, wrapPumpCallback(this))
    return this.res
  }

  setImmediate(handleReplyEnd, this, payload)
  return
}

Reply.prototype.header = function (key, value) {
  this.res.setHeader(key, value)
  return this
}

Reply.prototype.headers = function (headers) {
  var keys = Object.keys(headers)
  for (var i = 0; i < keys.length; i++) {
    this.header(keys[i], headers[keys[i]])
  }
  return this
}

Reply.prototype.code = function (code) {
  this.res.statusCode = code
  return this
}

Reply.prototype.serialize = function (payload) {
  return serialize(this.context, payload, this.res.statusCode)
}

Reply.prototype.serializer = function (fn) {
  this._serializer = fn
  return this
}

Reply.prototype.type = function (type) {
  this.res.setHeader('Content-Type', type)
  return this
}

Reply.prototype.redirect = function (code, url) {
  if (typeof code === 'string') {
    url = code
    code = 302
  }

  this.header('Location', url).code(code).send()
}

function wrapHandleReplyEnd (reply, payload) {
  setImmediate(
    handleReplyEnd,
    reply,
    payload
  )
}

function wrapPumpCallback (reply) {
  return function pumpCallback (err) {
    if (err) {
      reply.res.log.error(err)
      setImmediate(handleReplyEnd, reply, '')
    }
  }
}

function handleReplyEnd (reply, payload) {
  if (reply.context.onSend !== null) {
    setImmediate(
      reply.context.onSend,
      hookIterator.bind(reply),
      payload,
      wrapOnSendEnd.bind(reply)
    )
  } else {
    wrapOnSendEnd.call(reply, null, payload)
  }
}

function hookIterator (fn, payload, next) {
  return fn(this.request, this, payload, next)
}

function wrapOnSendEnd (err, payload) {
  if (err) {
    handleError(this, err, onSendEnd)
    return
  }
  onSendEnd(this, payload)
}

function onSendEnd (reply, payload) {
  if (payload && payload._readableState) {
    if (!reply.res.getHeader('Content-Type')) {
      reply.res.setHeader('Content-Type', 'application/octet-stream')
    }
    pump(payload, reply.res, wrapPumpCallback(reply))
    return reply.res
  }

  if (!reply.res.getHeader('Content-Type') || reply.res.getHeader('Content-Type') === 'application/json') {
    reply.res.setHeader('Content-Type', 'application/json')
    // Here we are assuming that the custom serializer is a json serializer
    payload = reply._serializer ? reply._serializer(payload) : serialize(reply.context, payload, reply.res.statusCode)
    flatstr(payload)
  } else if (reply._serializer) { // All the code below must have a 'content-type' setted
    payload = reply._serializer(payload)
  }

  if (!reply.res.getHeader('Content-Length')) {
    reply.res.setHeader('Content-Length', '' + Buffer.byteLength(payload))
  }
  reply.sent = true
  reply.res.end(payload)
}

function handleError (reply, err, cb) {
  if (!reply.res.statusCode || reply.res.statusCode < 400) {
    reply.res.statusCode =
        (err === null || err === undefined) ? 500
      : (err.status >= 400) ? err.status
      : (err.statusCode >= 400) ? err.statusCode
      : 500
  }

  if (reply.res.statusCode >= 500) {
    reply.res.log.error({ res: reply.res, err }, err && err.message)
  } else if (reply.res.statusCode >= 400) {
    reply.res.log.info({ res: reply.res, err }, err && err.message)
  }

  var errorHandler = reply.context.errorHandler

  if (errorHandler && !reply._errored) {
    reply.sent = false
    reply._errored = true
    errorHandler(err, reply)
    return
  }

  reply.res.setHeader('Content-Type', 'application/json')

  cb(reply, Object.assign({
    error: statusCodes[reply.res.statusCode + ''],
    message: (err || '') && err.message,
    statusCode: reply.res.statusCode
  }, reply._extendServerError && reply._extendServerError(err)))
}

function buildReply (R) {
  function _Reply (res, context, request) {
    this.res = res
    this.context = context
    this[isError] = false
    this.sent = false
    this._serializer = null
    this.request = request
  }
  _Reply.prototype = new R()
  return _Reply
}

module.exports = Reply
module.exports.buildReply = buildReply
module.exports.isError = isError
<commit_msg>Do not JSON.stringify strings by default, fixes #540<commit_after>/* eslint-disable no-useless-return */

'use strict'

const pump = require('pump')
const validation = require('./validation')
const serialize = validation.serialize
const statusCodes = require('http').STATUS_CODES
const flatstr = require('flatstr')

const isError = Symbol('is-error')

function Reply (res, context, request) {
  this.res = res
  this.context = context
  this[isError] = false
  this.sent = false
  this._serializer = null
  this._errored = false
  this.request = request
}

/**
 * Instead of using directly res.end(), we are using setImmediate(…)
 * This because we have observed that with this technique we are faster at responding to the various requests,
 * since the setImmediate forwards the res.end at the end of the poll phase of libuv in the event loop.
 * So we can gather multiple requests and then handle all the replies in a different moment,
 * causing a general improvement of performances, ~+10%.
 */
Reply.prototype.send = function (payload) {
  if (this.sent) {
    this.res.log.warn(new Error('Reply already sent'))
    return
  }

  this.sent = true

  var _isError = this[isError]

  if (payload === undefined && _isError !== true) {
    this.res.setHeader('Content-Length', '0')
    if (!this.res.getHeader('Content-Type')) {
      this.res.setHeader('Content-Type', 'text/plain')
    }
    setImmediate(handleReplyEnd, this, '')
    return
  }

  if (payload && payload.isBoom) {
    this.res.log.error(payload)
    this.res.statusCode = payload.output.statusCode

    this.res.setHeader('Content-Type', 'application/json')
    this.headers(payload.output.headers)

    setImmediate(
      handleReplyEnd,
      this,
      payload.output.payload
    )
    return
  }

  if (payload instanceof Error || _isError === true) {
    handleError(this, payload, wrapHandleReplyEnd)
    return
  }

  if (payload && payload._readableState) {
    if (!this.res.getHeader('Content-Type')) {
      this.res.setHeader('Content-Type', 'application/octet-stream')
    }
    pump(payload, this.res, wrapPumpCallback(this))
    return this.res
  }

  setImmediate(handleReplyEnd, this, payload)
  return
}

Reply.prototype.header = function (key, value) {
  this.res.setHeader(key, value)
  return this
}

Reply.prototype.headers = function (headers) {
  var keys = Object.keys(headers)
  for (var i = 0; i < keys.length; i++) {
    this.header(keys[i], headers[keys[i]])
  }
  return this
}

Reply.prototype.code = function (code) {
  this.res.statusCode = code
  return this
}

Reply.prototype.serialize = function (payload) {
  return serialize(this.context, payload, this.res.statusCode)
}

Reply.prototype.serializer = function (fn) {
  this._serializer = fn
  return this
}

Reply.prototype.type = function (type) {
  this.res.setHeader('Content-Type', type)
  return this
}

Reply.prototype.redirect = function (code, url) {
  if (typeof code === 'string') {
    url = code
    code = 302
  }

  this.header('Location', url).code(code).send()
}

function wrapHandleReplyEnd (reply, payload) {
  setImmediate(
    handleReplyEnd,
    reply,
    payload
  )
}

function wrapPumpCallback (reply) {
  return function pumpCallback (err) {
    if (err) {
      reply.res.log.error(err)
      setImmediate(handleReplyEnd, reply, '')
    }
  }
}

function handleReplyEnd (reply, payload) {
  if (reply.context.onSend !== null) {
    setImmediate(
      reply.context.onSend,
      hookIterator.bind(reply),
      payload,
      wrapOnSendEnd.bind(reply)
    )
  } else {
    wrapOnSendEnd.call(reply, null, payload)
  }
}

function hookIterator (fn, payload, next) {
  return fn(this.request, this, payload, next)
}

function wrapOnSendEnd (err, payload) {
  if (err) {
    handleError(this, err, onSendEnd)
    return
  }
  onSendEnd(this, payload)
}

function onSendEnd (reply, payload) {
  var contentType = reply.res.getHeader('Content-Type')
  if (payload && payload._readableState) {
    if (!contentType) {
      reply.res.setHeader('Content-Type', 'application/octet-stream')
    }
    pump(payload, reply.res, wrapPumpCallback(reply))
    return reply.res
  }

  if (!contentType && typeof payload === 'string') {
    reply.res.setHeader('Content-Type', 'text/plain')
  } else if (!contentType || contentType === 'application/json') {
    reply.res.setHeader('Content-Type', 'application/json')
    // Here we are assuming that the custom serializer is a json serializer
    payload = reply._serializer ? reply._serializer(payload) : serialize(reply.context, payload, reply.res.statusCode)
    flatstr(payload)
  } else if (reply._serializer) { // All the code below must have a 'content-type' setted
    payload = reply._serializer(payload)
  }

  if (!reply.res.getHeader('Content-Length')) {
    reply.res.setHeader('Content-Length', '' + Buffer.byteLength(payload))
  }
  reply.sent = true
  reply.res.end(payload)
}

function handleError (reply, err, cb) {
  if (!reply.res.statusCode || reply.res.statusCode < 400) {
    reply.res.statusCode =
        (err === null || err === undefined) ? 500
      : (err.status >= 400) ? err.status
      : (err.statusCode >= 400) ? err.statusCode
      : 500
  }

  if (reply.res.statusCode >= 500) {
    reply.res.log.error({ res: reply.res, err }, err && err.message)
  } else if (reply.res.statusCode >= 400) {
    reply.res.log.info({ res: reply.res, err }, err && err.message)
  }

  var errorHandler = reply.context.errorHandler

  if (errorHandler && !reply._errored) {
    reply.sent = false
    reply._errored = true
    errorHandler(err, reply)
    return
  }

  reply.res.setHeader('Content-Type', 'application/json')

  cb(reply, Object.assign({
    error: statusCodes[reply.res.statusCode + ''],
    message: (err || '') && err.message,
    statusCode: reply.res.statusCode
  }, reply._extendServerError && reply._extendServerError(err)))
}

function buildReply (R) {
  function _Reply (res, context, request) {
    this.res = res
    this.context = context
    this[isError] = false
    this.sent = false
    this._serializer = null
    this.request = request
  }
  _Reply.prototype = new R()
  return _Reply
}

module.exports = Reply
module.exports.buildReply = buildReply
module.exports.isError = isError
<|endoftext|>


<commit_before>'use strict';

import series from './series';
import noop from 'lodash/noop';

/**
 * Attempts to get a successful response from `task` no more than `times` times
 * before returning an error. If the task is successful, the `callback` will be
 * passed the result of the successful task. If all attempts fail, the callback
 * will be passed the error and result (if any) of the final attempt.
 *
 * @name retry
 * @static
 * @memberOf async
 * @category Control Flow
 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
 * object with `times` and `interval` or a number.
 * * `times` - The number of attempts to make before giving up.  The default
 *   is `5`.
 * * `interval` - The time to wait between retries, in milliseconds.  The
 *   default is `0`.
 * * If `opts` is a number, the number specifies the number of times to retry,
 *   with the default interval of `0`.
 * @param {Function} task - A function which receives two arguments: (1) a
 * `callback(err, result)` which must be called when finished, passing `err`
 * (which can be `null`) and the `result` of the function's execution, and (2)
 * a `results` object, containing the results of the previously executed
 * functions (if nested inside another control flow). Invoked with
 * (callback, results).
 * @param {Function} [callback] - An optional callback which is called when the
 * task has succeeded, or after the final failed attempt. It receives the `err`
 * and `result` arguments of the last attempt at completing the `task`. Invoked
 * with (err, results).
 * @example
 *
 * // The `retry` function can be used as a stand-alone control flow by passing
 * // a callback, as shown below:
 *
 * // try calling apiMethod 3 times
 * async.retry(3, apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 * // try calling apiMethod 3 times, waiting 200 ms between each retry
 * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 *  // try calling apiMethod the default 5 times no delay between each retry
 * async.retry(apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 * // It can also be embedded within other control flow functions to retry
 * // individual methods that are not as reliable, like this:
 * async.auto({
 *     users: api.getUsers.bind(api),
 *     payments: async.retry(3, api.getPayments.bind(api))
 * }, function(err, results) {
 *     // do something with the results
 * });
 */
export default function retry(times, task, callback) {
    var DEFAULT_TIMES = 5;
    var DEFAULT_INTERVAL = 0;

    var opts = {
        times: DEFAULT_TIMES,
        intervalFunc: constantIntervalFunc(DEFAULT_INTERVAL)
    };

    function parseTimes(acc, t) {
        if (typeof t === 'object') {
            acc.times = +t.times || DEFAULT_TIMES;

            if (typeof t.interval === 'function') {
                acc.intervalFunc = t.interval;
            } else {
                acc.intervalFunc = constantIntervalFunc(+t.interval || DEFAULT_INTERVAL);
            }
        } else if (typeof t === 'number' || typeof t === 'string') {
            acc.times = +t || DEFAULT_TIMES;
        } else {
            throw new Error("Invalid arguments for async.retry");
        }
    }

    if (arguments.length < 3 && typeof times === 'function') {
        callback = task || noop;
        task = times;
    } else {
        parseTimes(opts, times);
        callback = callback || noop;
    }

    if (typeof task !== 'function') {
        throw new Error("Invalid arguments for async.retry");
    }

    var attempts = [];
    for (var i = 1; i < opts.times + 1; i++) {
        var isFinalAttempt = (i == opts.times);
        attempts.push(retryAttempt(isFinalAttempt));
        var interval = opts.intervalFunc(i);
        if (!isFinalAttempt && interval > 0) {
            attempts.push(retryInterval(interval));
        }
    }

    series(attempts, function(done, data) {
        data = data[data.length - 1];
        callback(data.err, data.result);
    });

    function retryAttempt(isFinalAttempt) {
        return function(seriesCallback) {
            task(function(err, result) {
                seriesCallback(!err || isFinalAttempt, {
                    err: err,
                    result: result
                });
            });
        };
    }

    function retryInterval(interval) {
        return function(seriesCallback) {
            setTimeout(function() {
                seriesCallback(null);
            }, interval);
        };
    }

    function constantIntervalFunc(interval) {
        return function() {
            return interval;
        };
    }
}
<commit_msg>Style fixes<commit_after>'use strict';

import series from './series';
import noop from 'lodash/noop';
import constant from 'lodash/constant';

/**
 * Attempts to get a successful response from `task` no more than `times` times
 * before returning an error. If the task is successful, the `callback` will be
 * passed the result of the successful task. If all attempts fail, the callback
 * will be passed the error and result (if any) of the final attempt.
 *
 * @name retry
 * @static
 * @memberOf async
 * @category Control Flow
 * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
 * object with `times` and `interval` or a number.
 * * `times` - The number of attempts to make before giving up.  The default
 *   is `5`.
 * * `interval` - The time to wait between retries, in milliseconds.  The
 *   default is `0`.
 * * If `opts` is a number, the number specifies the number of times to retry,
 *   with the default interval of `0`.
 * @param {Function} task - A function which receives two arguments: (1) a
 * `callback(err, result)` which must be called when finished, passing `err`
 * (which can be `null`) and the `result` of the function's execution, and (2)
 * a `results` object, containing the results of the previously executed
 * functions (if nested inside another control flow). Invoked with
 * (callback, results).
 * @param {Function} [callback] - An optional callback which is called when the
 * task has succeeded, or after the final failed attempt. It receives the `err`
 * and `result` arguments of the last attempt at completing the `task`. Invoked
 * with (err, results).
 * @example
 *
 * // The `retry` function can be used as a stand-alone control flow by passing
 * // a callback, as shown below:
 *
 * // try calling apiMethod 3 times
 * async.retry(3, apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 * // try calling apiMethod 3 times, waiting 200 ms between each retry
 * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 *  // try calling apiMethod the default 5 times no delay between each retry
 * async.retry(apiMethod, function(err, result) {
 *     // do something with the result
 * });
 *
 * // It can also be embedded within other control flow functions to retry
 * // individual methods that are not as reliable, like this:
 * async.auto({
 *     users: api.getUsers.bind(api),
 *     payments: async.retry(3, api.getPayments.bind(api))
 * }, function(err, results) {
 *     // do something with the results
 * });
 */
export default function retry(times, task, callback) {
    var DEFAULT_TIMES = 5;
    var DEFAULT_INTERVAL = 0;

    var opts = {
        times: DEFAULT_TIMES,
        intervalFunc: constant(DEFAULT_INTERVAL)
    };

    function parseTimes(acc, t) {
        if (typeof t === 'object') {
            acc.times = +t.times || DEFAULT_TIMES;

            acc.intervalFunc = typeof t.interval === 'function' ?
                t.interval :
                constant(+t.interval || DEFAULT_INTERVAL);
        } else if (typeof t === 'number' || typeof t === 'string') {
            acc.times = +t || DEFAULT_TIMES;
        } else {
            throw new Error("Invalid arguments for async.retry");
        }
    }

    if (arguments.length < 3 && typeof times === 'function') {
        callback = task || noop;
        task = times;
    } else {
        parseTimes(opts, times);
        callback = callback || noop;
    }

    if (typeof task !== 'function') {
        throw new Error("Invalid arguments for async.retry");
    }

    var attempts = [];
    for (var i = 1; i < opts.times + 1; i++) {
        var isFinalAttempt = (i == opts.times);
        attempts.push(retryAttempt(isFinalAttempt));
        var interval = opts.intervalFunc(i);
        if (!isFinalAttempt && interval > 0) {
            attempts.push(retryInterval(interval));
        }
    }

    series(attempts, function(done, data) {
        data = data[data.length - 1];
        callback(data.err, data.result);
    });

    function retryAttempt(isFinalAttempt) {
        return function(seriesCallback) {
            task(function(err, result) {
                seriesCallback(!err || isFinalAttempt, {
                    err: err,
                    result: result
                });
            });
        };
    }

    function retryInterval(interval) {
        return function(seriesCallback) {
            setTimeout(function() {
                seriesCallback(null);
            }, interval);
        };
    }
}
<|endoftext|>


<commit_before>const bunyan = require('bunyan');
const bunyanFormat = require('bunyan-format');
const GitHubApi = require('github');
const Bottleneck = require('bottleneck');
const Context = require('./context');

const logger = bunyan.createLogger({
  name: 'PRobot',
  level: process.env.LOG_LEVEL || 'debug',
  stream: bunyanFormat({outputMode: process.env.LOG_FORMAT || 'short'})
});

class Robot {
  constructor(integration, webhook, cache) {
    this.integration = integration;
    this.webhook = webhook;
    this.cache = cache;
  }

  on(event, callback) {
    const [name, action] = event.split('.');

    return this.webhook.on(name, event => {
      if (!action || action === event.payload.action) {
        callback(event, new Context(event));
      }
    });
  }

  async auth(id) {
    const token = await this.cache.wrap(`integration:${id}:token`, () => {
      this.log.info(`creating token for installation ${id}`);
      return this.integration.createToken(id);
    }, {ttl: 60 * 60});

    const github = new GitHubApi({debug: process.env.LOG_LEVEL === 'trace'});
    github.authenticate({type: 'token', token: token.token});
    return probotEnhancedClient(github);
  }

  log(...args) {
    return logger.debug(...args);
  }
}

function probotEnhancedClient(github) {
  github = rateLimitedClient(github);

  github.paginate = require('./lib/paginate');

  return github;
}

// Hack client to only allow one request at a time with a 1s delay
// https://github.com/mikedeboer/node-github/issues/526
function rateLimitedClient(github) {
  const limiter = new Bottleneck(1, 1000);
  const oldHandler = github.handler;
  github.handler = (msg, block, callback) => {
    limiter.submit(oldHandler.bind(github), msg, block, callback);
  };
  return github;
}

// Add level methods on the logger
['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(level => {
  Robot.prototype.log[level] = logger[level].bind(logger);
});

module.exports = (...args) => new Robot(...args);
<commit_msg>robot.auth as integration or installation<commit_after>const bunyan = require('bunyan');
const bunyanFormat = require('bunyan-format');
const GitHubApi = require('github');
const Bottleneck = require('bottleneck');
const Context = require('./context');

const logger = bunyan.createLogger({
  name: 'PRobot',
  level: process.env.LOG_LEVEL || 'debug',
  stream: bunyanFormat({outputMode: process.env.LOG_FORMAT || 'short'})
});

class Robot {
  constructor(integration, webhook, cache) {
    this.integration = integration;
    this.webhook = webhook;
    this.cache = cache;
  }

  on(event, callback) {
    const [name, action] = event.split('.');

    return this.webhook.on(name, event => {
      if (!action || action === event.payload.action) {
        callback(event, new Context(event));
      }
    });
  }

  async auth(id) {
    let github;

    if(id) {
      const token = await this.cache.wrap(`integration:${id}:token`, () => {
        this.log.info(`creating token for installation ${id}`);
        return this.integration.createToken(id);
      }, {ttl: 60 * 60});

      github = new GitHubApi({debug: process.env.LOG_LEVEL === 'trace'});
      github.authenticate({type: 'token', token: token.token});
    } else {
      github = await this.integration.asIntegration();
    }

    return probotEnhancedClient(github);
  }

  log(...args) {
    return logger.debug(...args);
  }
}

function probotEnhancedClient(github) {
  github = rateLimitedClient(github);

  github.paginate = require('./paginate');

  return github;
}

// Hack client to only allow one request at a time with a 1s delay
// https://github.com/mikedeboer/node-github/issues/526
function rateLimitedClient(github) {
  const limiter = new Bottleneck(1, 1000);
  const oldHandler = github.handler;
  github.handler = (msg, block, callback) => {
    limiter.submit(oldHandler.bind(github), msg, block, callback);
  };
  return github;
}

// Add level methods on the logger
['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(level => {
  Robot.prototype.log[level] = logger[level].bind(logger);
});

module.exports = (...args) => new Robot(...args);
<|endoftext|>


<commit_before>/*global describe it before after  =*/

"use client";

require(["lib/architect/architect", "lib/chai/chai"],
  function (architect, chai, baseProc) {
    var expect = chai.expect;

    var runners  = {
        "node" : {
            "caption" : "Node.js (current)",
            "cmd": ["node", "$file"],
            "debug": ["--debug-brk=5454"],
            "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
            "selector": "source.python",
            "info": "Your code is running at \\033[01;34m$hostname\\033[00m.\n"
                + "\\033[01;31mImportant:\\033[00m use \\033[01;32mprocess.env.PORT\\033[00m as the port and \\033[01;32mprocess.env.IP\\033[00m as the host in your scripts!\n"
        },
        "pythoni" : {
            "caption" : "Python in interactive mode",
            "cmd": ["python", "-i"],
            "selector": "source.python",
            "info": "Hit \\033[01;34mCtrl-D\\033[00m to exit.\n"
        }
    };

    expect.setupArchitectTest([
        {
            packagePath : "plugins/c9.core/c9",
            workspaceId : "ubuntu/ip-10-35-77-180",
            startdate   : new Date(),
            debug       : true,
            hosted      : true,
            local       : false,
            hostname    : "dev.javruben.c9.io",
            davPrefix   : "/"
        },

        "plugins/c9.core/ext",
        "plugins/c9.core/http",
        "plugins/c9.core/util",
        "plugins/c9.ide.ui/anims",
        "plugins/c9.ide.ui/lib_apf",
        {
            packagePath : "plugins/c9.core/settings",
            settings : "<settings><state><console>" + JSON.stringify({
                type  : "pane",
                nodes : [
                    {
                        type : "tab",
                        editorType : "immediate",
                        active : "true"
                    }
                ]
            }) + "</console></state></settings>"
        },
        {
            packagePath  : "plugins/c9.ide.ui/ui",
            staticPrefix : "plugins/c9.ide.ui"
        },
        "plugins/c9.ide.editors/document",
        "plugins/c9.ide.editors/undomanager",
        "plugins/c9.ide.editors/editors",
        "plugins/c9.ide.editors/editor",
        {
            packagePath : "plugins/c9.ide.editors/tabmanager",
            testing     : 2
        },
        "plugins/c9.ide.ui/focus",
        "plugins/c9.ide.editors/pane",
        "plugins/c9.ide.editors/tab",
        "plugins/c9.ide.ace/ace",
        "plugins/c9.ide.ace.statusbar/statusbar",
        "plugins/c9.ide.ace.gotoline/gotoline",
        {
            packagePath: "plugins/c9.ide.immediate/immediate",
            staticPrefix : "plugins/c9.ide.layout.classic"
        },
        "plugins/c9.ide.immediate/evaluator",
        "plugins/c9.ide.immediate/evaluators/browserjs",
        "plugins/c9.ide.console/console",
        "plugins/c9.fs/proc",
        "plugins/c9.fs/fs",
        "plugins/c9.vfs.client/vfs_client",
        "plugins/c9.vfs.client/endpoint",
        "plugins/c9.ide.auth/auth",
        "plugins/c9.ide.keys/commands",
        {
            packagePath : "plugins/c9.ide.run/run",
            testing     : true,
            base        : baseProc,
            runners     : runners
        },
        "plugins/c9.ide.ui/menus.js",

        // Mock plugins
        {
            consumes : ["apf", "ui", "Plugin"],
            provides : [
                "menus", "layout", "watcher",
                "save", "fs", "preferences", "clipboard",
                "auth.bootstrap", "info", "dialog.alert"
            ],
            setup    : expect.html.mocked,
            show: function() {
                alert(arguments);
            }
        },
        {
            consumes : ["immediate", "tabManager"],
            provides : [],
            setup    : main
        }
    ], architect);

    function main(options, imports, register) {
        var immediate = imports.immediate;
        var tabs      = imports.tabManager;

        expect.html.setConstructor(function(tab){
            if (typeof tab == "object")
                return tab.pane.aml.getPage("editor::" + tab.editorType).$ext;
        });

        function countEvents(count, expected, done){
            if (count == expected)
                done();
            else
                throw new Error("Wrong Event Count: "
                    + count + " of " + expected);
        }

        describe('immediate', function() {
            before(function(done){
                apf.config.setProperty("allow-select", false);
                apf.config.setProperty("allow-blur", false);

                window.bar.$ext.style.background = "rgba(220, 220, 220, 0.93)";
                window.bar.$ext.style.position = "fixed";
                window.bar.$ext.style.left = "20px";
                window.bar.$ext.style.right = "20px";
                window.bar.$ext.style.bottom = "20px";
                window.bar.$ext.style.height = "150px";

                document.body.style.marginBottom = "150px";

               // for (var name in runners) {
               //     immediate.addType(name.uCaseFirst(), name);
               // }

                done();
            });

            describe("addType(), on.evaluate", function(){
                it('should add an item to the dropdown and run it', function(done) {
                    // var inp = tabs.focussedTab.editor.getElement("txtInput");
                    // inp.setValue("1+1");
                    // inp.dispatchEvent("keydown", {keyCode: 13});
                    done();
                });
            });

            // after(function(done){
            //     tabs.unload();
            //     bar.parentNode.removeChild(bar);
            //
            //     document.body.style.marginBottom = "";
            //     done();
            // });
        });

        onload && onload();
    }
});<commit_msg>Fix remainder api-dependant tests<commit_after>/*global describe it before after  =*/

"use client";

require(["lib/architect/architect", "lib/chai/chai"],
  function (architect, chai, baseProc) {
    var expect = chai.expect;

    var runners  = {
        "node" : {
            "caption" : "Node.js (current)",
            "cmd": ["node", "$file"],
            "debug": ["--debug-brk=5454"],
            "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
            "selector": "source.python",
            "info": "Your code is running at \\033[01;34m$hostname\\033[00m.\n"
                + "\\033[01;31mImportant:\\033[00m use \\033[01;32mprocess.env.PORT\\033[00m as the port and \\033[01;32mprocess.env.IP\\033[00m as the host in your scripts!\n"
        },
        "pythoni" : {
            "caption" : "Python in interactive mode",
            "cmd": ["python", "-i"],
            "selector": "source.python",
            "info": "Hit \\033[01;34mCtrl-D\\033[00m to exit.\n"
        }
    };

    expect.setupArchitectTest([
        {
            packagePath : "plugins/c9.core/c9",
            workspaceId : "ubuntu/ip-10-35-77-180",
            startdate   : new Date(),
            debug       : true,
            hosted      : true,
            local       : false,
            hostname    : "dev.javruben.c9.io",
            davPrefix   : "/"
        },

        "plugins/c9.core/ext",
        "plugins/c9.core/http",
        "plugins/c9.core/util",
        "plugins/c9.ide.ui/anims",
        "plugins/c9.ide.ui/lib_apf",
        {
            packagePath : "plugins/c9.core/settings",
            settings : "<settings><state><console>" + JSON.stringify({
                type  : "pane",
                nodes : [
                    {
                        type : "tab",
                        editorType : "immediate",
                        active : "true"
                    }
                ]
            }) + "</console></state></settings>"
        },
        "plugins/c9.ide.api/api.js",
        {
            packagePath  : "plugins/c9.ide.ui/ui",
            staticPrefix : "plugins/c9.ide.ui"
        },
        "plugins/c9.ide.editors/document",
        "plugins/c9.ide.editors/undomanager",
        "plugins/c9.ide.editors/editors",
        "plugins/c9.ide.editors/editor",
        {
            packagePath : "plugins/c9.ide.editors/tabmanager",
            testing     : 2
        },
        "plugins/c9.ide.ui/focus",
        "plugins/c9.ide.editors/pane",
        "plugins/c9.ide.editors/tab",
        "plugins/c9.ide.ace/ace",
        "plugins/c9.ide.ace.statusbar/statusbar",
        "plugins/c9.ide.ace.gotoline/gotoline",
        {
            packagePath: "plugins/c9.ide.immediate/immediate",
            staticPrefix : "plugins/c9.ide.layout.classic"
        },
        "plugins/c9.ide.immediate/evaluator",
        "plugins/c9.ide.immediate/evaluators/browserjs",
        "plugins/c9.ide.console/console",
        "plugins/c9.fs/proc",
        "plugins/c9.fs/fs",
        "plugins/c9.vfs.client/vfs_client",
        "plugins/c9.vfs.client/endpoint",
        "plugins/c9.ide.auth/auth",
        "plugins/c9.ide.keys/commands",
        {
            packagePath : "plugins/c9.ide.run/run",
            testing     : true,
            base        : baseProc,
            runners     : runners
        },
        "plugins/c9.ide.ui/menus.js",

        // Mock plugins
        {
            consumes : ["apf", "ui", "Plugin"],
            provides : [
                "menus", "layout", "watcher",
                "save", "fs", "preferences", "clipboard",
                "auth.bootstrap", "info", "dialog.alert"
            ],
            setup    : expect.html.mocked,
            show: function() {
                alert(arguments);
            }
        },
        {
            consumes : ["immediate", "tabManager"],
            provides : [],
            setup    : main
        }
    ], architect);

    function main(options, imports, register) {
        var immediate = imports.immediate;
        var tabs      = imports.tabManager;

        expect.html.setConstructor(function(tab){
            if (typeof tab == "object")
                return tab.pane.aml.getPage("editor::" + tab.editorType).$ext;
        });

        function countEvents(count, expected, done){
            if (count == expected)
                done();
            else
                throw new Error("Wrong Event Count: "
                    + count + " of " + expected);
        }

        describe('immediate', function() {
            before(function(done){
                apf.config.setProperty("allow-select", false);
                apf.config.setProperty("allow-blur", false);

                window.bar.$ext.style.background = "rgba(220, 220, 220, 0.93)";
                window.bar.$ext.style.position = "fixed";
                window.bar.$ext.style.left = "20px";
                window.bar.$ext.style.right = "20px";
                window.bar.$ext.style.bottom = "20px";
                window.bar.$ext.style.height = "150px";

                document.body.style.marginBottom = "150px";

               // for (var name in runners) {
               //     immediate.addType(name.uCaseFirst(), name);
               // }

                done();
            });

            describe("addType(), on.evaluate", function(){
                it('should add an item to the dropdown and run it', function(done) {
                    // var inp = tabs.focussedTab.editor.getElement("txtInput");
                    // inp.setValue("1+1");
                    // inp.dispatchEvent("keydown", {keyCode: 13});
                    done();
                });
            });

            // after(function(done){
            //     tabs.unload();
            //     bar.parentNode.removeChild(bar);
            //
            //     document.body.style.marginBottom = "";
            //     done();
            // });
        });

        onload && onload();
    }
});<|endoftext|>


<commit_before><commit_msg>Get Programming<commit_after><|endoftext|>