<commit_before>const fs = require('fs')
const path = require('path')

exports.exists = function (path) {
  try {
    fs.statSync(path)
    return true
  } catch (err) {
    return false
  }
}

exports.deleteDir = function (filePath, leaveDist, callback) {
  const me = this;

  fs.readdirSync(filePath).forEach(function (file, index) {
    var curPath = filePath + '/' + file

    if (fs.statSync(curPath).isDirectory()) {
      const name = path.parse(curPath).name

      if (name !== '.git') {
        me.deleteDir(curPath)
      }
    } else {
      fs.unlinkSync(curPath)
    }
  })

  if (!leaveDist) {
    fs.rmdirSync(filePath)
  }

  if (typeof(callback) == 'function') {
    callback()
  }
}

exports.isSite = function () {
  const pkgPath = process.cwd() + '/package.json'

  if (!exports.exists(pkgPath)) {
    return false
  }

  const package = require(pkgPath)

  if (!package.scripts || !package.scripts.start) {
    return false
  }

  const startScript = package.scripts.start
  return startScript.includes('cory')
}
<commit_msg>Don't delete .gitignores<commit_after>const fs = require('fs')
const path = require('path')

exports.exists = function (path) {
  try {
    fs.statSync(path)
    return true
  } catch (err) {
    return false
  }
}

exports.deleteDir = function (filePath, leaveDist, callback) {
  const me = this;

  fs.readdirSync(filePath).forEach(function (file, index) {
    var curPath = filePath + '/' + file
    const details = path.parse(curPath)

    if (fs.statSync(curPath).isDirectory()) {
      if (details.name !== '.git') {
        me.deleteDir(curPath)
      }
    } else if (details.base !== '.gitignore') {
      fs.unlinkSync(curPath)
    }
  })

  if (!leaveDist) {
    fs.rmdirSync(filePath)
  }

  if (typeof(callback) == 'function') {
    callback()
  }
}

exports.isSite = function () {
  const pkgPath = process.cwd() + '/package.json'

  if (!exports.exists(pkgPath)) {
    return false
  }

  const package = require(pkgPath)

  if (!package.scripts || !package.scripts.start) {
    return false
  }

  const startScript = package.scripts.start
  return startScript.includes('cory')
}
<|endoftext|>


<commit_before>/*!
 * node-gpg
 * Copyright(c) 2011 Nicholas Penree <drudge@conceited.net>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var spawn = require('child_process').spawn
  , stream = require('fs').createReadStream
  , writeStream = require('fs').createWriteStream
  , readFile = require('fs').readFile
  , pump = require('util').pump
  , exists = require('path').exists
  , globalArgs = ['--no-use-agent', '--batch']
  ;

/**
 * Base `GPG` object.
 */

var GPG = {

  /**
   * Encrypt source file passed as `options.source` and store it in a file specified in `options.dest`.
   *
   * @param {Object} options
   * @param {Function} Optional callback
   * @api public
   */

  encryptToFile: function(options, fn){
    options = options || {};

    if (typeof options.source === 'undefined'){
      return fn.call(null, new Error('Missing \'source\' option'));
    } else if (typeof options.dest === 'undefined'){
      return fn.call(null, new Error('Missing \'dest\' option'));
    }

    exists(options.source, function(e){
      if (e){
        var buffer = new Buffer('')
          , fileStream = stream(options.source)
          , destStream = writeStream(options.dest)
          , gpg = spawn('gpg', ['--encrypt']);

        gpg.on('close', function (code){
          fn.call(null, null);
        });

        pump(fileStream, gpg.stdin);
        pump(gpg.stdout, destStream);
      } else {
        fn.call(null, new Error(options.source + ' does not exist', null));
      }
    });
  },

  /**
   * Encrypt source `file` and pass the encrypted contents to the callback `fn`.
   *
   * @param {String} file
   * @param {Function} Optional callback containing the encrypted file contents.
   * @api public
   */

  encryptFile: function(file, fn){
    var self = this;

    readFile(file, function(err, content){
      self.encrypt(content, function(err, data){
        fn.call(null, err, data);
      });
    });
  },

  /**
   * Encrypt string `str` and pass the encrypted version to the callback `fn`.
   *
   * @param {String} str
   * @param {Array} args Optional array of additonal gpg arguments.
   * @param {Function} fn Optional callback containing the encrypted Buffer.
   * @api public
   */

  encrypt: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--encrypt']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function (buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function(buf){
      error += buf.toString('utf8');
    });

    gpg.on('close', function (code){
      if (code !== 0) {
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });
      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  },

  /**
   * Decrypt `str` and pass the decrypted version to the callback `fn`.
   *
   * @param {String|Buffer} str
   * @param {Array} args Optional array of additonal gpg arguments.
   * @param {Function} fn Optional callback containing the decrypted Buffer.
   * @api public
   */

  decrypt: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--decrypt']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function (buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function (data){
      error += data.toString('utf8');
    });

    gpg.on('close', function (code){
      if (code !== 0){
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });
      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  },

  /**
   * Decrypt source `file` and pass the decrypted contents to the callback `fn`.
   *
   * @param {String} file
   * @param {Function} Optional callback containing the decrypted file contents.
   * @api public
   */

  decryptFile: function(file, fn){
    var self = this;

    readFile(file, function(err, content){
      self.decrypt(content, function(err, data){
        fn.call(null, err, data);
      });
    });
  },

  /**
   * Decrypt source file passed as `options.source` and store it in a file specified in `options.dest`.
   *
   * @param {Object} options
   * @param {Function} Optional callback
   * @api public
   */

  decryptToFile: function(options, fn){
    options = options || {};

    if (typeof options.source === 'undefined'){
      return fn.call(null, new Error('Missing \'source\' option'));
    } else if (typeof options.dest === 'undefined'){
      return fn.call(null, new Error('Missing \'dest\' option'));
    }

    exists(options.source, function(e){
      if (e){
        var buffer = new Buffer('')
          , fileStream = stream(options.source)
          , destStream = writeStream(options.dest)
          , gpg = spawn('gpg', ['--decrypt']);

        gpg.on('close', function (code){
          fn.call(null, null);
        });

        pump(fileStream, gpg.stdin);
        pump(gpg.stdout, destStream);
      } else {
        fn.call(null, new Error(options.source + ' does not exist'));
      }
    });
  },

  /**
   * Clearsign `str` and pass the signed message to the callback `fn`.
   *
   * @param {String|Buffer} str
   * @param {Array} args Optional additional arguments to pass to gpg.
   * @param {Function} callback containing the signed message Buffer.
   * @api public
   */

  clearsign: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--clearsign']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function(buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function(data){
      error += data.toString('utf8');
    });

    gpg.on('close', function(code){
      if (code !== 0) {
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });

      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  }

};

/**
 * Expose `GPG` object.
 */

module.exports = GPG;
<commit_msg>Add verifySignature function.<commit_after>/*!
 * node-gpg
 * Copyright(c) 2011 Nicholas Penree <drudge@conceited.net>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var spawn = require('child_process').spawn
  , stream = require('fs').createReadStream
  , writeStream = require('fs').createWriteStream
  , readFile = require('fs').readFile
  , pump = require('util').pump
  , exists = require('path').exists
  , globalArgs = ['--no-use-agent', '--batch']
  ;

/**
 * Base `GPG` object.
 */

var GPG = {

  /**
   * Encrypt source file passed as `options.source` and store it in a file specified in `options.dest`.
   *
   * @param {Object} options
   * @param {Function} Optional callback
   * @api public
   */

  encryptToFile: function(options, fn){
    options = options || {};

    if (typeof options.source === 'undefined'){
      return fn.call(null, new Error('Missing \'source\' option'));
    } else if (typeof options.dest === 'undefined'){
      return fn.call(null, new Error('Missing \'dest\' option'));
    }

    exists(options.source, function(e){
      if (e){
        var buffer = new Buffer('')
          , fileStream = stream(options.source)
          , destStream = writeStream(options.dest)
          , gpg = spawn('gpg', ['--encrypt']);

        gpg.on('close', function (code){
          fn.call(null, null);
        });

        pump(fileStream, gpg.stdin);
        pump(gpg.stdout, destStream);
      } else {
        fn.call(null, new Error(options.source + ' does not exist', null));
      }
    });
  },

  /**
   * Encrypt source `file` and pass the encrypted contents to the callback `fn`.
   *
   * @param {String} file
   * @param {Function} Optional callback containing the encrypted file contents.
   * @api public
   */

  encryptFile: function(file, fn){
    var self = this;

    readFile(file, function(err, content){
      self.encrypt(content, function(err, data){
        fn.call(null, err, data);
      });
    });
  },

  /**
   * Encrypt string `str` and pass the encrypted version to the callback `fn`.
   *
   * @param {String} str
   * @param {Array} args Optional array of additonal gpg arguments.
   * @param {Function} fn Optional callback containing the encrypted Buffer.
   * @api public
   */

  encrypt: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--encrypt']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function (buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function(buf){
      error += buf.toString('utf8');
    });

    gpg.on('close', function (code){
      if (code !== 0) {
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });
      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  },

  /**
   * Decrypt `str` and pass the decrypted version to the callback `fn`.
   *
   * @param {String|Buffer} str
   * @param {Array} args Optional array of additonal gpg arguments.
   * @param {Function} fn Optional callback containing the decrypted Buffer.
   * @api public
   */

  decrypt: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--decrypt']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function (buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function (data){
      error += data.toString('utf8');
    });

    gpg.on('close', function (code){
      if (code !== 0){
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });
      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  },

  /**
   * Decrypt source `file` and pass the decrypted contents to the callback `fn`.
   *
   * @param {String} file
   * @param {Function} Optional callback containing the decrypted file contents.
   * @api public
   */

  decryptFile: function(file, fn){
    var self = this;

    readFile(file, function(err, content){
      self.decrypt(content, function(err, data){
        fn.call(null, err, data);
      });
    });
  },

  /**
   * Decrypt source file passed as `options.source` and store it in a file specified in `options.dest`.
   *
   * @param {Object} options
   * @param {Function} Optional callback
   * @api public
   */

  decryptToFile: function(options, fn){
    options = options || {};

    if (typeof options.source === 'undefined'){
      return fn.call(null, new Error('Missing \'source\' option'));
    } else if (typeof options.dest === 'undefined'){
      return fn.call(null, new Error('Missing \'dest\' option'));
    }

    exists(options.source, function(e){
      if (e){
        var buffer = new Buffer('')
          , fileStream = stream(options.source)
          , destStream = writeStream(options.dest)
          , gpg = spawn('gpg', ['--decrypt']);

        gpg.on('close', function (code){
          fn.call(null, null);
        });

        pump(fileStream, gpg.stdin);
        pump(gpg.stdout, destStream);
      } else {
        fn.call(null, new Error(options.source + ' does not exist'));
      }
    });
  },

  /**
   * Clearsign `str` and pass the signed message to the callback `fn`.
   *
   * @param {String|Buffer} str
   * @param {Array} args Optional additional arguments to pass to gpg.
   * @param {Function} callback containing the signed message Buffer.
   * @api public
   */

  clearsign: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--clearsign']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    gpg.stdout.on('data', function(buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.stderr.on('data', function(data){
      error += data.toString('utf8');
    });

    gpg.on('close', function(code){
      if (code !== 0) {
        return fn.call(null, new Error(error));
      }

      // concatenate all buffers together
      var buffer = new Buffer(buffersLength)
        , targetStart = 0;
      buffers.forEach(function(b){
        b.copy(buffer, targetStart);
        targetStart += b.length
      });

      fn.call(null, null, buffer);
    });

    gpg.stdin.end(str);
  },

  /**
   * Verify `str` and pass the output to the callback `fn`.
   *
   * @param {String|Buffer} str
   * @param {Array} args Optional additional arguments to pass to gpg.
   * @param {Function} callback containing the signed message Buffer.
   * @api public
   */
  verifySignature: function(str, args, fn){
    var defaultArgs = globalArgs.concat(['--verify']);
    if (typeof args === 'function'){
      fn = args;
      args = defaultArgs;
    } else {
      args = defaultArgs.concat(args);
    }

    var buffers = []
      , buffersLength = 0
      , error = ''
      , gpg = spawn('gpg', args);

    // For whatever reason, all data comes through stderr
    gpg.stderr.on('data', function(buf){
      buffers.push(buf);
      buffersLength += buf.length;
    });

    gpg.on('close', function(code){
      var msg = Buffer.concat(buffers, buffersLength);
      if (code !== 0) {
        return fn(new Error(error));
      }

      fn(null, msg);
    });

    gpg.stdin.end(str);
  }

};

/**
 * Expose `GPG` object.
 */

module.exports = GPG;
<|endoftext|>


<commit_before>/**
 * Appcelerator Common Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var exec = require('child_process').exec,
	async = require('async'),
	path = require('path'),
	util = require('./util'),
	fs = require('fs'),
	afs = require('./fs'),
	plist = require('./plist'),
	version = require('./version'),
	cached;

exports.detect = function (finished, opts) {
	if (process.platform != 'darwin') return finished();
	if (cached) return finished(cached);

	opts = opts || {};

	async.parallel([
		function (callback) {
			var searchDirs = ['/Developer'],
				xcodeInfo = {},
				xcodeBuildTasks = [];

			// first we build up a full list of places to check for xcodebuild
			fs.lstatSync('/Applications').isDirectory() && fs.readdirSync('/Applications').forEach(function (dir) {
				/^Xcode.*\.app$/.test(dir) && searchDirs.push('/Applications/' + dir + '/Contents/Developer');
			});
			fs.lstatSync('/Volumes').isDirectory() && fs.readdirSync('/Volumes').forEach(function (dir) {
				var vol = '/Volumes/' + dir;
				searchDirs.push(vol + '/Developer');
				afs.exists(vol + '/Applications') && fs.lstatSync(vol + '/Applications').isDirectory() && fs.readdirSync(vol + '/Applications').forEach(function (dir) {
					/^Xcode.*\.app$/.test(dir) && searchDirs.push(vol + '/Applications/' + dir + '/Contents/Developer');
				});
			});

			// TODO: try to use spotlight to find additional Xcode locations: "mdfind kMDItemDisplayName==Xcode&&kMDItemKind==Application"

			exec('xcode-select -print-path', function (err, stdout, stderr) {
				var selected = err ? '' : stdout.trim(),
					sdkRegExp = /^iPhone(OS|Simulator)(.+)\.sdk$/;

				searchDirs.indexOf(selected) == -1 && searchDirs.push(selected);

				function getSDKs() {
					var dir = path.join.apply(null, Array.prototype.slice.call(arguments)),
						vers = [];

					afs.exists(dir) && fs.readdirSync(dir).forEach(function (d) {
						if (fs.lstatSync(path.join(dir, d)).isDirectory()) {
							var m = d.match(sdkRegExp);
							m && (!opts.minSDK || version.gte(m[2], opts.minSDK)) && vers.push(m[2]);
						}
					});

					return vers;
				}

				async.parallel(searchDirs.sort().map(function (dir) {
					return function (cb) {
						var m = dir.match(/^(.+?\/Xcode.*\.app)\//),
							xcodeapp = m ? m[1] : path.join(dir, 'Applications', 'Xcode.app'),
							xcodebuild = path.join(dir, 'usr', 'bin', 'xcodebuild'),
							plistfile = path.join(path.dirname(dir), 'version.plist'),
							p, info, key;

						if (afs.exists(xcodebuild) && afs.exists(plistfile)) {
							p = new plist(plistfile);
							info = {
								path: dir,
								xcodeapp: xcodeapp,
								xcodebuild: xcodebuild,
								selected: dir == selected,
								version: p.CFBundleShortVersionString,
								build: p.ProductBuildVersion,
								sdks: null,
								sims: null
							};
							key = info.version + ':' + info.build;

							// if we already have this version of Xcode, ignore unless it's currently the selected version
							if (!xcodeInfo[key] || info.selected || dir <= xcodeInfo[key].path) {
								xcodeInfo[key] = info;
								info.selected && (xcodeInfo.__selected__ = info);
								info.sdks = getSDKs(dir, 'Platforms', 'iPhoneOS.platform', 'Developer', 'SDKs');
								info.sims = getSDKs(dir, 'Platforms', 'iPhoneSimulator.platform', 'Developer', 'SDKs');
							}
						}
						cb();
					};
				}), function () {
					callback(null, xcodeInfo);
				});
			});
		},

		function (callback) {
			exec('security dump-keychain', {
				maxBuffer: 1024 * 1024
			}, function (err, stdout, stderr) {
				var result = {
					devNames: [],
					distNames: [],
					wwdr: false
				};

				if (!err) {
					stdout.split('\n').forEach(function (line) {
						var m = line.match(/"iPhone Developer\: (.*)"/);
						if (m) {
							result.devNames[m[1].trim()] = 1;
						}

						m = line.match(/"iPhone Distribution\: (.*)"/);
						if (m) {
							result.distNames[m[1].trim()] = 1;
						}

						if (!result.wwdr && line.indexOf('Apple Worldwide Developer Relations Certification Authority') == -1) {
							result.wwdr = true;
						}
					});

					result.devNames = Object.keys(result.devNames).sort();
					result.distNames = Object.keys(result.distNames).sort();
				}

				callback(null, result);
			});
		},

		function (callback) {
			var dir = afs.resolvePath('~/Library/MobileDevice/Provisioning Profiles'),
				provisioningProfiles = {
					adhoc: [],
					enterprise: [],
					development: [],
					distribution: []
				};

			afs.exists(dir) && fs.readdirSync(dir).forEach(function (file) {
				if (/.+\.mobileprovision$/.test(file)) {
					var contents = fs.readFileSync(path.join(dir, file)).toString(),
						i = contents.indexOf('<?xml'),
						j = contents.lastIndexOf('</plist>'),
						p,
						dest = 'development',
						appPrefix,
						entitlements;

					if (i != -1 && j != -1) {
						p = new plist().parse(contents.substring(i, j + 8));
						appPrefix = (p.ApplicationIdentifierPrefix || []).shift();
						entitlements = p.Entitlements || {};

						if (!p.ProvisionedDevices || !p.ProvisionedDevices.length) {
							dest = 'distribution';
						} else if (new Buffer(p.DeveloperCertificates[0], 'base64').toString().indexOf('Distribution:') != -1) {
							dest = 'adhoc';
						}

						provisioningProfiles[dest].push({
							uuid: p.UUID,
							name: p.Name,
							appPrefix: appPrefix,
							appId: (entitlements['application-identifier'] || '').replace(appPrefix + '.', ''),
							getTaskAllow: entitlements['get-task-allow'] || '',
							apsEnvironment: entitlements['aps-environment'] || ''
						});
					}
				}
			});

			callback(null, provisioningProfiles);
		},

		function (callback) {
			var result = [];
			exec('security list-keychains', function (err, stdout, stderr) {
				if (!err) {
					result = result.concat(stdout.split('\n').filter(function (line) {
						var m = line.match(/[^"]*"([^"]*)"/);
						m && result.push(m[1].trim());
					}));
				}
			});
			callback(null, result);
		}

	], function (err, results) {
		finished(cached = {
			xcode: results[0],
			certs: results[1],
			provisioningProfiles: results[2],
			keychains: results[3]
		});
	});
};
<commit_msg>[TIMOB-12146] Fixed buffer size issues when ios library detects installed developer certs.<commit_after>/**
 * Appcelerator Common Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var child_process = require('child_process'),
	exec = child_process.exec,
	spawn = child_process.spawn,
	async = require('async'),
	path = require('path'),
	util = require('./util'),
	exception = require('./exception'),
	fs = require('fs'),
	afs = require('./fs'),
	plist = require('./plist'),
	version = require('./version'),
	cached;

exports.detect = function (finished, opts) {
	if (process.platform != 'darwin') return finished();
	if (cached) return finished(cached);

	opts = opts || {};

	async.parallel([
		function (callback) {
			var searchDirs = ['/Developer'],
				xcodeInfo = {},
				xcodeBuildTasks = [];

			// first we build up a full list of places to check for xcodebuild
			fs.lstatSync('/Applications').isDirectory() && fs.readdirSync('/Applications').forEach(function (dir) {
				/^Xcode.*\.app$/.test(dir) && searchDirs.push('/Applications/' + dir + '/Contents/Developer');
			});
			fs.lstatSync('/Volumes').isDirectory() && fs.readdirSync('/Volumes').forEach(function (dir) {
				var vol = '/Volumes/' + dir;
				searchDirs.push(vol + '/Developer');
				afs.exists(vol + '/Applications') && fs.lstatSync(vol + '/Applications').isDirectory() && fs.readdirSync(vol + '/Applications').forEach(function (dir) {
					/^Xcode.*\.app$/.test(dir) && searchDirs.push(vol + '/Applications/' + dir + '/Contents/Developer');
				});
			});

			// TODO: try to use spotlight to find additional Xcode locations: "mdfind kMDItemDisplayName==Xcode&&kMDItemKind==Application"

			exec('xcode-select -print-path', function (err, stdout, stderr) {
				var selected = err ? '' : stdout.trim(),
					sdkRegExp = /^iPhone(OS|Simulator)(.+)\.sdk$/;

				searchDirs.indexOf(selected) == -1 && searchDirs.push(selected);

				function getSDKs() {
					var dir = path.join.apply(null, Array.prototype.slice.call(arguments)),
						vers = [];

					afs.exists(dir) && fs.readdirSync(dir).forEach(function (d) {
						if (fs.lstatSync(path.join(dir, d)).isDirectory()) {
							var m = d.match(sdkRegExp);
							m && (!opts.minSDK || version.gte(m[2], opts.minSDK)) && vers.push(m[2]);
						}
					});

					return vers;
				}

				async.parallel(searchDirs.sort().map(function (dir) {
					return function (cb) {
						var m = dir.match(/^(.+?\/Xcode.*\.app)\//),
							xcodeapp = m ? m[1] : path.join(dir, 'Applications', 'Xcode.app'),
							xcodebuild = path.join(dir, 'usr', 'bin', 'xcodebuild'),
							plistfile = path.join(path.dirname(dir), 'version.plist'),
							p, info, key;

						if (afs.exists(xcodebuild) && afs.exists(plistfile)) {
							p = new plist(plistfile);
							info = {
								path: dir,
								xcodeapp: xcodeapp,
								xcodebuild: xcodebuild,
								selected: dir == selected,
								version: p.CFBundleShortVersionString,
								build: p.ProductBuildVersion,
								sdks: null,
								sims: null
							};
							key = info.version + ':' + info.build;

							// if we already have this version of Xcode, ignore unless it's currently the selected version
							if (!xcodeInfo[key] || info.selected || dir <= xcodeInfo[key].path) {
								xcodeInfo[key] = info;
								info.selected && (xcodeInfo.__selected__ = info);
								info.sdks = getSDKs(dir, 'Platforms', 'iPhoneOS.platform', 'Developer', 'SDKs');
								info.sims = getSDKs(dir, 'Platforms', 'iPhoneSimulator.platform', 'Developer', 'SDKs');
							}
						}
						cb();
					};
				}), function () {
					callback(null, xcodeInfo);
				});
			});
		},

		function (callback) {
			var child = spawn('security', ['dump-keychain']),
				out = [],
				err = [];

			child.stdout.on('data', function (data) {
				out.push(data.toString());
			});

			child.stderr.on('data', function (data) {
				err.push(data.toString());
			});

			child.on('exit', function (code) {
				var result = {
					devNames: [],
					distNames: [],
					wwdr: false
				};

				if (code) {
					result.error = new exception('Failed during "security dump-keychain"', err.join('').split('\n'));
				} else {
					out.join('').split('\n').forEach(function (line) {
						var m = line.match(/"iPhone Developer\: (.*)"/);
						if (m) {
							result.devNames[m[1].trim()] = 1;
						}

						m = line.match(/"iPhone Distribution\: (.*)"/);
						if (m) {
							result.distNames[m[1].trim()] = 1;
						}

						if (!result.wwdr && line.indexOf('Apple Worldwide Developer Relations Certification Authority') == -1) {
							result.wwdr = true;
						}
					});

					result.devNames = Object.keys(result.devNames).sort();
					result.distNames = Object.keys(result.distNames).sort();
				}

				callback(null, result);
			});
		},

		function (callback) {
			var dir = afs.resolvePath('~/Library/MobileDevice/Provisioning Profiles'),
				provisioningProfiles = {
					adhoc: [],
					enterprise: [],
					development: [],
					distribution: []
				};

			afs.exists(dir) && fs.readdirSync(dir).forEach(function (file) {
				if (/.+\.mobileprovision$/.test(file)) {
					var contents = fs.readFileSync(path.join(dir, file)).toString(),
						i = contents.indexOf('<?xml'),
						j = contents.lastIndexOf('</plist>'),
						p,
						dest = 'development',
						appPrefix,
						entitlements;

					if (i != -1 && j != -1) {
						p = new plist().parse(contents.substring(i, j + 8));
						appPrefix = (p.ApplicationIdentifierPrefix || []).shift();
						entitlements = p.Entitlements || {};

						if (!p.ProvisionedDevices || !p.ProvisionedDevices.length) {
							dest = 'distribution';
						} else if (new Buffer(p.DeveloperCertificates[0], 'base64').toString().indexOf('Distribution:') != -1) {
							dest = 'adhoc';
						}

						provisioningProfiles[dest].push({
							uuid: p.UUID,
							name: p.Name,
							appPrefix: appPrefix,
							appId: (entitlements['application-identifier'] || '').replace(appPrefix + '.', ''),
							getTaskAllow: entitlements['get-task-allow'] || '',
							apsEnvironment: entitlements['aps-environment'] || ''
						});
					}
				}
			});

			callback(null, provisioningProfiles);
		},

		function (callback) {
			var result = [];
			exec('security list-keychains', function (err, stdout, stderr) {
				if (!err) {
					result = result.concat(stdout.split('\n').filter(function (line) {
						var m = line.match(/[^"]*"([^"]*)"/);
						m && result.push(m[1].trim());
					}));
				}
			});
			callback(null, result);
		}

	], function (err, results) {
		finished(cached = {
			xcode: results[0],
			certs: results[1],
			provisioningProfiles: results[2],
			keychains: results[3]
		});
	});
};
<|endoftext|>


<commit_before>/**
 * IRC Class
 *
 * @author      Michael Owens
 * @website     http://www.michaelowens.nl
 * @copyright   Michael Owens 2011
 *
 * @author      Shaun Walker
 * @website     http://www.theshaun.com
 * @copyright   Shaun Walker 2012
 */

var util = require('util'),
	net = require('net'),
	fs = require('fs'),
	path = require('path'),
	user = require ('./user' ),
	channel = require('./channel'),
	message = require('./message');

Irc = exports.Irc = function(config) {
	this.initialize(config);
};

util.inherits(Irc, process.EventEmitter);

Irc.prototype.initialize = function(config) {
	this.host = config.host;
	this.port = config.port;
	this.nick = config.nick;

	this.pass = config.pass;

	this.username = config.username;
	this.realname = config.realname;
	this.command = config.command;
	this.userchannels = config.channels;

	// carry over config object to allow plugins to access it
	this.config = config;

	// channel constructor and channel hash
	this.channelObj = channel.Channel;
	this.channels = {};

	// user constructor and user hash
	this.userObj = user.User;
	this.users = {};

	// hook and callback arrays
	this.hooks = [];
	this.triggers = [];
	this.replies = [];

	this.connection = null;
	this.buffer = "";
	this.encoding = "utf8";
	this.timeout = 60*60*1000;

	this.logger = config.logger;

	/*
	 * Boot Plugins
	 */
	this.plugins = [];

	this.logger.verbose('loading plugins: ');

	for(var i = 0, z = config.plugins.length; i < z; i++) {
		var p = config.plugins[i];
		this.logger.verbose('-- ' + p);
		this.loadPlugin(p);
	}
};

Irc.prototype.connect = function() {
	var c = this.connection = net.createConnection(this.port, this.host);
	c.setEncoding(this.encoding);
	c.setTimeout(this.timeout);

	this.initListeners();
};

Irc.prototype.dummyConnect = function(connection) {
	var c = this.connection = connection;

	this.initListeners();
}

Irc.prototype.initListeners = function() {
	this.addListener('connect', this.onConnect);
	this.addListener('data', this.onReceive);
	this.addListener('eof', this.onEOF);
	this.addListener('timeout', this.onTimeout);
	this.addListener('close', this.onClose);
}

Irc.prototype.disconnect = function(reason) {
	if (this.connection.readyState !== 'closed') {
		this.connection.close();
		this.logger.info('disconnected (' + reason + ')');
	}
};

Irc.prototype.onConnect = function() {
	this.logger.info('connected');

	if(this.zncIdent != '') {
		this.raw('PASS ' + this.zncIdent);
	}

	this.raw('NICK', this.nick);
	this.raw('USER', this.username, '0', '*', ':' + this.realname);

	this.emit('connect');
};

Irc.prototype.onReceive = function(chunk) {
	this.buffer += chunk;
	while(this.buffer) {
		var offset = this.buffer.indexOf("\r\n");
		if (offset < 0) {
			return;
		}

		var msg = this.buffer.slice(0, offset);
		this.buffer = this.buffer.slice(offset + 2);

		this.logger.verbose( "< " + msg);

		msg = new message.Message(msg);
		this.onMessage(msg);
	}
};

Irc.prototype.onMessage = function(msg) {
	this.logger.verbose('++ command: ' + msg.command);
	this.logger.verbose('++ rawCommand: '+ msg.rawCommand);
	this.logger.verbose('++ arguments: ' + msg.arguments);
	this.logger.verbose('++ prefix: ' + msg.prefix);
	this.logger.verbose('++ lastarg: ' + msg.lastarg);

	var target = msg.arguments[0], // target
		nick = (msg.user || '').toLowerCase(), // nick
		user = this.users[nick], // user
		m, // message
		command = msg.rawCommand, // command
		users = this.users; // user hash

	switch(true){
		case (command === 'PING'):
			this.raw('PONG', msg.arguments);
			break;

		case (command === 'PRIVMSG'):
			if (user) {
				user.update(msg.prefix);
			}
			// Look for triggers
			m = msg.arguments[1];
			if (m.substring( 0, 1 ) == this.command) {
				var trigger = m.split(' ' )[0].substring( 1, m.length);
				if (typeof this.triggers[trigger] != 'undefined') {
					var trig = this.triggers[trigger];

					trig.callback.apply(this.plugins[trig.plugin], arguments);
				}
			}
			if (user == this.nick) {
				// emit "privateMessage", if the message is send by the bot itself
				console.log("===========================privateMessage");
				this.emit('privateMessage', msg);
			} else {
				this.emit('message', msg);
			}
			break;

		case (command === 'JOIN'):
			if (user) {
				user.update(msg.prefix);
				user.join(target);
			} else {
				user = this.users[nick] = new this.userObj(this, nick);
			}
			user.join(target);

			this.emit('join', msg);
			break;

		case (command === 'PART'):
			if (user) {
				user.update(msg.prefix);
				user.part(target);
			}

			this.emit('part', msg);
			break;

		case (command === 'QUIT'):
			if (user) {
				user.update(msg.prefix);
				user.quit(msg)
			}

			this.emit('quit', msg);
			break;

		case (command === 'NICK'):
			if (user) {
				user.update(msg.prefix);
			}

			this.emit('nick', msg);
			break;

		case (/^\d+$/.test(command)):
			this.emit('numeric', msg);
			break;
	}

	this.emit(msg.command, msg);
	this.emit('data', msg);
};

Irc.prototype.onEOF = function() {
	this.disconnect('EOF');
};

Irc.prototype.onTimeout = function() {
	this.disconnect('timeout');
};

Irc.prototype.onClose = function() {
	this.disconnect('close');
};

Irc.prototype.raw = function(cmd) {
	if (this.connection.readyState !== "open") {
		return this.disconnect("cannot send with readyState " + this.connection.readyState);
	}

	var msg = Array.prototype.slice.call(arguments, 1).join(' ') + "\r\n";

	this.logger.verbose('>' + cmd + ' ' + msg);

	this.connection.write(cmd + " " + msg, this.encoding);
};

// public method to send PRIVMSG cleanly
Irc.prototype.send = function(target, msg) {
	msg = Array.prototype.slice.call(arguments, 1).join(' ') + "\r\n";

	if (arguments.length > 1) {
		this.raw('PRIVMSG', target, ':' + msg);
	}
};

// Overriden method of eventEmitter
Irc.prototype.addListener = function(ev, f) {
	var that = this;
	return this.connection.addListener(ev, (function() {
		return function() {
			f.apply(that, arguments);
		};
	})());
};

Irc.prototype.addPluginListener = function(plugin, ev, f) {
	this.logger.verbose('plugin ', plugin);
	this.logger.verbose('ev ', ev);

	if (typeof this.hooks[plugin ] == 'undefined') {
		this.logger.info('initialize hooks');
		this.hooks[plugin] = [];
	}

	var callback = (function() {
		return function() {
			this.logger.verbose('apply callback for plugin: ' + plugin + ' and event ' + ev + ' with arguments: ', arguments);
			f.apply(that, arguments);
		};
	})();

	this.hooks[plugin].push({event: ev, callback: callback});

	var that = this.plugins[plugin];
	return this.on(ev, callback);
};

Irc.prototype.unloadPlugin = function(name) {
	if (typeof this.plugins[name] != 'undefined') {
		delete this.plugins[name];

		if (typeof this.hooks[name] != 'undefined') {
			for(var hook in this.hooks[name]) {
				this.removeListener(this.hooks[name ][ hook ].event, this.hooks[ name ][ hook].callback);
			}
		}

		if (typeof this.replies[name] != 'undefined') {
			for(var reply in this.replies[name]) {
				this.removeListener(this.replies[name ][ reply ].event, this.replies[ name ][ reply].callback);
			}
		}

		for(var trig in this.triggers) {
			if (this.triggers[trig].plugin == name) {
				delete this.triggers[trig];
			}
		}

		var p = path.normalize(__dirname + '/../plugins/' + name);
		delete require.cache[p + '.js'];
	}
};

Irc.prototype.loadPlugin = function(name) {
	this.unloadPlugin(name);
	var that = this;

	try {
		this.logger.verbose('Loading Plugin: ', name);

		var p = require('../plugins/' + name);
		this.plugins[name] = new p.Plugin(this, name);

		/*
		 * Hooks
		 */
		['connect', 'data', 'numeric', 'message', 'join', 'part', 'quit', 'nick', 'privateMessage'].forEach(function(event) {
			var onEvent = 'on' + event.charAt(0).toUpperCase() + event.substr(1),
				callback = this.plugins[name][onEvent];

			if (typeof callback == 'function') {
				this.logger.verbose("adding event: ", onEvent);
				this.addPluginListener(name, event, callback);
			}
		}, this);

	} catch (err) {
		this.logger.error('Cannot load Plugin ' + name + ': ', err.message);
		throw 'Error loading plugin';
	}
};

Irc.prototype.addTrigger = function(plugin, trigger, callback) {
	if (typeof this.triggers[trigger] == 'undefined') {
		this.triggers[trigger] = { plugin: plugin.name, callback: callback};
	}
};
<commit_msg>fix changed config property<commit_after>/**
 * IRC Class
 *
 * @author      Michael Owens
 * @website     http://www.michaelowens.nl
 * @copyright   Michael Owens 2011
 *
 * @author      Shaun Walker
 * @website     http://www.theshaun.com
 * @copyright   Shaun Walker 2012
 */

var util = require('util'),
	net = require('net'),
	fs = require('fs'),
	path = require('path'),
	user = require ('./user' ),
	channel = require('./channel'),
	message = require('./message');

Irc = exports.Irc = function(config) {
	this.initialize(config);
};

util.inherits(Irc, process.EventEmitter);

Irc.prototype.initialize = function(config) {
	this.host = config.host;
	this.port = config.port;
	this.nick = config.nick;

	this.pass = config.pass;

	this.username = config.username;
	this.realname = config.realname;
	this.command = config.command;
	this.userchannels = config.channels;

	// carry over config object to allow plugins to access it
	this.config = config;

	// channel constructor and channel hash
	this.channelObj = channel.Channel;
	this.channels = {};

	// user constructor and user hash
	this.userObj = user.User;
	this.users = {};

	// hook and callback arrays
	this.hooks = [];
	this.triggers = [];
	this.replies = [];

	this.connection = null;
	this.buffer = "";
	this.encoding = "utf8";
	this.timeout = 60*60*1000;

	this.logger = config.logger;

	/*
	 * Boot Plugins
	 */
	this.plugins = [];

	this.logger.verbose('loading plugins: ');

	for(var i = 0, z = config.plugins.length; i < z; i++) {
		var p = config.plugins[i];
		this.logger.verbose('-- ' + p);
		this.loadPlugin(p);
	}
};

Irc.prototype.connect = function() {
	var c = this.connection = net.createConnection(this.port, this.host);
	c.setEncoding(this.encoding);
	c.setTimeout(this.timeout);

	this.initListeners();
};

Irc.prototype.dummyConnect = function(connection) {
	var c = this.connection = connection;

	this.initListeners();
}

Irc.prototype.initListeners = function() {
	this.addListener('connect', this.onConnect);
	this.addListener('data', this.onReceive);
	this.addListener('eof', this.onEOF);
	this.addListener('timeout', this.onTimeout);
	this.addListener('close', this.onClose);
}

Irc.prototype.disconnect = function(reason) {
	if (this.connection.readyState !== 'closed') {
		this.connection.close();
		this.logger.info('disconnected (' + reason + ')');
	}
};

Irc.prototype.onConnect = function() {
	this.logger.info('connected');

	if(this.pass != '') {
		this.raw('PASS ' + this.pass);
	}

	this.raw('NICK', this.nick);
	this.raw('USER', this.username, '0', '*', ':' + this.realname);

	this.emit('connect');
};

Irc.prototype.onReceive = function(chunk) {
	this.buffer += chunk;
	while(this.buffer) {
		var offset = this.buffer.indexOf("\r\n");
		if (offset < 0) {
			return;
		}

		var msg = this.buffer.slice(0, offset);
		this.buffer = this.buffer.slice(offset + 2);

		this.logger.verbose( "< " + msg);

		msg = new message.Message(msg);
		this.onMessage(msg);
	}
};

Irc.prototype.onMessage = function(msg) {
	this.logger.verbose('++ command: ' + msg.command);
	this.logger.verbose('++ rawCommand: '+ msg.rawCommand);
	this.logger.verbose('++ arguments: ' + msg.arguments);
	this.logger.verbose('++ prefix: ' + msg.prefix);
	this.logger.verbose('++ lastarg: ' + msg.lastarg);

	var target = msg.arguments[0], // target
		nick = (msg.user || '').toLowerCase(), // nick
		user = this.users[nick], // user
		command = msg.rawCommand, // command
		users = this.users; // user hash

	switch(true){
		case (command === 'PING'):
			this.raw('PONG', msg.arguments);
			break;

		case (command === 'PRIVMSG'):
			if (user) {
				user.update(msg.prefix);
			}
			// Look for triggers
			var m = msg.arguments[1];
			if (m.substring( 0, 1 ) == this.command) {
				var trigger = m.split(' ' )[0].substring( 1, m.length);
				if (typeof this.triggers[trigger] != 'undefined') {
					var trig = this.triggers[trigger];

					trig.callback.apply(this.plugins[trig.plugin], arguments);
				}
			}
			if (user == this.nick) {
				// emit "privateMessage", if the message is send by the bot itself
				console.log("===========================privateMessage");
				this.emit('privateMessage', msg);
			} else {
				this.emit('message', msg);
			}
			break;

		case (command === 'JOIN'):
			if (user) {
				user.update(msg.prefix);
				user.join(target);
			} else {
				user = this.users[nick] = new this.userObj(this, nick);
				user.join(target);
			}

			this.emit('join', msg);
			break;

		case (command === 'PART'):
			if (user) {
				user.update(msg.prefix);
				user.part(target);
			}

			this.emit('part', msg);
			break;

		case (command === 'QUIT'):
			if (user) {
				user.update(msg.prefix);
				user.quit(msg)
			}

			this.emit('quit', msg);
			break;

		case (command === 'NICK'):
			if (user) {
				user.update(msg.prefix);
			}

			this.emit('nick', msg);
			break;

		case (/^\d+$/.test(command)):
			this.emit('numeric', msg);
			break;
	}

	this.emit(msg.command, msg);
	this.emit('data', msg);
};

Irc.prototype.onEOF = function() {
	this.disconnect('EOF');
};

Irc.prototype.onTimeout = function() {
	this.disconnect('timeout');
};

Irc.prototype.onClose = function() {
	this.disconnect('close');
};

Irc.prototype.raw = function(cmd) {
	if (this.connection.readyState !== "open") {
		return this.disconnect("cannot send with readyState " + this.connection.readyState);
	}

	var msg = Array.prototype.slice.call(arguments, 1).join(' ') + "\r\n";

	this.logger.verbose('>' + cmd + ' ' + msg);

	this.connection.write(cmd + " " + msg, this.encoding);
};

// public method to send PRIVMSG cleanly
Irc.prototype.send = function(target, msg) {
	msg = Array.prototype.slice.call(arguments, 1).join(' ') + "\r\n";

	if (arguments.length > 1) {
		this.raw('PRIVMSG', target, ':' + msg);
	}
};

// Overriden method of eventEmitter
Irc.prototype.addListener = function(ev, f) {
	var that = this;
	return this.connection.addListener(ev, (function() {
		return function() {
			f.apply(that, arguments);
		};
	})());
};

Irc.prototype.addPluginListener = function(plugin, ev, f) {
	this.logger.verbose('plugin ', plugin);
	this.logger.verbose('ev ', ev);

	if (typeof this.hooks[plugin ] == 'undefined') {
		this.logger.info('initialize hooks');
		this.hooks[plugin] = [];
	}

	var callback = (function() {
		return function() {
			this.logger.verbose('apply callback for plugin: ' + plugin + ' and event ' + ev + ' with arguments: ', arguments);
			f.apply(that, arguments);
		};
	})();

	this.hooks[plugin].push({event: ev, callback: callback});

	var that = this.plugins[plugin];
	return this.on(ev, callback);
};

Irc.prototype.unloadPlugin = function(name) {
	if (typeof this.plugins[name] != 'undefined') {
		delete this.plugins[name];

		if (typeof this.hooks[name] != 'undefined') {
			for(var hook in this.hooks[name]) {
				this.removeListener(this.hooks[name ][ hook ].event, this.hooks[ name ][ hook].callback);
			}
		}

		if (typeof this.replies[name] != 'undefined') {
			for(var reply in this.replies[name]) {
				this.removeListener(this.replies[name ][ reply ].event, this.replies[ name ][ reply].callback);
			}
		}

		for(var trig in this.triggers) {
			if (this.triggers[trig].plugin == name) {
				delete this.triggers[trig];
			}
		}

		var p = path.normalize(__dirname + '/../plugins/' + name);
		delete require.cache[p + '.js'];
	}
};

Irc.prototype.loadPlugin = function(name) {
	this.unloadPlugin(name);
	var that = this;

	try {
		this.logger.verbose('Loading Plugin: ', name);

		var p = require('../plugins/' + name);
		this.plugins[name] = new p.Plugin(this, name);

		/*
		 * Hooks
		 */
		['connect', 'data', 'numeric', 'message', 'join', 'part', 'quit', 'nick', 'privateMessage'].forEach(function(event) {
			var onEvent = 'on' + event.charAt(0).toUpperCase() + event.substr(1),
				callback = this.plugins[name][onEvent];

			if (typeof callback == 'function') {
				this.logger.verbose("adding event: ", onEvent);
				this.addPluginListener(name, event, callback);
			}
		}, this);

	} catch (err) {
		this.logger.error('Cannot load Plugin ' + name + ': ', err.message);
		throw 'Error loading plugin';
	}
};

Irc.prototype.addTrigger = function(plugin, trigger, callback) {
	if (typeof this.triggers[trigger] == 'undefined') {
		this.triggers[trigger] = { plugin: plugin.name, callback: callback};
	}
};
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var async = require('async');
var colorize = require('./colorize');
var debug = require('debug')('strider-runner-core:job');
var shellQuote = require('shell-quote').quote;
var spawnNormal = require('./spawn-normal');
var text = require('../locales/en.json');
var utils = require('./utils');

// TODO: should these go in a strider-phases repo? centralize the constants
var PHASES = ['environment', 'prepare', 'test', 'deploy', 'cleanup'];

function getPath(path) {
  var envPath = process.env.path || process.env.Path || process.env.PATH;

  if (path) {
    var sep = process.platform === 'win32' ? ';' : ':';
    var joined = path.join(sep);

    if (joined) {
      return joined + sep + envPath;
    }
  }

  return envPath;
}

module.exports = Job;

// config:
// - baseDir - the directory to work in. The code gets cloned to baseDir/code
// - io - eventemitter for sending job status events
// - logger
// - log
// - error
// - pty
function Job(job, provider, plugins, config) {
  debug('Creating new job "' + job._id + '" for project "' + job.project.display_name + '" using provider "' + provider.id + '".');
  this.config = _.extend({
    spawn: spawnNormal,
    pty: false,
    env: {}
  }, config);

  if (this.config.pty) {
    debug('PTY has been disabled due to a bug in node core');
    this.config.pty = false;
  }

  this.io = config.io;
  this.job = job;
  this.id = job._id;
  this.provider = provider;
  this.plugins = plugins;
  this.logPrefix = colorize.job(this.id);
  this.phase = null;
  this.testcode = null;
  this.cancelled = false;
  this.commands = [];
  this.listen();
}

Job.prototype = {
  // public api
  run: function (done) {
    debug('Running job "' + this.id + '"...');

    var self = this;
    var dom = require('domain').create();

    // no plugins in use, nothing will happen. fail.
    if (!this.plugins.length) {
      return this.done({message: 'No plugins configured. Aborting'}, done);
    }

    // If the plugin has a listen function, execute it
    this.plugins.forEach(function (plugin) {
      if (plugin.listen) {
        var context = self.pluginContext(self.provider.id, _.cloneDeep(self.config.env), []);
        plugin.listen(self.io, context);
      }
    });

    if (this.job.fromStriderJson) {
      this.comment('Config merged from strider.json');
    }

    dom.on('error', function (err) {
      debug('domain error caught', err.message, err.stack);
      debug(err);
      dom.dispose();
      self.done(err, done);
    });

    dom.run(function () {
      self.phase = PHASES[0];
      self.runPhase(done);
    });
  },

  cancel: function () {
    if (this.cancelled) return;

    var self = this;

    debug('Cancelling job "' + this.id + '"...');

    this.cancelled = true;

    if (!this.commands.length) {
      return self.io.emit('job.cancelled', self.id);
    }

    this.commands.forEach(function (cmd) {
      debug('killing', cmd.cmd.command);
      cmd.proc.kill();
    });

    setTimeout(function () {
      self.io.emit('job.cancelled', self.id);
    }, 1000);
  },

  // private api
  listen: function () {
    var self = this;

    this.io.on('job.cancel', function (id) {
      debug('io cancel', id, self.id);

      if (self.id.toString() === id.toString()) {
        self.cancel();
      }
    });
  },

  done: function (err, done) {
    if (this.cancelled) {
      debug('"done" called but the job is cancelled. Not calling continuation');
      return;
    }

    done(err);
  },

  // command execution stuff

  comment: function (text, plugin) {
    debug('Job "' + this.id + '" comments:', plugin || '<no plugin>', text);
    this.status('command.comment', {
      comment: text,
      plugin: plugin,
      time: new Date()
    });
  },

  /* usage:   (cmd, [plugin,] next) -> next(exitCode)
   * or:      (options, [plugin,] next) -> next(exitCode)
   *
   * plugin:  the name of the plugin that intiated the command
   *
   * options:
   *     cmd: string or {command: str, args: [], screen: str}
   *     silent: don't status the output as it goes
   *     env: {}
   *     cwd: str
   *
   * cmd('echo "hey"', next)
   * cmd({command: 'echo secretpassword', screen: 'echo [pwd]'}, next)
   * cmd({command: 'echo', args: ['hello']}, next)
   * cmd({cmd: 'hey', env: {ONE: 2}}, next)
   */
  cmd: function (cmd, plugin, next) {
    if (arguments.length === 2) {
      next = plugin;
      plugin = null;
    }

    debug('Job "' + this.id + '" runs:', plugin, cmd);

    var self = this;
    var start = new Date();
    var options = {
      cwd: this.phase === 'environment' ? this.config.baseDir : this.config.dataDir,
      silent: false,
      detached: process.platform !== 'win32'
    };
    var std = {
      out: '',
      err: ''
    };

    cmd = utils.normalizeCmd(cmd, options);

    this.config.spawn(cmd.command, cmd.args, options, function (err, proc) {
      if (err) {
        if (err === 127) {
          return next(127, '', 'Command not found');
        }

        debug('fail!', err, cmd.command, cmd.args);
        return next(500, '', 'Unable to execude command :( ' + err);
      }

      proc.stdout.setEncoding('utf8');
      proc.stderr.setEncoding('utf8');

      proc.stdout.on('data', function (buf) {
        if (!options.silent) {
          self.status('stdout', buf);
        }

        std.out += buf;
      });

      proc.stderr.on('data', function (buf) {
        if (!options.silent) {
          self.status('stderr', buf);
        }

        std.err += buf;
      });

      proc.on('exit', function (exitCode) {
        var end = new Date();
        var elapsed = end.getTime() - start.getTime();

        // Uncomment to monitor job commands
        // self.log(util.format('command done %s %s; exit code %s; duration %s',
        // cmd.command, cmd.args, exitCode, elapsed))
        self.status('command.done', {
          exitCode: exitCode,
          time: end,
          elapsed: elapsed
        });

        var ind = -1;

        for (var i = 0; i < self.commands.length; i++) {
          if (self.commands[i].proc === proc) {
            ind = i;
            break;
          }
        }

        if (ind !== -1) {
          self.commands.splice(ind, 1);
        }

        next(exitCode, std.out, std.err);
      });

      proc.on('error', function () {
        // prevent node from throwing an error
      });

      var strCmd = shellQuote([cmd.command].concat(cmd.args));
      var display = cmd.screen || strCmd;

      this.status('command.start', {command: display, started: start, plugin: plugin, time: start});

      if (options.silent) {
        this.status('stdout', '[output suppressed]');
      }

      this.commands.push({
        cmd: {
          command: display,
          started: start,
          plugin: plugin,
          time: start
        },
        proc: proc
      });
    }.bind(this));
  },

  // job running stuff
  pluginContext: function (pluginName, env, path) {
    var self = this;
    var context = {
      status: this.status.bind(this),
      out: this.out.bind(this),

      comment: function (text) {
        self.comment(text, pluginName);
      },

      cmd: function (cmd, next) {
        if (typeof(cmd) === 'string' || cmd.command) {
          cmd = {cmd: cmd};
        }

        cmd.env = _.extend({}, env, {
          PATH: getPath(path),
          HOME: process.env.HOME || (process.env.HOMEDRIVE + process.env.HOMEPATH),
          LANG: process.env.LANG,
          SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
          PAAS_NAME: 'strider'
        }, cmd.env || {});

        return self.cmd(cmd, pluginName, next);
      },

      // update pluginData
      data: function (data, method, path) {
        self.status('plugin-data', {
          plugin: pluginName,
          data: data,
          method: method,
          path: path
        });
      },

      dataDir: this.config.dataDir,
      baseDir: this.config.baseDir,
      cacheDir: this.config.cacheDir,
      cachier: this.config.cachier(pluginName),
      io: this.io,

      plugin: pluginName,
      phase: this.phase,
      job: this.job,
      branch: this.job.ref.branch,
      project: this.project,

      runnerId: (
        this.config.branchConfig
        && this.config.branchConfig.runner
        && this.config.branchConfig.runner.id || 'unkown'
      )
    };

    return context;
  },

  // collect `env` from all plugins for the current phase, and execute
  // plugin.runPhase(context) for each plugin in series
  runPhase: function (next) {
    if (this.cancelled) return;

    var tasks = [];
    var started = new Date();
    var self = this;
    var path = [];
    var env = _.cloneDeep(this.config.env);

    // need to clone the repo first
    if (this.phase === 'prepare') {
      tasks.push(this.provider.fetch.bind(this.provider, self.pluginContext(this.provider.id, env, path)));
    }

    this.plugins.forEach(function (plugin) {
      // all plugins will get the final, fully populated env object
      _.extend(env, ('function' === typeof plugin.env) ? plugin.env(self.phase) : plugin.env);

      if ('string' === typeof plugin.path) {
        path.push(plugin.path);
      } else {
        path = path.concat('function' === typeof plugin.path ? plugin.path(self.phase) : plugin.path);
      }

      tasks.push(function (next) {
        utils.runPlugin(self.phase, plugin, self.pluginContext(plugin.id, env, path), next);
      });
    });

    async.series(tasks, this.phaseDone.bind(this, next, started));
  },

  // called on the completion (or erroring) of a phase
  phaseDone: function (next, started, err, actuallyRan) {
    /* jshint maxcomplexity: 11 */
    var code = 0;
    var now = new Date();

    if (err) {
      if (err.type === 'exitCode') code = err.code;
      if ('number' === typeof err) code = err;

      this.status('phase.errored', {
        time: now,
        exitCode: code
      });

      if (code === 0) {
        this.error(err);
        return this.done(err, next);
      }
    }
    // Complain if no plugins actually did anything during testing?
    // XXX: should this be a fail hard?
    if (['deploy', 'test'].indexOf(this.phase) !== -1 && utils.sum(actuallyRan) === 0) {
      this.out('Phase ' + this.phase + ' didn\'t actually run anything. Check your plugin configuration', 'warn');
    }

    if (this.phase === 'test') {
      this.status('tested', {time: now, exitCode: code});
    }

    if (this.phase === 'deploy') {
      this.status('deployed', {time: now, exitCode: code});
    }

    var nextPhase = PHASES[PHASES.indexOf(this.phase) + 1];

    if (code !== 0) {
      nextPhase = 'cleanup';
    } else if (nextPhase === 'deploy' && this.job.type !== 'TEST_AND_DEPLOY') {
      nextPhase = 'cleanup';
    }

    this.status('phase.done', {
      phase: this.phase,
      time: now,
      exitCode: code,
      next: nextPhase,
      elapsed: now.getTime() - started.getTime()
    });

    if (this.phase === 'cleanup') {
      return this.done(null, next);
    }

    this.phase = nextPhase;
    this.runPhase(next);
  },

  error: function (error, serverOnly) {
    debug('Job "' + this.id + '" errored:', error.message, error.stack);

    if (!serverOnly) {
      this.status('stderr', text.errorPleaseReport + '\n\n' + error.message + '\n\n' + error.stack);
    }
  },

  status: function (type) {
    if (this.cancelled) return false;

    debug('Job "' + this.id + '" status:', type, arguments);

    var args = [].slice.call(arguments, 1);

    this.io.emit.apply(this.io, ['job.status.' + type, this.id].concat(args));
  },

  out: function (text, type) {
    debug('Job "' + this.id + '" prints:', type, text);

    var dest = ['error', 'stderr', 'warn'].indexOf(type) !== -1 ? 'stderr' : 'stdout';

    text = (type && colorize[type]) ? colorize[type](text) : text;

    this.status(dest, text);
  }
};
<commit_msg>More logging<commit_after>'use strict';

var _ = require('lodash');
var async = require('async');
var colorize = require('./colorize');
var debug = require('debug')('strider-runner-core:job');
var shellQuote = require('shell-quote').quote;
var spawnNormal = require('./spawn-normal');
var text = require('../locales/en.json');
var utils = require('./utils');

// TODO: should these go in a strider-phases repo? centralize the constants
var PHASES = ['environment', 'prepare', 'test', 'deploy', 'cleanup'];

function getPath(path) {
  var envPath = process.env.path || process.env.Path || process.env.PATH;

  if (path) {
    var sep = process.platform === 'win32' ? ';' : ':';
    var joined = path.join(sep);

    if (joined) {
      return joined + sep + envPath;
    }
  }

  return envPath;
}

module.exports = Job;

// config:
// - baseDir - the directory to work in. The code gets cloned to baseDir/code
// - io - eventemitter for sending job status events
// - logger
// - log
// - error
// - pty
function Job(job, provider, plugins, config) {
  debug('Creating new job "' + job._id + '" for project "' + job.project.display_name + '" using provider "' + provider.id + '".');
  this.config = _.extend({
    spawn: spawnNormal,
    pty: false,
    env: {}
  }, config);

  if (this.config.pty) {
    debug('PTY has been disabled due to a bug in node core');
    this.config.pty = false;
  }

  this.io = config.io;
  this.job = job;
  this.id = job._id;
  this.provider = provider;
  this.plugins = plugins;
  this.logPrefix = colorize.job(this.id);
  this.phase = null;
  this.testcode = null;
  this.cancelled = false;
  this.commands = [];
  this.listen();
}

Job.prototype = {
  // public api
  run: function (done) {
    debug('Running job "' + this.id + '"...');

    var self = this;
    var dom = require('domain').create();

    // no plugins in use, nothing will happen. fail.
    if (!this.plugins.length) {
      return this.done({message: 'No plugins configured. Aborting'}, done);
    }

    // If the plugin has a listen function, execute it
    this.plugins.forEach(function (plugin) {
      if (plugin.listen) {
        var context = self.pluginContext(self.provider.id, _.cloneDeep(self.config.env), []);
        plugin.listen(self.io, context);
      }
    });

    if (this.job.fromStriderJson) {
      this.comment('Config merged from strider.json');
    }

    dom.on('error', function (err) {
      debug('domain error caught', err.message, err.stack);
      debug(err);
      dom.dispose();
      self.done(err, done);
    });

    dom.run(function () {
      self.phase = PHASES[0];
      self.runPhase(done);
    });
  },

  cancel: function () {
    if (this.cancelled) return;

    var self = this;

    debug('Cancelling job "' + this.id + '"...');

    this.cancelled = true;

    if (!this.commands.length) {
      return self.io.emit('job.cancelled', self.id);
    }

    this.commands.forEach(function (cmd) {
      debug('killing', cmd.cmd.command);
      cmd.proc.kill();
    });

    setTimeout(function () {
      self.io.emit('job.cancelled', self.id);
    }, 1000);
  },

  // private api
  listen: function () {
    var self = this;

    this.io.on('job.cancel', function (id) {
      debug('io cancel', id, self.id);

      if (self.id.toString() === id.toString()) {
        self.cancel();
      }
    });
  },

  done: function (err, done) {
    if (this.cancelled) {
      debug('"done" called but the job is cancelled. Not calling continuation');
      return;
    }

    done(err);
  },

  // command execution stuff

  comment: function (text, plugin) {
    debug('Job "' + this.id + '" comments:', plugin || '<no plugin>', text);
    this.status('command.comment', {
      comment: text,
      plugin: plugin,
      time: new Date()
    });
  },

  /* usage:   (cmd, [plugin,] next) -> next(exitCode)
   * or:      (options, [plugin,] next) -> next(exitCode)
   *
   * plugin:  the name of the plugin that intiated the command
   *
   * options:
   *     cmd: string or {command: str, args: [], screen: str}
   *     silent: don't status the output as it goes
   *     env: {}
   *     cwd: str
   *
   * cmd('echo "hey"', next)
   * cmd({command: 'echo secretpassword', screen: 'echo [pwd]'}, next)
   * cmd({command: 'echo', args: ['hello']}, next)
   * cmd({cmd: 'hey', env: {ONE: 2}}, next)
   */
  cmd: function (cmd, plugin, next) {
    if (arguments.length === 2) {
      next = plugin;
      plugin = null;
    }

    debug('Job "' + this.id + '" runs:', plugin, cmd);

    var self = this;
    var start = new Date();
    var options = {
      cwd: this.phase === 'environment' ? this.config.baseDir : this.config.dataDir,
      silent: false,
      detached: process.platform !== 'win32'
    };
    var std = {
      out: '',
      err: ''
    };

    cmd = utils.normalizeCmd(cmd, options);

    this.config.spawn(cmd.command, cmd.args, options, function (err, proc) {
      if (err) {
        if (err === 127) {
          return next(127, '', 'Command not found');
        }

        debug('fail!', err, cmd.command, cmd.args);
        return next(500, '', 'Unable to execude command :( ' + err);
      }

      proc.stdout.setEncoding('utf8');
      proc.stderr.setEncoding('utf8');

      proc.stdout.on('data', function (buf) {
        if (!options.silent) {
          self.status('stdout', buf);
        }

        std.out += buf;
      });

      proc.stderr.on('data', function (buf) {
        if (!options.silent) {
          self.status('stderr', buf);
        }

        std.err += buf;
      });

      proc.on('exit', function (exitCode) {
        var end = new Date();
        var elapsed = end.getTime() - start.getTime();

        // Uncomment to monitor job commands
        // self.log(util.format('command done %s %s; exit code %s; duration %s',
        // cmd.command, cmd.args, exitCode, elapsed))
        self.status('command.done', {
          exitCode: exitCode,
          time: end,
          elapsed: elapsed
        });

        var ind = -1;

        for (var i = 0; i < self.commands.length; i++) {
          if (self.commands[i].proc === proc) {
            ind = i;
            break;
          }
        }

        if (ind !== -1) {
          self.commands.splice(ind, 1);
        }

        next(exitCode, std.out, std.err);
      });

      proc.on('error', function () {
        // prevent node from throwing an error
      });

      var strCmd = shellQuote([cmd.command].concat(cmd.args));
      var display = cmd.screen || strCmd;

      this.status('command.start', {command: display, started: start, plugin: plugin, time: start});

      if (options.silent) {
        this.status('stdout', '[output suppressed]');
      }

      this.commands.push({
        cmd: {
          command: display,
          started: start,
          plugin: plugin,
          time: start
        },
        proc: proc
      });
    }.bind(this));
  },

  // job running stuff
  pluginContext: function (pluginName, env, path) {
    var self = this;
    var context = {
      status: this.status.bind(this),
      out: this.out.bind(this),

      comment: function (text) {
        self.comment(text, pluginName);
      },

      cmd: function (cmd, next) {
        if (typeof(cmd) === 'string' || cmd.command) {
          cmd = {cmd: cmd};
        }

        cmd.env = _.extend({}, env, {
          PATH: getPath(path),
          HOME: process.env.HOME || (process.env.HOMEDRIVE + process.env.HOMEPATH),
          LANG: process.env.LANG,
          SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK,
          PAAS_NAME: 'strider'
        }, cmd.env || {});

        return self.cmd(cmd, pluginName, next);
      },

      // update pluginData
      data: function (data, method, path) {
        self.status('plugin-data', {
          plugin: pluginName,
          data: data,
          method: method,
          path: path
        });
      },

      dataDir: this.config.dataDir,
      baseDir: this.config.baseDir,
      cacheDir: this.config.cacheDir,
      cachier: this.config.cachier(pluginName),
      io: this.io,

      plugin: pluginName,
      phase: this.phase,
      job: this.job,
      branch: this.job.ref.branch,
      project: this.project,

      runnerId: (
        this.config.branchConfig
        && this.config.branchConfig.runner
        && this.config.branchConfig.runner.id || 'unkown'
      )
    };

    return context;
  },

  // collect `env` from all plugins for the current phase, and execute
  // plugin.runPhase(context) for each plugin in series
  runPhase: function (next) {
    if (this.cancelled) return;

    debug('Running phase', this.phase);

    var tasks = [];
    var started = new Date();
    var self = this;
    var path = [];
    var env = _.cloneDeep(this.config.env);

    // need to clone the repo first
    if (this.phase === 'prepare') {
      tasks.push(this.provider.fetch.bind(this.provider, self.pluginContext(this.provider.id, env, path)));
    }

    this.plugins.forEach(function (plugin) {
      debug('Running plugin', plugin.id);
      // all plugins will get the final, fully populated env object
      _.extend(env, ('function' === typeof plugin.env) ? plugin.env(self.phase) : plugin.env);

      if ('string' === typeof plugin.path) {
        path.push(plugin.path);
      } else {
        path = path.concat('function' === typeof plugin.path ? plugin.path(self.phase) : plugin.path);
      }

      tasks.push(function (next) {
        utils.runPlugin(self.phase, plugin, self.pluginContext(plugin.id, env, path), next);
      });
    });

    async.series(tasks, this.phaseDone.bind(this, next, started));
  },

  // called on the completion (or erroring) of a phase
  phaseDone: function (next, started, err, actuallyRan) {
    /* jshint maxcomplexity: 11 */
    var code = 0;
    var now = new Date();

    if (err) {
      if (err.type === 'exitCode') code = err.code;
      if ('number' === typeof err) code = err;

      this.status('phase.errored', {
        time: now,
        exitCode: code
      });

      if (code === 0) {
        this.error(err);
        return this.done(err, next);
      }
    }
    // Complain if no plugins actually did anything during testing?
    // XXX: should this be a fail hard?
    if (['deploy', 'test'].indexOf(this.phase) !== -1 && utils.sum(actuallyRan) === 0) {
      this.out('Phase ' + this.phase + ' didn\'t actually run anything. Check your plugin configuration', 'warn');
    }

    if (this.phase === 'test') {
      this.status('tested', {time: now, exitCode: code});
    }

    if (this.phase === 'deploy') {
      this.status('deployed', {time: now, exitCode: code});
    }

    var nextPhase = PHASES[PHASES.indexOf(this.phase) + 1];

    if (code !== 0) {
      nextPhase = 'cleanup';
    } else if (nextPhase === 'deploy' && this.job.type !== 'TEST_AND_DEPLOY') {
      nextPhase = 'cleanup';
    }

    this.status('phase.done', {
      phase: this.phase,
      time: now,
      exitCode: code,
      next: nextPhase,
      elapsed: now.getTime() - started.getTime()
    });

    if (this.phase === 'cleanup') {
      return this.done(null, next);
    }

    this.phase = nextPhase;
    this.runPhase(next);
  },

  error: function (error, serverOnly) {
    debug('Job "' + this.id + '" errored:', error.message, error.stack);

    if (!serverOnly) {
      this.status('stderr', text.errorPleaseReport + '\n\n' + error.message + '\n\n' + error.stack);
    }
  },

  status: function (type) {
    if (this.cancelled) return false;

    debug('Job "' + this.id + '" status:', type, arguments);

    var args = [].slice.call(arguments, 1);

    this.io.emit.apply(this.io, ['job.status.' + type, this.id].concat(args));
  },

  out: function (text, type) {
    debug('Job "' + this.id + '" prints:', type, text);

    var dest = ['error', 'stderr', 'warn'].indexOf(type) !== -1 ? 'stderr' : 'stdout';

    text = (type && colorize[type]) ? colorize[type](text) : text;

    this.status(dest, text);
  }
};
<|endoftext|>


<commit_before>(function () {
    'use strict';

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll().then(function () {
                //#region scan badge handler
                $("#secureID").keydown(function (e) {
                    // F7 or enter key indicate end of scan
                    if (e.keyCode == 118 || e.keyCode == 13) {
                        checkInBadgeHandler();
                    }
                });
                //#endregion

                //#region manual check-in handlers
                $("#checkInButton").click(function () {
                    checkInButtonClickHandler();
                });

                // if enter key selected on #personID input
                $("#personID").keydown(function (e) {
                    if (e.keyCode == 13) {
                        checkInButtonClickHandler();
                    }
                });
                //#endregion

                updateCheckedInCount();
            }));
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state that needs to persist across suspensions here.
        // You might use the WinJS.Application.sessionState object, which is automatically saved and restored across suspension.
        // If you need to complete an asynchronous operation before your application is suspended, call args.setPromise().
    };

    var clearGreetingOutputTimer;

    function resetInputs() {
        $("#personID").val("");
        $("#secureID").val("");
        $("#secureID").focus();
    }

    function greetingOutput(string) {
        //remove timer to clear last set greeting
        clearTimeout(clearGreetingOutputTimer);

        //set greeting
        $("#greetingOutput").text(string);

        //set timer to clear greeting
        clearGreetingOutputTimer = setTimeout(function () {
            $("#greetingOutput").text("");
        }, 5000);
    }

    function welcomeGreeting(name) {
        var greetingString = "Hello, " + name + "!";
        greetingOutput(greetingString);
        resetInputs();
    }

    function errorGreeting() {
        var errorString = "An error has occurred, please try again";
        greetingOutput(errorString);
        resetInputs();
    }

    function updateCheckedInCount() {
        checkedInCount()
            .then(function (count) {
                $("#checkedInCount").text(count);
            });
    }

    function checkInBadgeHandler() {
        var secureID = $("#secureID").val();
        if (secureID) { //if valid, e.g. non-blank
            var person = secureID; //todo: lookup person
            var personID = null; //todo: lookup personID
            saveCheckIn(personID, secureID).then(function () {
                updateCheckedInCount();
                welcomeGreeting(person);
            });
        } else {
            errorGreeting();
        }
    }

    function checkInButtonClickHandler(eventInfo) {
        var personID = $("#personID").val();
        if (personID) { //if valid, e.g. non-blank
            var person = personID; //todo: lookup person
            saveCheckIn(personID).then(function () {
                updateCheckedInCount();
                welcomeGreeting(person);
            });
        } else {
            errorGreeting();
        }
    }

    app.start();
}());<commit_msg>only allow numbers<commit_after>(function () {
    'use strict';

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll().then(function () {
                //#region scan badge handler
                $("#secureID").keydown(function (e) {
                    // F7 or enter key indicate end of scan
                    if (e.keyCode == 118 || e.keyCode == 13) {
                        checkInBadgeHandler();
                    }
                });
                //#endregion

                //#region manual check-in handlers
                $("#checkInButton").click(function () {
                    checkInButtonClickHandler();
                });

                // if enter key selected on #personID input
                $("#personID").keydown(function (e) {
                    if (e.keyCode == 13) {
                        checkInButtonClickHandler();
                    }
                });
                //#endregion

                updateCheckedInCount();
            }));
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state that needs to persist across suspensions here.
        // You might use the WinJS.Application.sessionState object, which is automatically saved and restored across suspension.
        // If you need to complete an asynchronous operation before your application is suspended, call args.setPromise().
    };

    var clearGreetingOutputTimer;

    function resetInputs() {
        $("#personID").val("");
        $("#secureID").val("");
        $("#secureID").focus();
    }

    function greetingOutput(string) {
        //remove timer to clear last set greeting
        clearTimeout(clearGreetingOutputTimer);

        //set greeting
        $("#greetingOutput").text(string);

        //set timer to clear greeting
        clearGreetingOutputTimer = setTimeout(function () {
            $("#greetingOutput").text("");
        }, 5000);
    }

    function welcomeGreeting(name) {
        var greetingString = "Hello, " + name + "!";
        greetingOutput(greetingString);
        resetInputs();
    }

    function errorGreeting() {
        var errorString = "An error has occurred, please try again";
        greetingOutput(errorString);
        resetInputs();
    }

    function updateCheckedInCount() {
        checkedInCount()
            .then(function (count) {
                $("#checkedInCount").text(count);
            });
    }

    function checkInBadgeHandler() {
        var secureID = $("#secureID").val();
        if (secureID && $.isNumeric(secureID)) { //if valid, e.g. non-blank
            var person = secureID; //todo: lookup person
            var personID = null; //todo: lookup personID
            saveCheckIn(personID, secureID).then(function () {
                updateCheckedInCount();
                welcomeGreeting(person);
            });
        } else {
            errorGreeting();
        }
    }

    function checkInButtonClickHandler(eventInfo) {
        var personID = $("#personID").val();
        if (personID && $.isNumeric(personID)) { //if valid, e.g. non-blank
            var person = personID; //todo: lookup person
            saveCheckIn(personID).then(function () {
                updateCheckedInCount();
                welcomeGreeting(person);
            });
        } else {
            errorGreeting();
        }
    }

    app.start();
}());<|endoftext|>


<commit_before>'use strict';

var colors = {
    error: '\u001b[31m',
    warn: '\u001b[33m',
    normal: '\u001b[39m',
    srcy: '\u001b[32m'
};

module.exports = {

    error: function (msg) {
        this.log(colors.error + 'ERROR: ' + colors.normal + ' ' + msg);
    },

    warn: function (msg) {
        this.log(colors.warn + 'WARNING: ' + colors.normal + ' ' + msg);
    },

    info: function (msg) {
        console.log('    ', msg);
    },

    log: function (msg) {
        console.log(colors.srcy + 'Srcy ' + msg);
    }

};
<commit_msg>added success logging<commit_after>'use strict';

var colors = {
    error: '\u001b[31m',
    warn: '\u001b[33m',
    normal: '\u001b[39m',
    srcy: '\u001b[32m'
};

module.exports = {

    error: function (msg) {
        this.log(colors.error + 'ERROR: ' + colors.normal + ' ' + msg);
    },

    warn: function (msg) {
        this.log(colors.warn + 'WARNING: ' + colors.normal + ' ' + msg);
    },

    info: function (msg) {
        console.log('    ', msg);
    },

    success: function (msg) {
        this.log(colors.normal + msg);
    },

    log: function (msg) {
        console.log(colors.srcy + 'Srcy ' + msg);
    }

};
<|endoftext|>


<commit_before>'use strict';
module.exports = function(cb) {
  var svn = require('svn-interface');
  var clc = require('cli-color');
  // var color;

  var colorLog = function(log) {
    var output = {};
    for (var key in log) {
      switch (key) {
        case '_attribute':
          output.revision = clc.white(log[key].revision);
          break;
        case 'author':
          output.author = clc.xterm(227)(log[key]._text);
          break;
      }
    }

    return output;
  };
  // Clear the screen...
  console.log('\u001b[2J\u001b[0;0H');
  // ...then ask SVN for the status (what just run `svn status`
  // behind the scene).
  svn.log('', {'limit': 10}, function(err, res) {
    if (res.log.logentry) {
      var coloredLog;
      res.log.logentry.forEach(function(singleLog) {
        coloredLog = colorLog(singleLog);
        console.log(coloredLog.revision, coloredLog.author);
      });
    } else {
      console.log('\n\n');
      console.log(clc.xterm(200)('Error accessing the log...'));
      cb();
      return;
    }
  });

};
<commit_msg>:mailbox: rest of the log information rendered<commit_after>'use strict';
module.exports = function(cb) {
  var svn = require('svn-interface');
  var clc = require('cli-color');
  // var color;

  var colorLog = function(log) {
    var output = {};
    for (var key in log) {
      switch (key) {
        case '_attribute':
          output.revision = clc.white(log[key].revision);
          break;
        case 'author':
          output.author = clc.xterm(227)(log[key]._text);
          break;
        case 'date':
          log[key]._text = new Date(log[key]._text);
          output.date = clc.xterm(236)(log[key]._text);
          break;
        case 'msg':
          output.msg = clc.xterm(200)(log[key]._text);
          break;
      }
    }

    return output;
  };
  // Clear the screen...
  console.log('\u001b[2J\u001b[0;0H');
  // ...then ask SVN for the status (what just run `svn status`
  // behind the scene).
  svn.log('', {'limit': 5}, function(err, res) {
    if (res.log.logentry) {
      var coloredLog;
      res.log.logentry.forEach(function(singleLog) {
        coloredLog = colorLog(singleLog);
        console.log('Revision: ' + coloredLog.revision + ' from ' + coloredLog.date);
        console.log('By: ' + coloredLog.author);
        console.log('Message: ' + coloredLog.msg + '\n');
      });
      cb();
    } else {
      console.log('\n\n');
      console.log(clc.xterm(200)('Error accessing the log...'));
      cb();
      return;
    }
  });

};
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
var Store = require("./storage/file");

var Logger = module.exports;

/* Every line in the log should contain:
    * timestamp
    * public key of initiator
    * the action
    * the event's tag
*/
var messageTemplate = function (type, time, tag, info) {
    return JSON.stringify([type.toUpperCase(), time, tag, info]);
};

var noop = function () {};

var write = function (ctx, content) {
    if (!ctx.store) { return; }
    ctx.store.log(ctx.channelName, content, noop);
};

// various degrees of logging
const logLevels = Logger.levels = ['silly', 'verbose', 'debug', 'feedback', 'info', 'warn', 'error'];

var handlers = {
    silly: function (ctx, time, tag, info) {
        console.log('[SILLY]', time, tag, info);
    },
    debug: function (ctx, time, tag, info) {
        console.log('[DEBUG]', time, tag, info);
    },
    verbose: function (ctx, time, tag, info) {
        console.log('[VERBOSE]', time, tag, info);
    },
    feedback: function (ctx, time, tag, info) {
        console.log('[FEEDBACK]', time, tag, info);
    },
    info: function (ctx, time, tag, info) {
        console.info('[INFO]', time, tag, info);
    },
    warn: function (ctx, time, tag, info) {
        console.warn('[WARN]', time, tag, info);
    },
    error: function (ctx, time, tag, info) {
        console.error('[ERROR]', time, tag, info);
    }
};

var noop = function () {};

var createLogType = function (ctx, type) {
    if (logLevels.indexOf(type) < logLevels.indexOf(ctx.logLevel)) {
        return noop;
    }
    return function (tag, info) {
        if (ctx.shutdown) {
            throw new Error("Logger has been shut down!");
        }
        var time = new Date().toISOString();
        var content;
        try {
            content = messageTemplate(type, time, tag, info);
        } catch (e) {
            return;
        }
        if (ctx.logToStdout && typeof(handlers[type]) === 'function') {
            handlers[type](ctx, time, tag, info);
        }
        write(ctx, content);
    };
};

var createMethods = function (ctx) {
    var log = {};
    logLevels.forEach(function (type) {
        log[type] = createLogType(ctx, type);
    });
    return log;
};

Logger.create = function (config, cb) {
    if (typeof(config.logLevel) !== 'string') {
        config.logLevel = 'info';
    }

    var date = new Date();
    var launchTime = ('' + date.getUTCFullYear()).slice(-2) + date.toISOString();

    var ctx = {
        channelName: launchTime,
        logFeedback: Boolean(config.logFeedback),
        logLevel: config.logLevel,
        logToStdout: config.logToStdout,
    };

    if (!config.logPath) {
        console.log("No logPath configured. Logging to file disabled");
        var logger = createMethods(ctx);
        logger.shutdown = noop;
        return void cb(Object.freeze(logger));
    }

    Store.create({
        filePath: config.logPath,
    }, function (err, store) {
        if (err) {
            throw err;
        }
        ctx.store = store;
        var logger = createMethods(ctx);
        logger.shutdown = function () {
            delete ctx.store;
            ctx.shutdown = true;
            store.shutdown();
        };
        cb(Object.freeze(logger));
    });
};

<commit_msg>unify format of console output with stored logs<commit_after>/*jshint esversion: 6 */
var Store = require("./storage/file");

var Logger = module.exports;

/* Every line in the log should contain:
    * timestamp
    * public key of initiator
    * the action
    * the event's tag
*/
var messageTemplate = function (type, time, tag, info) {
    return JSON.stringify([type.toUpperCase(), time, tag, info]);
};

var noop = function () {};

var write = function (ctx, content) {
    if (!ctx.store) { return; }
    ctx.store.log(ctx.channelName, content, noop);
};

// various degrees of logging
const logLevels = Logger.levels = ['silly', 'verbose', 'debug', 'feedback', 'info', 'warn', 'error'];

var handlers = {};
['silly', 'debug', 'verbose', 'feedback', 'info'].forEach(function (level) {
    handlers[level] = function (ctx, content) { console.log(content); };
});
['warn', 'error'].forEach(function (level) {
    handlers[level] = function (ctx, content) { console.error(content); }
});

var noop = function () {};

var createLogType = function (ctx, type) {
    if (logLevels.indexOf(type) < logLevels.indexOf(ctx.logLevel)) {
        return noop;
    }
    return function (tag, info) {
        if (ctx.shutdown) {
            throw new Error("Logger has been shut down!");
        }
        var time = new Date().toISOString();
        var content;
        try {
            content = messageTemplate(type, time, tag, info);
        } catch (e) {
            return;
        }
        if (ctx.logToStdout && typeof(handlers[type]) === 'function') {
            handlers[type](ctx, content);
        }
        write(ctx, content);
    };
};

var createMethods = function (ctx) {
    var log = {};
    logLevels.forEach(function (type) {
        log[type] = createLogType(ctx, type);
    });
    return log;
};

Logger.create = function (config, cb) {
    if (typeof(config.logLevel) !== 'string') {
        config.logLevel = 'info';
    }

    var date = new Date();
    var launchTime = ('' + date.getUTCFullYear()).slice(-2) + date.toISOString();

    var ctx = {
        channelName: launchTime,
        logFeedback: Boolean(config.logFeedback),
        logLevel: config.logLevel,
        logToStdout: config.logToStdout,
    };

    if (!config.logPath) {
        console.log("No logPath configured. Logging to file disabled");
        var logger = createMethods(ctx);
        logger.shutdown = noop;
        return void cb(Object.freeze(logger));
    }

    Store.create({
        filePath: config.logPath,
    }, function (err, store) {
        if (err) {
            throw err;
        }
        ctx.store = store;
        var logger = createMethods(ctx);
        logger.shutdown = function () {
            delete ctx.store;
            ctx.shutdown = true;
            store.shutdown();
        };
        cb(Object.freeze(logger));
    });
};

<|endoftext|>