<commit_before>'use strict';

/**
 * Imports.
 */
const auth = require('koa-basic-auth');
const bodyParser = require('koa-bodyparser');
const http = require('http');
const Koa = require('koa');
const Router = require('koa-router');
const uuidV4 = require('uuid/v4');

const ApiWebController = require('./controllers/ApiWebController');
const config = require('../../config');
const Initializer = require('../lib/Initializer');
const ToolsWebController = require('./controllers/ToolsWebController');
const WebHooksWebController = require('./controllers/WebHooksWebController');

/**
 * Initializations.
 */
// Chdir to project root to ensure that relative paths work.
process.chdir(__dirname);

// Web server
const blinkWeb = new Koa();

// Setup web middleware.
blinkWeb.use(bodyParser());

// Set context id.
blinkWeb.use(async (ctx, next) => {
  ctx.id = ctx.id || uuidV4();
  await next();
  ctx.set('X-Request-Id', ctx.id);
});

// Setup web server env from local config.
blinkWeb.env = config.app.env;

// Authentication
// Custom 401 handling
blinkWeb.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    if (err.status === 401) {
      ctx.status = 401;
      ctx.set('WWW-Authenticate', 'Basic');
      // Doctor Who Easter Egg
      // Copyright info: http://tardis.wikia.com/wiki/File:Angel_bares_fangs.jpg
      ctx.set('Content-type', 'text/html');
      ctx.body = 'Don\'t blink!
';
    } else {
      throw err;
    }
  }
});
blinkWeb.use(auth({ name: config.app.auth.name, pass: config.app.auth.password }));

// Setup dependencies.
const router = new Router();
config.router = router;
config.initializer = new Initializer(config);

config.initializer.getExchange();
config.initializer.getFetchQ();
config.initializer.getCustomerIoWebhookQ();

/**
 * Initialize all web controllers.
 */
const apiWebController = new ApiWebController(config);
const toolsWebController = new ToolsWebController(config);
const webHooksWebController = new WebHooksWebController(config);

/**
 * Routing.
 */
router.get('/', async (ctx) => {
  ctx.body = 'Hi, I\'m Blink!';
});
router.get('api.index', '/api', apiWebController.index);
router.get('api.v1', '/api/v1', ApiWebController.v1);
router.get('api.v1.tools', '/api/v1/tools', toolsWebController.index);
router.post('api.v1.tools.fetch', '/api/v1/tools/fetch', toolsWebController.fetch);
router.get('api.v1.webhooks', '/api/v1/webhooks', webHooksWebController.index);
router.post('api.v1.webhooks.customerio', '/api/v1/webhooks/customerio', webHooksWebController.customerio);

blinkWeb
  .use(router.routes())
  .use(router.allowedMethods());

/**
 * Create server.
 */
const server = http.createServer(blinkWeb.callback());
server.listen(config.web.bind_port, config.web.bind_address, () => {
  const address = server.address();
  // Make sure random port setting gets overriden with actual resolved port.
  config.web.bind_port = address.port;
  config.logger.info(
    `Blink is listening on http://${config.web.hostname}:${config.web.bind_port} env:${config.app.env}`
  );
});

module.exports = blinkWeb;
<commit_msg>Fix variable name mistake<commit_after>'use strict';

/**
 * Imports.
 */
const auth = require('koa-basic-auth');
const bodyParser = require('koa-bodyparser');
const http = require('http');
const Koa = require('koa');
const Router = require('koa-router');
const uuidV4 = require('uuid/v4');

const ApiWebController = require('./controllers/ApiWebController');
const config = require('../../config');
const Initializer = require('../lib/Initializer');
const ToolsWebController = require('./controllers/ToolsWebController');
const WebHooksWebController = require('./controllers/WebHooksWebController');

/**
 * Initializations.
 */
// Chdir to project root to ensure that relative paths work.
process.chdir(__dirname);

// Web server
const blinkWeb = new Koa();

// Setup web middleware.
blinkWeb.use(bodyParser());

// Set context id.
blinkWeb.use(async (ctx, next) => {
  ctx.id = ctx.id || uuidV4();
  await next();
  ctx.set('X-Request-Id', ctx.id);
});

// Setup web server env from local config.
blinkWeb.env = config.app.env;

// Authentication
// Custom 401 handling
blinkWeb.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    if (err.status === 401) {
      ctx.status = 401;
      ctx.set('WWW-Authenticate', 'Basic');
      // Doctor Who Easter Egg
      // Copyright info: http://tardis.wikia.com/wiki/File:Angel_bares_fangs.jpg
      ctx.set('Content-type', 'text/html');
      ctx.body = 'Don\'t blink!
';
    } else {
      throw err;
    }
  }
});
blinkWeb.use(auth({ name: config.app.auth.name, pass: config.app.auth.password }));

// Setup dependencies.
const router = new Router();
config.router = router;
config.initializer = new Initializer(config);

config.initializer.getExchange();
config.initializer.getFetchQ();
config.initializer.getCustomerIoWebhookQ();

/**
 * Initialize all web controllers.
 */
const apiWebController = new ApiWebController(config);
const toolsWebController = new ToolsWebController(config);
const webHooksWebController = new WebHooksWebController(config);

/**
 * Routing.
 */
router.get('/', async (ctx) => {
  ctx.body = 'Hi, I\'m Blink!';
});
router.get('api.index', '/api', apiWebController.index);
router.get('api.v1', '/api/v1', apiWebController.v1);
router.get('api.v1.tools', '/api/v1/tools', toolsWebController.index);
router.post('api.v1.tools.fetch', '/api/v1/tools/fetch', toolsWebController.fetch);
router.get('api.v1.webhooks', '/api/v1/webhooks', webHooksWebController.index);
router.post('api.v1.webhooks.customerio', '/api/v1/webhooks/customerio', webHooksWebController.customerio);

blinkWeb
  .use(router.routes())
  .use(router.allowedMethods());

/**
 * Create server.
 */
const server = http.createServer(blinkWeb.callback());
server.listen(config.web.bind_port, config.web.bind_address, () => {
  const address = server.address();
  // Make sure random port setting gets overriden with actual resolved port.
  config.web.bind_port = address.port;
  config.logger.info(
    `Blink is listening on http://${config.web.hostname}:${config.web.bind_port} env:${config.app.env}`
  );
});

module.exports = blinkWeb;
<|endoftext|>


<commit_before>'use babel';

import fs from 'fs';
import path from 'path';
import { CompositeDisposable } from 'atom';

export default {

	mapMenuItems(items) {

		return items.map(function(item) {
			return {
				label: "Packages",
				submenu: [{
					label: "collaby",
					submenu: [{
						label: item.label,
						command: item.command
					}]
				}]
			};
		});

	},

	addMenuItems(...items) {
		atom.menu.add(this.mapMenuItems(items));
	},

	removeMenuItems(...items) {
		atom.menu.remove(this.mapMenuItems(items));
	},

	recSingleScan(name, filePath) {
		let output = null;
		let stat = fs.statSync(filePath);

		if (stat.isDirectory()) {
			output = {name: name, type: "directory", stats: stat, path: filePath, content: this.recScan(filePath)};
		} else {
			output = {name: name, type: "file", stats: stat, path: filePath};
		}

		return output;
	},

	recScan(scanPath) {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));
		let arr = {};

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			arr[file] = this.recSingleScan(file, filePath);
		}

		return arr;

	},

	recScanCb(scanPath, cb, rPath = "") {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			let stat = fs.statSync(filePath);

			if (stat.isDirectory()) {
				this.recScanCb(filePath, cb, rPath + path.sep + file);
			} else {
				cb({file: file, filePath: filePath, stat: stat, relPath: rPath + path.sep + file});
			}
		}

	},

	deepDiff(o1, o2) {

		function diffServer(o1, o2, rPath = "") {

			let diff = new Array();

			// Check all server files
			for (let key in o1) {
				let objS = o1[key];

				objS.path = this.normalizeSeperators(objS.path);

				// First check if file or directory exists on client
				if (!o2.hasOwnProperty(key)) {
					console.log("path " + objS.path + " not available on client");
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				// Check if the types are the same
				let objC = o2[key];

				// Then check if the types are the same
				if (objC.type != objS.type) {
					console.log("type is different.. unlinking " + objC.path);
					fs.unlink(objC.path, function(err) {
						console.log("error with unlinking file ", err);
					});
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				if (objS.type == "file") {
					let timeS = new Date(objS.stats.ctime);
					let timeC = new Date(objC.stats.ctime);

					// Now check for size and time differences
					if (objC.stats.size != objS.stats.size || timeS.getTime() > timeC.getTime()) {
						console.log("size is different (" + objS.path + ")");
						diff.push({path: objS.path, directory: false, relPath: rPath + path.sep + objS.name});
					}
				} else if (objS.type == "directory") {
					// Call self for deep checking
					let newDiff = diffServer(objS.content, objC.content, rPath + path.sep + objS.name);

					if (newDiff != null) {
						diff = diff.concat(newDiff);
					}
				}
			}

			return diff;
		}

		// Check client files
		// User should not have files, the server has -> delete them
		function diffClient(o1, o2) {

			for (let key in o2) {
				let objC = o2[key];

				objC.path = this.normalizeSeperators(objC.path);

				if (!o1.hasOwnProperty(key)) {
					console.log("deleting file " + objC.path);
					fs.unlink(objC.path);
					continue;
				}

				// If the object is a directory, call self for a deep check
				if (objC.type == "directory") {
					diffClient(objS.content, objC.content);
				}
			}
		}

		return diffServer(o1, o2);

	},

	mkDirRec(dir) {
		if (fs.existsSync(dir)) {
			return;
		}

		try {
			fs.mkdirSync(dir);
			console.log("created " + dir);
		} catch(err) {
			if (err.code == 'ENOENT') {
				this.mkDirRec(path.dirname(dir)); //create parent dir
				this.mkDirRec(dir); //create dir
			}
		}
	},

	getBufferOfFile(file) {
		let buf = null;

		let findBuffer = () => {
			for (b of atom.project.getBuffers()) {
				if (!b.file || !b.file.path) continue;

				if (file == b.file.path) return b;
			}
		};

		buf = findBuffer();

		if (buf) return buf;

		// if no buffer could be found, we try to open that file and search again
		atom.workspace.open(file, {activateItem: false});

		return findBuffer();

	},

	normalizeSeperators(p) {

		if (path.sep == "/") {
			// Mac, Linux -> replace windows separators
			return p.replace("/", path.sep);
		} else if (path.sep == "\\") {
			// Windows
			return p.replace("\\", path.sep);
		}

		return p;
	}

}
<commit_msg>Fixed path normalizing<commit_after>'use babel';

import fs from 'fs';
import path from 'path';
import { CompositeDisposable } from 'atom';

export default {

	mapMenuItems(items) {

		return items.map(function(item) {
			return {
				label: "Packages",
				submenu: [{
					label: "collaby",
					submenu: [{
						label: item.label,
						command: item.command
					}]
				}]
			};
		});

	},

	addMenuItems(...items) {
		atom.menu.add(this.mapMenuItems(items));
	},

	removeMenuItems(...items) {
		atom.menu.remove(this.mapMenuItems(items));
	},

	recSingleScan(name, filePath) {
		let output = null;
		let stat = fs.statSync(filePath);

		if (stat.isDirectory()) {
			output = {name: name, type: "directory", stats: stat, path: filePath, content: this.recScan(filePath)};
		} else {
			output = {name: name, type: "file", stats: stat, path: filePath};
		}

		return output;
	},

	recScan(scanPath) {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));
		let arr = {};

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			arr[file] = this.recSingleScan(file, filePath);
		}

		return arr;

	},

	recScanCb(scanPath, cb, rPath = "") {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			let stat = fs.statSync(filePath);

			if (stat.isDirectory()) {
				this.recScanCb(filePath, cb, rPath + path.sep + file);
			} else {
				cb({file: file, filePath: filePath, stat: stat, relPath: rPath + path.sep + file});
			}
		}

	},

	deepDiff(o1, o2) {

		function diffServer(o1, o2, rPath = "") {

			let diff = new Array();

			// Check all server files
			for (let key in o1) {
				let objS = o1[key];

				objS.path = this.normalizeSeperators(objS.path);

				// First check if file or directory exists on client
				if (!o2.hasOwnProperty(key)) {
					console.log("path " + objS.path + " not available on client");
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				// Check if the types are the same
				let objC = o2[key];

				// Then check if the types are the same
				if (objC.type != objS.type) {
					console.log("type is different.. unlinking " + objC.path);
					fs.unlink(objC.path, function(err) {
						console.log("error with unlinking file ", err);
					});
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				if (objS.type == "file") {
					let timeS = new Date(objS.stats.ctime);
					let timeC = new Date(objC.stats.ctime);

					// Now check for size and time differences
					if (objC.stats.size != objS.stats.size || timeS.getTime() > timeC.getTime()) {
						console.log("size is different (" + objS.path + ")");
						diff.push({path: objS.path, directory: false, relPath: rPath + path.sep + objS.name});
					}
				} else if (objS.type == "directory") {
					// Call self for deep checking
					let newDiff = diffServer(objS.content, objC.content, rPath + path.sep + objS.name);

					if (newDiff != null) {
						diff = diff.concat(newDiff);
					}
				}
			}

			return diff;
		}

		// Check client files
		// User should not have files, the server has -> delete them
		function diffClient(o1, o2) {

			for (let key in o2) {
				let objC = o2[key];

				objC.path = this.normalizeSeperators(objC.path);

				if (!o1.hasOwnProperty(key)) {
					console.log("deleting file " + objC.path);
					fs.unlink(objC.path);
					continue;
				}

				// If the object is a directory, call self for a deep check
				if (objC.type == "directory") {
					diffClient(objS.content, objC.content);
				}
			}
		}

		return diffServer(o1, o2);

	},

	mkDirRec(dir) {
		if (fs.existsSync(dir)) {
			return;
		}

		try {
			fs.mkdirSync(dir);
			console.log("created " + dir);
		} catch(err) {
			if (err.code == 'ENOENT') {
				this.mkDirRec(path.dirname(dir)); //create parent dir
				this.mkDirRec(dir); //create dir
			}
		}
	},

	getBufferOfFile(file) {
		let buf = null;

		let findBuffer = () => {
			for (b of atom.project.getBuffers()) {
				if (!b.file || !b.file.path) continue;

				if (file == b.file.path) return b;
			}
		};

		buf = findBuffer();

		if (buf) return buf;

		// if no buffer could be found, we try to open that file and search again
		atom.workspace.open(file, {activateItem: false});

		return findBuffer();

	},

	normalizeSeperators(p) {

		if (!p) return p;

		if (path.sep == "/") {
			// Mac, Linux -> replace windows separators
			return p.replace(/\\/g, path.sep);
		} else if (path.sep == "\\") {
			// Windows
			return p.replace(/\//g, path.sep);
		}

		return p;
	}

}
<|endoftext|>


<commit_before><commit_msg>super-project overhaul<commit_after><|endoftext|>


<commit_before>/*!
* deja
* Copyright(c) 2011 Mike Cantelon
* MIT Licensed
*/

var path = require('path')
  , fs = require('fs')
  , spawn = require('child_process').spawn

exports.getHomeEnvVarOrDie = function() {

  var home = process.env.HOME

  if (home === undefined) {
    console.log('Error: HOME environmental variable not defined.')
    process.exit(1)
  }

  return home
}

exports.whenDirectoryExists = function(directory, callback) {

  // attempt to make directory if it doesn't already exist
  try {
    fs.mkdirSync(directory, 0700)
  } catch(e) {}

  // if directory exists, run callback or die
  fs.exists(directory, function(exists) {

    if (exists) {
      callback()
    }
    else {
      console.log('Error: Could not create $HOME/.deja.')
    }
  })
}

exports.traverseDir = function(dir, callback) {

  fs.readdir(dir, function(err, children) {
    if (err) throw err
    children.forEach(callback)
  })
}

exports.findUnusedBasename = function(dejaHome, repoUrl, callback, counter) {

  counter = (counter == undefined) ? 0 : counter

  // strip ".git" and pad with counter if the basename's already been used
  var basename = path.basename(repoUrl, '.git')
  basename += (counter > 0) ? '_' + counter : ''

  fs.exists(dejaHome + '/' + basename, function(exists) {

    if (exists) {
      // recurse, increasing counter, if basename has already been used
      exports.findUnusedBasename(dejaHome, repoUrl, callback, counter + 1)
    }
    else {
      // provide callback with unused basename
      callback(basename)
    }
  })
}

exports.expandRepoUrl = function(config, repoUrl) {

  // default to Github if protocal not specified
  if (repoUrl.indexOf(':') == -1) {

    // if "username/repo" format not used, get from config
    if (repoUrl.indexOf('/') == -1) {

      if (config.github && config.github.user) {

        repoUrl = 'git@github.com:' + config.github.user + '/' + repoUrl
      }
      else {

        console.log('Error: Github repo name only specified, but no github user defined in $HOME/.gitconfig.')
        console.log('Set one with "git config --global github.user YOUR_USERNAME".')
        process.exit(1)
      }
    }
    else {

      repoUrl = 'git://github.com/' + repoUrl
    }
  }

  return repoUrl
}

exports.clone = function(repoUrl, pathToRepo, successCallback) {

  var clone = spawn('git', ['clone', repoUrl, pathToRepo])

  clone.on('exit', function(code) {

    if (code != 0) {

      console.log('Error: could not clone.')
      process.exit(code)
    }
    else {

      // check if the repo has submodules
      fs.exists(pathToRepo + '/.gitmodules', function(exists) {

        // if submodules found, initialize and update them
        if (exists) {

          console.log('Initializing and updating submodules...')
          process.chdir(pathToRepo)

          var submodules = spawn('git', ['submodule', 'update', '--init'])

          submodules.on('exit', function(code) {
            successCallback()
          })
        }
        else {

          successCallback()
        }
      })
    }
  })
}

function formatEntryAndInfo(entry, attributes) {

  var entry_info = ''
  entry_info += (attributes.length) ? ' [' : ''
  entry_info += attributes.join(', ')
  entry_info += (attributes.length) ? ']' : ''
  return entry + entry_info
}

exports.outputEntryAndInfo = function(entry, pathToRepo, pathToEntry) {

  fs.exists(pathToEntry, function(exists) {

    var attributes = []

    // if there's a corresponding entry in the home dir, let the user
    // know if it's unlinked or conflicts
    if (exists) {
      fs.lstat(pathToEntry, function(err, stats) {

        // if the home entry links back, display info
        if (stats.isSymbolicLink()) {

          // check if linking to a directory
          var repoEntryStats = fs.statSync(pathToRepo + '/' + entry)

          if (repoEntryStats.isDirectory()) {
            attributes.push('dir')
          }

          // get path link leads to
          var destPath = fs.readlinkSync(pathToEntry)

          if ((pathToRepo + '/' + entry) != destPath) {
            attributes.push('unlinked')
          }
        }
        else {
          // indicate the entry is a conflicting directory
          if (stats.isDirectory()) {
            attributes.push('dir')
          }
          attributes.push('conflicts')
        }

        console.log(formatEntryAndInfo(entry, attributes))
      })
    }
    else {
    // no corresponding entry in home dir, indicate it's unlinked
      fs.stat(pathToRepo + '/' + entry, function(err, stats) {

        if (stats.isDirectory()) {
          attributes.push('dir')
        }
        attributes.push('unlinked')

        console.log(formatEntryAndInfo(entry, attributes))
      })
    }
  })
}

exports.createSymlinkIfPathExists = function(symlinkPath, filePath) {

  fs.exists(symlinkPath, function(exists) {

    if (!exists) {

      console.log('  ' + symlinkPath + ' -> ' + filePath)
      fs.symlinkSync(filePath, symlinkPath)
    }
    else {

      console.log('  Skipped ' + filePath + ': already exists.')
    }
  })
}

exports.deleteSymlinksToRepo = function(home, pathToRepo) {

  exports.traverseDir(pathToRepo, function(entry) {

    var pathToEntry = home + '/' + entry

    fs.exists(pathToEntry, function(exists) {
      if (exists) {
        fs.lstat(pathToEntry, function(err, stats) {
          if (stats.isSymbolicLink()) {

            // get path link leads to
            var destPath = fs.readlinkSync(pathToEntry)

            if (destPath == pathToRepo + '/' + entry) {

              fs.unlink(pathToEntry, function (err) {
                if (err) {
                  console.log ('Error: Could not delete symlink ' + pathToEntry + '.')
                }
                else {
                  console.log('Deleted symlink ' + pathToEntry + '.')
                }
              })
            }
          }
        })
      }
    })
  })
}

exports.parseOutRepoAndSubdir = function(repo) {

  var pathData
    , subDir = ''

  // if repo contains slashes, then user wants to link a repo subdirectory
  if (repo.indexOf('/') != -1) {

    pathData = repo.split('/')
    repo = pathData.shift()
    subDir = pathData.join('/')
  }

  return {
    repo:   repo,
    subDir: subDir
  }
}

exports.spawnThenExit = function(params) {

  var env = (params.env) ? params.env : process.env

  process.stdin.pause()

  var job = spawn(params.command, params.arguments, {
    cwd: params.cwd,
    env: env,
    customFds: [
      0,
      1,
      2
    ]
  })

  job.on('exit', function(code) {

    process.stdin.resume()

    if (params.successMessage || params.errorMessage) {
      console.log(
        (code == 0)
          ? params.successMessage
          : params.errorMessage
      )
    }

    process.exit()
  })
}

exports.checkIfFileShouldBeIgnored = function(file, ignoreList) {

  var ignoreItem

  for(var index in ignoreList) {
    ignoreItem = new RegExp(ignoreList[index])
    if (file.match(ignoreItem)) {
      return true
    }
  }

  return false
}

exports.getIgnoreList = function(home, repo, callback) {

  var ignoreFilename = '.dejaignore'
    , pathToGlobalIgnore = home + '/' + ignoreFilename
    , pathToRepoIgnore = home + '/.deja/' + repo + '/' + ignoreFilename
    , homeIgnoreList
    , repoIgnoreList
    , ignoreList

  fs.exists(pathToGlobalIgnore, function(exists) {

    if (exists) {

      homeIgnoreList = exports.readIgnoreListFromFile(pathToGlobalIgnore)
    }

    fs.exists(pathToRepoIgnore, function(exists) {

      if (exists) {

        repoIgnoreList = exports.readIgnoreListFromFile(pathToRepoIgnore)
      }

      // merge two ignore lists
      ignoreList = homeIgnoreList || []

      if (repoIgnoreList) {
        for(var index in repoIgnoreList) {
          var ignoreItem = repoIgnoreList[index]
          if (ignoreList.indexOf(ignoreItem) == -1) {
            ignoreList.push(ignoreItem)
          }
        }
      }

      callback(ignoreList)
    })
  })
}

exports.readIgnoreListFromFile = function(file) {

  var lines = fs.readFileSync(file).toString().split("\n")
    , ignoreList = []
    , line

  for (var index in lines) {

    line = lines[index]

    // if line contains a comment, trim it off
    if (line.indexOf('#') != -1) {
      line = line.slice(0, line.indexOf('#'))
    }

    // trim blank space from start/end of line
    line = line.trim();

    // change file pattern to regex
    line = '^' + line.replace(/\*/g, '(.*)') + '$'

    // if pattern doesn't exist in ignore list, add it
    if (line != '' && ignoreList.indexOf(line) == -1) {
      ignoreList.push(line)
    }
  }

  return ignoreList
}
<commit_msg>Got rid of depricated warning.<commit_after>/*!
* deja
* Copyright(c) 2011 Mike Cantelon
* MIT Licensed
*/

var path = require('path')
  , fs = require('fs')
  , spawn = require('child_process').spawn

exports.getHomeEnvVarOrDie = function() {

  var home = process.env.HOME

  if (home === undefined) {
    console.log('Error: HOME environmental variable not defined.')
    process.exit(1)
  }

  return home
}

exports.whenDirectoryExists = function(directory, callback) {

  // attempt to make directory if it doesn't already exist
  try {
    fs.mkdirSync(directory, 0700)
  } catch(e) {}

  // if directory exists, run callback or die
  fs.exists(directory, function(exists) {

    if (exists) {
      callback()
    }
    else {
      console.log('Error: Could not create $HOME/.deja.')
    }
  })
}

exports.traverseDir = function(dir, callback) {

  fs.readdir(dir, function(err, children) {
    if (err) throw err
    children.forEach(callback)
  })
}

exports.findUnusedBasename = function(dejaHome, repoUrl, callback, counter) {

  counter = (counter == undefined) ? 0 : counter

  // strip ".git" and pad with counter if the basename's already been used
  var basename = path.basename(repoUrl, '.git')
  basename += (counter > 0) ? '_' + counter : ''

  fs.exists(dejaHome + '/' + basename, function(exists) {

    if (exists) {
      // recurse, increasing counter, if basename has already been used
      exports.findUnusedBasename(dejaHome, repoUrl, callback, counter + 1)
    }
    else {
      // provide callback with unused basename
      callback(basename)
    }
  })
}

exports.expandRepoUrl = function(config, repoUrl) {

  // default to Github if protocal not specified
  if (repoUrl.indexOf(':') == -1) {

    // if "username/repo" format not used, get from config
    if (repoUrl.indexOf('/') == -1) {

      if (config.github && config.github.user) {

        repoUrl = 'git@github.com:' + config.github.user + '/' + repoUrl
      }
      else {

        console.log('Error: Github repo name only specified, but no github user defined in $HOME/.gitconfig.')
        console.log('Set one with "git config --global github.user YOUR_USERNAME".')
        process.exit(1)
      }
    }
    else {

      repoUrl = 'git://github.com/' + repoUrl
    }
  }

  return repoUrl
}

exports.clone = function(repoUrl, pathToRepo, successCallback) {

  var clone = spawn('git', ['clone', repoUrl, pathToRepo])

  clone.on('exit', function(code) {

    if (code != 0) {

      console.log('Error: could not clone.')
      process.exit(code)
    }
    else {

      // check if the repo has submodules
      fs.exists(pathToRepo + '/.gitmodules', function(exists) {

        // if submodules found, initialize and update them
        if (exists) {

          console.log('Initializing and updating submodules...')
          process.chdir(pathToRepo)

          var submodules = spawn('git', ['submodule', 'update', '--init'])

          submodules.on('exit', function(code) {
            successCallback()
          })
        }
        else {

          successCallback()
        }
      })
    }
  })
}

function formatEntryAndInfo(entry, attributes) {

  var entry_info = ''
  entry_info += (attributes.length) ? ' [' : ''
  entry_info += attributes.join(', ')
  entry_info += (attributes.length) ? ']' : ''
  return entry + entry_info
}

exports.outputEntryAndInfo = function(entry, pathToRepo, pathToEntry) {

  fs.exists(pathToEntry, function(exists) {

    var attributes = []

    // if there's a corresponding entry in the home dir, let the user
    // know if it's unlinked or conflicts
    if (exists) {
      fs.lstat(pathToEntry, function(err, stats) {

        // if the home entry links back, display info
        if (stats.isSymbolicLink()) {

          // check if linking to a directory
          var repoEntryStats = fs.statSync(pathToRepo + '/' + entry)

          if (repoEntryStats.isDirectory()) {
            attributes.push('dir')
          }

          // get path link leads to
          var destPath = fs.readlinkSync(pathToEntry)

          if ((pathToRepo + '/' + entry) != destPath) {
            attributes.push('unlinked')
          }
        }
        else {
          // indicate the entry is a conflicting directory
          if (stats.isDirectory()) {
            attributes.push('dir')
          }
          attributes.push('conflicts')
        }

        console.log(formatEntryAndInfo(entry, attributes))
      })
    }
    else {
    // no corresponding entry in home dir, indicate it's unlinked
      fs.stat(pathToRepo + '/' + entry, function(err, stats) {

        if (stats.isDirectory()) {
          attributes.push('dir')
        }
        attributes.push('unlinked')

        console.log(formatEntryAndInfo(entry, attributes))
      })
    }
  })
}

exports.createSymlinkIfPathExists = function(symlinkPath, filePath) {

  fs.exists(symlinkPath, function(exists) {

    if (!exists) {

      console.log('  ' + symlinkPath + ' -> ' + filePath)
      fs.symlinkSync(filePath, symlinkPath)
    }
    else {

      console.log('  Skipped ' + filePath + ': already exists.')
    }
  })
}

exports.deleteSymlinksToRepo = function(home, pathToRepo) {

  exports.traverseDir(pathToRepo, function(entry) {

    var pathToEntry = home + '/' + entry

    fs.exists(pathToEntry, function(exists) {
      if (exists) {
        fs.lstat(pathToEntry, function(err, stats) {
          if (stats.isSymbolicLink()) {

            // get path link leads to
            var destPath = fs.readlinkSync(pathToEntry)

            if (destPath == pathToRepo + '/' + entry) {

              fs.unlink(pathToEntry, function (err) {
                if (err) {
                  console.log ('Error: Could not delete symlink ' + pathToEntry + '.')
                }
                else {
                  console.log('Deleted symlink ' + pathToEntry + '.')
                }
              })
            }
          }
        })
      }
    })
  })
}

exports.parseOutRepoAndSubdir = function(repo) {

  var pathData
    , subDir = ''

  // if repo contains slashes, then user wants to link a repo subdirectory
  if (repo.indexOf('/') != -1) {

    pathData = repo.split('/')
    repo = pathData.shift()
    subDir = pathData.join('/')
  }

  return {
    repo:   repo,
    subDir: subDir
  }
}

exports.spawnThenExit = function(params) {

  var env = (params.env) ? params.env : process.env

  process.stdin.pause()

  var job = spawn(params.command, params.arguments, {
    cwd: params.cwd,
    env: env,
    stdio: [
      0,
      1,
      2
    ]
  })

  job.on('exit', function(code) {

    process.stdin.resume()

    if (params.successMessage || params.errorMessage) {
      console.log(
        (code == 0)
          ? params.successMessage
          : params.errorMessage
      )
    }

    process.exit()
  })
}

exports.checkIfFileShouldBeIgnored = function(file, ignoreList) {

  var ignoreItem

  for(var index in ignoreList) {
    ignoreItem = new RegExp(ignoreList[index])
    if (file.match(ignoreItem)) {
      return true
    }
  }

  return false
}

exports.getIgnoreList = function(home, repo, callback) {

  var ignoreFilename = '.dejaignore'
    , pathToGlobalIgnore = home + '/' + ignoreFilename
    , pathToRepoIgnore = home + '/.deja/' + repo + '/' + ignoreFilename
    , homeIgnoreList
    , repoIgnoreList
    , ignoreList

  fs.exists(pathToGlobalIgnore, function(exists) {

    if (exists) {

      homeIgnoreList = exports.readIgnoreListFromFile(pathToGlobalIgnore)
    }

    fs.exists(pathToRepoIgnore, function(exists) {

      if (exists) {

        repoIgnoreList = exports.readIgnoreListFromFile(pathToRepoIgnore)
      }

      // merge two ignore lists
      ignoreList = homeIgnoreList || []

      if (repoIgnoreList) {
        for(var index in repoIgnoreList) {
          var ignoreItem = repoIgnoreList[index]
          if (ignoreList.indexOf(ignoreItem) == -1) {
            ignoreList.push(ignoreItem)
          }
        }
      }

      callback(ignoreList)
    })
  })
}

exports.readIgnoreListFromFile = function(file) {

  var lines = fs.readFileSync(file).toString().split("\n")
    , ignoreList = []
    , line

  for (var index in lines) {

    line = lines[index]

    // if line contains a comment, trim it off
    if (line.indexOf('#') != -1) {
      line = line.slice(0, line.indexOf('#'))
    }

    // trim blank space from start/end of line
    line = line.trim();

    // change file pattern to regex
    line = '^' + line.replace(/\*/g, '(.*)') + '$'

    // if pattern doesn't exist in ignore list, add it
    if (line != '' && ignoreList.indexOf(line) == -1) {
      ignoreList.push(line)
    }
  }

  return ignoreList
}
<|endoftext|>


<commit_before>'use strict';

var async = require('async'),
	glob = require('glob'),
	path = require('path'),
	fs = require('fs'),
	_ = require('underscore'),
	changeDetector = require('./utils/changeDetector'),
	defaults = {
		src: [],
		spritePath: '',
		stylesheetPath: '',
		layout: 'vertical',
		stylesheet: 'stylus',
		compositor: 'canvas',
		layoutOptions: {},
		compositorOptions: {},
		stylesheetOptions: {}
	};

function generateSprite(options, callback) {
	var layout,
		stylesheet,
		compositor,
		generatedLayout;

	options = options || {};
	callback = callback || function () {};

	_.defaults(options, defaults);

	// require the files if they are provided as strings
	layout = _.isString(options.layout) ? require(path.join(__dirname + '/layout', options.layout)) : options.layout;
	compositor = _.isString(options.compositor) ? require(path.join(__dirname + '/compositor', options.compositor)) : options.compositor;
	stylesheet = _.isString(options.stylesheet) ? require(path.join(__dirname + '/stylesheet', options.stylesheet)) : options.stylesheet;

	// do glob pattern matching
	async.map(options.src, glob, function (err, fileNames) {
		if (err) {
			callback(err);
			return;
		}

		// filter duplicates from glob pattern matching
		fileNames = _(fileNames).chain().flatten().uniq().value();

		async.waterfall([
			function (callback) {
				compositor.readImages(fileNames, callback);
			},
			function (images, callback) {
				layout(images, options.layoutOptions, callback);
			},
			function (newLayout, callback) {
				// store layout so it can be used for stylesheet generation
				generatedLayout = newLayout;
				compositor.render(generatedLayout, options.spritePath, options.outputOptions, callback);
			},
			function (callback) {
				stylesheet(generatedLayout, options.stylesheetPath, options.spritePath, options.stylesheetOptions, callback);
			}
		], function (err) {
			callback(err);
		});
	});
}

generateSprite.middleware = function (options) {
	var changes = changeDetector(options);

	return function (req, res, next) {
		changes.detect(function (err, changesDetected) {
			if (changesDetected) {
				generateSprite(options, function () {
					changes.register(function () {
						return next(err);
					});
				});
			} else {
				return next();
			}
		});
	};
};

module.exports = generateSprite;<commit_msg>dont do a require at generation time<commit_after>'use strict';

var async = require('async'),
	glob = require('glob'),
	path = require('path'),
	fs = require('fs'),
	_ = require('underscore'),
	changeDetector = require('./utils/changeDetector'),
	providedLayouts = {
		'diagonal': require('./layout/diagonal'),
		'horizontal': require('./layout/horizontal'),
		'vertical': require('./layout/vertical')
	},
	providedCompositors = {
		'canvas': require('./compositor/canvas')
	},
	providedStylesheets = {
		'css': require('./stylesheet/css'),
		'stylus': require('./stylesheet/stylus')
	},
	defaults = {
		src: [],
		spritePath: '',
		stylesheetPath: '',
		layout: 'vertical',
		stylesheet: 'stylus',
		compositor: 'canvas',
		layoutOptions: {},
		compositorOptions: {},
		stylesheetOptions: {}
	};

function generateSprite(options, callback) {
	var layout,
		stylesheet,
		compositor,
		generatedLayout;

	options = options || {};
	callback = callback || function () {};

	_.defaults(options, defaults);

	// require the files if they are provided as strings
	layout = _.isString(options.layout) ? providedLayouts[options.layout] : options.layout;
	compositor = _.isString(options.compositor) ? providedCompositors[options.compositor] : options.compositor;
	stylesheet = _.isString(options.stylesheet) ? providedStylesheets[options.stylesheet] : options.stylesheet;

	// do glob pattern matching
	async.map(options.src, glob, function (err, fileNames) {
		if (err) {
			callback(err);
			return;
		}

		// filter duplicates from glob pattern matching
		fileNames = _(fileNames).chain().flatten().uniq().value();

		async.waterfall([
			function (callback) {
				compositor.readImages(fileNames, callback);
			},
			function (images, callback) {
				layout(images, options.layoutOptions, callback);
			},
			function (newLayout, callback) {
				// store layout so it can be used for stylesheet generation
				generatedLayout = newLayout;
				compositor.render(generatedLayout, options.spritePath, options.outputOptions, callback);
			},
			function (callback) {
				stylesheet(generatedLayout, options.stylesheetPath, options.spritePath, options.stylesheetOptions, callback);
			}
		], function (err) {
			callback(err);
		});
	});
}

generateSprite.middleware = function (options) {
	var changes = changeDetector(options);

	return function (req, res, next) {
		changes.detect(function (err, changesDetected) {
			if (changesDetected) {
				generateSprite(options, function () {
					changes.register(function () {
						return next(err);
					});
				});
			} else {
				return next();
			}
		});
	};
};

module.exports = generateSprite;<|endoftext|>


<commit_before>'use babel';

import fs from 'fs';
import path from 'path';
import { CompositeDisposable } from 'atom';

export default {

	mapMenuItems(items) {

		return items.map(function(item) {
			return {
				label: "Packages",
				submenu: [{
					label: "collaby",
					submenu: [{
						label: item.label,
						command: item.command
					}]
				}]
			};
		});

	},

	addMenuItems(...items) {
		atom.menu.add(this.mapMenuItems(items));
	},

	removeMenuItems(...items) {
		atom.menu.remove(this.mapMenuItems(items));
	},

	recSingleScan(name, filePath) {
		let output = null;
		let stat = fs.statSync(filePath);

		if (stat.isDirectory()) {
			output = {name: name, type: "directory", stats: stat, path: filePath, content: this.recScan(filePath)};
		} else {
			output = {name: name, type: "file", stats: stat, path: filePath};
		}

		return output;
	},

	recScan(scanPath) {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));
		let arr = {};

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			arr[file] = this.recSingleScan(file, filePath);
		}

		return arr;

	},

	recScanCb(scanPath, cb, rPath = "") {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			let stat = fs.statSync(filePath);

			if (stat.isDirectory()) {
				this.recScanCb(filePath, cb, rPath + path.sep + file);
			} else {
				cb({file: file, filePath: filePath, stat: stat, relPath: rPath + path.sep + file});
			}
		}

	},

	deepDiff(o1, o2) {

		function diffServer(o1, o2, rPath = "") {

			let diff = new Array();

			// Check all server files
			for (let key in o1) {
				let objS = o1[key];

				objS.path = this.normalizeSeperators(objS.path);

				// First check if file or directory exists on client
				if (!o2.hasOwnProperty(key)) {
					console.log("path " + objS.path + " not available on client");
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				// Check if the types are the same
				let objC = o2[key];

				// Then check if the types are the same
				if (objC.type != objS.type) {
					console.log("type is different.. unlinking " + objC.path);
					fs.unlink(objC.path, function(err) {
						console.log("error with unlinking file ", err);
					});
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				if (objS.type == "file") {
					let timeS = new Date(objS.stats.ctime);
					let timeC = new Date(objC.stats.ctime);

					// Now check for size and time differences
					if (objC.stats.size != objS.stats.size || timeS.getTime() > timeC.getTime()) {
						console.log("size is different (" + objS.path + ")");
						diff.push({path: objS.path, directory: false, relPath: rPath + path.sep + objS.name});
					}
				} else if (objS.type == "directory") {
					// Call self for deep checking
					let newDiff = diffServer(objS.content, objC.content, rPath + path.sep + objS.name);

					if (newDiff != null) {
						diff = diff.concat(newDiff);
					}
				}
			}

			return diff;
		}

		// Check client files
		// User should not have files, the server has -> delete them
		function diffClient(o1, o2) {

			for (let key in o2) {
				let objC = o2[key];

				objC.path = this.normalizeSeperators(objC.path);

				if (!o1.hasOwnProperty(key)) {
					console.log("deleting file " + objC.path);
					fs.unlink(objC.path);
					continue;
				}

				// If the object is a directory, call self for a deep check
				if (objC.type == "directory") {
					diffClient(objS.content, objC.content);
				}
			}
		}

		return diffServer(o1, o2);

	},

	mkDirRec(dir) {
		if (fs.existsSync(dir)) {
			return;
		}

		try {
			fs.mkdirSync(dir);
			console.log("created " + dir);
		} catch(err) {
			if (err.code == 'ENOENT') {
				this.mkDirRec(path.dirname(dir)); //create parent dir
				this.mkDirRec(dir); //create dir
			}
		}
	},

	getBufferOfFile(file) {
		let buf = null;

		let findBuffer = () => {
			for (b of atom.project.getBuffers()) {
				if (!b.file || !b.file.path) continue;

				if (file == b.file.path) return b;
			}
		};

		buf = findBuffer();

		if (buf) return buf;

		// if no buffer could be found, we try to open that file and search again
		atom.workspace.open(file, {activateItem: false});

		return findBuffer();

	},

	normalizeSeperators(p) {

		if (!p || typeof(p) != "string") return p;

		if (path.sep == "/") {
			// Mac, Linux -> replace windows separators
			return p.replace(/\\/g, path.sep);
		} else if (path.sep == "\\") {
			// Windows
			return p.replace(/\//g, path.sep);
		}

		return p;
	}

}
<commit_msg>Fixed path normalizing again<commit_after>'use babel';

import fs from 'fs';
import path from 'path';
import { CompositeDisposable } from 'atom';

export default {

	mapMenuItems(items) {

		return items.map(function(item) {
			return {
				label: "Packages",
				submenu: [{
					label: "collaby",
					submenu: [{
						label: item.label,
						command: item.command
					}]
				}]
			};
		});

	},

	addMenuItems(...items) {
		atom.menu.add(this.mapMenuItems(items));
	},

	removeMenuItems(...items) {
		atom.menu.remove(this.mapMenuItems(items));
	},

	recSingleScan(name, filePath) {
		let output = null;
		let stat = fs.statSync(filePath);

		if (stat.isDirectory()) {
			output = {name: name, type: "directory", stats: stat, path: filePath, content: this.recScan(filePath)};
		} else {
			output = {name: name, type: "file", stats: stat, path: filePath};
		}

		return output;
	},

	recScan(scanPath) {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));
		let arr = {};

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			arr[file] = this.recSingleScan(file, filePath);
		}

		return arr;

	},

	recScanCb(scanPath, cb, rPath = "") {

		let files = fs.readdirSync(scanPath);
		let sFiles = files.filter(file => !atom.config.get("collaby.ignore").includes(file));

		for (file of sFiles) {
			let filePath = scanPath + path.sep + file;
			let stat = fs.statSync(filePath);

			if (stat.isDirectory()) {
				this.recScanCb(filePath, cb, rPath + path.sep + file);
			} else {
				cb({file: file, filePath: filePath, stat: stat, relPath: rPath + path.sep + file});
			}
		}

	},

	deepDiff(o1, o2) {

		diffServer = (o1, o2, rPath = "") => {

			let diff = new Array();

			// Check all server files
			for (let key in o1) {
				let objS = o1[key];

				objS.path = this.normalizeSeperators(objS.path);

				// First check if file or directory exists on client
				if (!o2.hasOwnProperty(key)) {
					console.log("path " + objS.path + " not available on client");
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				// Check if the types are the same
				let objC = o2[key];

				// Then check if the types are the same
				if (objC.type != objS.type) {
					console.log("type is different.. unlinking " + objC.path);
					fs.unlink(objC.path, function(err) {
						console.log("error with unlinking file ", err);
					});
					diff.push({path: objS.path, directory: objS.type == "directory", relPath: rPath + path.sep + objS.name });
					continue;
				}

				if (objS.type == "file") {
					let timeS = new Date(objS.stats.ctime);
					let timeC = new Date(objC.stats.ctime);

					// Now check for size and time differences
					if (objC.stats.size != objS.stats.size || timeS.getTime() > timeC.getTime()) {
						console.log("size is different (" + objS.path + ")");
						diff.push({path: objS.path, directory: false, relPath: rPath + path.sep + objS.name});
					}
				} else if (objS.type == "directory") {
					// Call self for deep checking
					let newDiff = diffServer(objS.content, objC.content, rPath + path.sep + objS.name);

					if (newDiff != null) {
						diff = diff.concat(newDiff);
					}
				}
			}

			return diff;
		}

		// Check client files
		// User should not have files, the server has -> delete them
		diffClient = (o1, o2) => {

			for (let key in o2) {
				let objC = o2[key];

				objC.path = this.normalizeSeperators(objC.path);

				if (!o1.hasOwnProperty(key)) {
					console.log("deleting file " + objC.path);
					fs.unlink(objC.path);
					continue;
				}

				// If the object is a directory, call self for a deep check
				if (objC.type == "directory") {
					diffClient(objS.content, objC.content);
				}
			}
		}

		// First check if the client has too much files
		diffClient(o1, o2);

		// Then get the files, the client needs from the server
		return diffServer(o1, o2);

	},

	mkDirRec(dir) {
		if (fs.existsSync(dir)) {
			return;
		}

		try {
			fs.mkdirSync(dir);
			console.log("created " + dir);
		} catch(err) {
			if (err.code == 'ENOENT') {
				this.mkDirRec(path.dirname(dir)); //create parent dir
				this.mkDirRec(dir); //create dir
			}
		}
	},

	getBufferOfFile(file) {
		let buf = null;

		let findBuffer = () => {
			for (b of atom.project.getBuffers()) {
				if (!b.file || !b.file.path) continue;

				if (file == b.file.path) return b;
			}
		};

		buf = findBuffer();

		if (buf) return buf;

		// if no buffer could be found, we try to open that file and search again
		atom.workspace.open(file, {activateItem: false});

		return findBuffer();

	},

	normalizeSeperators(p) {

		if (!p || typeof(p) != "string") return p;

		if (path.sep == "/") {
			// Mac, Linux -> replace windows separators
			return p.replace(/\\/g, path.sep);
		} else if (path.sep == "\\") {
			// Windows
			return p.replace(/\//g, path.sep);
		}

		return p;
	}

}
<|endoftext|>


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

  var root = this

  var HLP = {}, CryptoJS, BigInt
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = HLP = {}
    CryptoJS = require('../vendor/crypto.js')
    BigInt = require('../vendor/bigint.js')
  } else {
    if (root.OTR) root.OTR.HLP = HLP
    if (root.DSA) root.DSA.HLP = HLP
    CryptoJS = root.CryptoJS
    BigInt = root.BigInt
  }

  // data types (byte lengths)
  var DTS = {
      BYTE  : 1
    , SHORT : 2
    , INT   : 4
    , CTR   : 8
    , MAC   : 20
    , SIG   : 40
  }

  // otr message wrapper begin and end
  var WRAPPER_BEGIN = "?OTR"
    , WRAPPER_END   = "."

  var TWO = BigInt.str2bigInt('2', 10)

  HLP.debug = function (msg) {
    // used as HLP.debug.call(ctx, msg)
    if ( this.debug &&
         typeof this.debug !== 'function' &&
         typeof console !== 'undefined'
    ) console.log(msg)
  }

  HLP.extend = function (child, parent) {
    for (var key in parent) {
      if (Object.hasOwnProperty.call(parent, key))
        child[key] = parent[key]
    }
    function Ctor() { this.constructor = child }
    Ctor.prototype = parent.prototype
    child.prototype = new Ctor()
    child.__super__ = parent.prototype
  }

  // constant-time string comparison
  HLP.compare = function (str1, str2) {
    if (str1.length !== str2.length)
      return false
    var i = 0, result = 0
    for (; i < str1.length; i++)
      result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
    return result === 0
  }

  HLP.divMod = function (num, den, n) {
    return BigInt.multMod(num, BigInt.inverseMod(den, n), n)
  }

  HLP.subMod = function (one, two, n) {
    one = BigInt.mod(one, n)
    two = BigInt.mod(two, n)
    if (BigInt.greater(two, one)) one = BigInt.add(one, n)
    return BigInt.sub(one, two)
  }

  HLP.randomExponent = function () {
    return BigInt.randBigInt(1536)
  }

  HLP.smpHash = function (version, fmpi, smpi) {
    var sha256 = CryptoJS.algo.SHA256.create()
    sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(version, DTS.BYTE)))
    sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(fmpi)))
    if (smpi) sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(smpi)))
    var hash = sha256.finalize()
    return HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))
  }

  HLP.makeMac = function (aesctr, m) {
    var pass = CryptoJS.enc.Latin1.parse(m)
    var mac = CryptoJS.HmacSHA256(CryptoJS.enc.Latin1.parse(aesctr), pass)
    return HLP.mask(mac.toString(CryptoJS.enc.Latin1), 0, 160)
  }

  HLP.make1Mac = function (aesctr, m) {
    var pass = CryptoJS.enc.Latin1.parse(m)
    var mac = CryptoJS.HmacSHA1(CryptoJS.enc.Latin1.parse(aesctr), pass)
    return mac.toString(CryptoJS.enc.Latin1)
  }

  HLP.encryptAes = function (msg, c, iv) {
    var opts = {
        mode: CryptoJS.mode.CTR
      , iv: CryptoJS.enc.Latin1.parse(iv)
      , padding: CryptoJS.pad.NoPadding
    }
    var aesctr = CryptoJS.AES.encrypt(
        msg
      , CryptoJS.enc.Latin1.parse(c)
      , opts
    )
    var aesctr_decoded = CryptoJS.enc.Base64.parse(aesctr.toString())
    return CryptoJS.enc.Latin1.stringify(aesctr_decoded)
  }

  HLP.decryptAes = function (msg, c, iv) {
    msg = CryptoJS.enc.Latin1.parse(msg)
    var opts = {
        mode: CryptoJS.mode.CTR
      , iv: CryptoJS.enc.Latin1.parse(iv)
      , padding: CryptoJS.pad.NoPadding
    }
    return CryptoJS.AES.decrypt(
        CryptoJS.enc.Base64.stringify(msg)
      , CryptoJS.enc.Latin1.parse(c)
      , opts
    )
  }

  HLP.multPowMod = function (a, b, c, d, e) {
    return BigInt.multMod(BigInt.powMod(a, b, e), BigInt.powMod(c, d, e), e)
  }

  HLP.ZKP = function (v, c, d, e) {
    return BigInt.equals(c, HLP.smpHash(v, d, e))
  }

  // greater than, or equal
  HLP.GTOE = function (a, b) {
    return (BigInt.equals(a, b) || BigInt.greater(a, b))
  }

  HLP.between = function (x, a, b) {
    return (BigInt.greater(x, a) && BigInt.greater(b, x))
  }

  HLP.checkGroup = function (g, N_MINUS_2) {
    return HLP.GTOE(g, TWO) && HLP.GTOE(N_MINUS_2, g)
  }

  HLP.h1 = function (b, secbytes) {
    var sha1 = CryptoJS.algo.SHA1.create()
    sha1.update(CryptoJS.enc.Latin1.parse(b))
    sha1.update(CryptoJS.enc.Latin1.parse(secbytes))
    return (sha1.finalize()).toString(CryptoJS.enc.Latin1)
  }

  HLP.h2 = function (b, secbytes) {
    var sha256 = CryptoJS.algo.SHA256.create()
    sha256.update(CryptoJS.enc.Latin1.parse(b))
    sha256.update(CryptoJS.enc.Latin1.parse(secbytes))
    return (sha256.finalize()).toString(CryptoJS.enc.Latin1)
  }

  HLP.mask = function (bytes, start, n) {
    return bytes.substr(start / 8, n / 8)
  }

  HLP.twotothe = function (m) {
    var b = Math.floor(m / BigInt.bpe) + 2
    var t = new Array(b)
    for (var i = 0; i < b; i++) t[i] = 0
    t[b - 2] = 1 << (m % BigInt.bpe)
    return t
  }

  HLP.packBytes = function (val, bytes) {
    val = val.toString(16)
    var nex, res = ''  // big-endian, unsigned long
    for (; bytes > 0; bytes--) {
      nex = val.length ? val.substr(-2, 2) : '0'
      val = val.substr(0, val.length - 2)
      res = _toString(parseInt(nex, 16)) + res
    }
    return res
  }

  HLP.packINT = function (d) {
    return HLP.packBytes(d, DTS.INT)
  }

  HLP.packCtr = function (d) {
    return HLP.padCtr(HLP.packBytes(d, DTS.CTR))
  }

  HLP.padCtr = function (ctr) {
    return ctr + '\x00\x00\x00\x00\x00\x00\x00\x00'
  }

  HLP.unpackCtr = function (d) {
    d = HLP.toByteArray(d.substring(0, 8))
    return HLP.unpack(d)
  }

  HLP.unpack = function (arr) {
    arr.reverse()
    var val = 0, i = 0, len = arr.length
    for (; i < len; i++) {
      val += Math.pow(256, i) * arr[i]
    }
    return val
  }

  HLP.packData = function (d) {
    return HLP.packINT(d.length) + d
  }

  HLP.bigInt2bits = function (bi, pad) {
    pad || (pad = 0)
    bi = BigInt.dup(bi)
    var ba = ''
    while (!BigInt.isZero(bi)) {
      ba = _num2bin[bi[0] & 0xff] + ba
      BigInt.rightShift_(bi, 8)
    }
    while (ba.length < pad) {
      ba = '\x00' + ba
    }
    return ba
  }

  HLP.bits2bigInt = function (bits) {
    bits = HLP.toByteArray(bits)
    return HLP.retMPI(bits)
  }

  HLP.packMPI = function (mpi) {
    return HLP.packData(HLP.bigInt2bits(BigInt.trim(mpi, 0)))
  }

  HLP.packSHORT = function (short) {
    return HLP.packBytes(short, DTS.SHORT)
  }

  HLP.unpackSHORT = function (short) {
    short = HLP.toByteArray(short)
    return HLP.unpack(short)
  }

  HLP.packTLV = function (type, value) {
    return HLP.packSHORT(type) + HLP.packSHORT(value.length) + value
  }

  HLP.readLen = function (msg) {
    msg = HLP.toByteArray(msg.substring(0, 4))
    return HLP.unpack(msg)
  }

  HLP.readData = function (data) {
    var n = HLP.unpack(data.splice(0, 4))
    return [n, data]
  }

  HLP.retMPI = function (data) {
    var mpi = BigInt.str2bigInt('0', 10, data.length)
    data.forEach(function (d, i) {
      if (i) BigInt.leftShift_(mpi, 8)
      mpi[0] |= d
    })
    return mpi
  }

  HLP.readMPI = function (data) {
    data = HLP.toByteArray(data)
    data = HLP.readData(data)
    return HLP.retMPI(data[1])
  }

  HLP.packMPIs = function (arr) {
    return arr.reduce(function (prv, cur) {
      return prv + HLP.packMPI(cur)
    }, '')
  }

  HLP.unpackMPIs = function (num, mpis) {
    var i = 0, arr = []
    for (; i < num; i++) arr.push('MPI')
    return (HLP.splitype(arr, mpis)).map(function (m) {
      return HLP.readMPI(m)
    })
  }

  HLP.wrapMsg = function (msg, fs, v3, our_it, their_it) {
    msg = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg))
    msg = WRAPPER_BEGIN + ":" + msg + WRAPPER_END

    var its
    if (v3) {
      its = '|'
      its += (HLP.readLen(our_it)).toString(16)
      its += '|'
      its += (HLP.readLen(their_it)).toString(16)
    }

    if (!fs) return [null, msg]

    var n = Math.ceil(msg.length / fs)
    if (n > 65535) return ['Too many fragments']
    if (n == 1) return [null, msg]

    var k, bi, ei, frag, mf, mfs = []
    for (k = 1; k <= n; k++) {
      bi = (k - 1) * fs
      ei = k * fs
      frag = msg.slice(bi, ei)
      mf = WRAPPER_BEGIN
      if (v3) mf += its
      mf += ',' + k + ','
      mf += n + ','
      mf += frag + ','
      mfs.push(mf)
    }

    return [null, mfs]
  }

  HLP.splitype = function splitype(arr, msg) {
    var data = []
    arr.forEach(function (a) {
      var str
      switch (a) {
        case 'PUBKEY':
          str = splitype(['SHORT', 'MPI', 'MPI', 'MPI', 'MPI'], msg).join('')
          break
        case 'DATA':  // falls through
        case 'MPI':
          str = msg.substring(0, HLP.readLen(msg) + 4)
          break
        default:
          str = msg.substring(0, DTS[a])
      }
      data.push(str)
      msg = msg.substring(str.length)
    })
    return data
  }

  // https://github.com/msgpack/msgpack-javascript/blob/master/msgpack.js

  var _bin2num = {}
    , _num2bin = {}
    , _toString = String.fromCharCode

  var i = 0, v

  for (; i < 0x100; ++i) {
    v = _toString(i)
    _bin2num[v] = i  // "\00" -> 0x00
    _num2bin[i] = v  //     0 -> "\00"
  }

  for (i = 0x80; i < 0x100; ++i) {  // [Webkit][Gecko]
    _bin2num[_toString(0xf700 + i)] = i  // "\f780" -> 0x80
  }

  HLP.toByteArray = function (data) {
    var rv = [], bin2num = _bin2num, remain
      , ary = data.split("")
      , i = -1
      , iz

    iz = ary.length
    remain = iz % 8

    while (remain--) {
      ++i
      rv[i] = bin2num[ary[i]]
    }
    remain = iz >> 3
    while (remain--) {
      rv.push(bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]])
    }
    return rv
  }

}).call(this)<commit_msg>unpack faster<commit_after>;(function () {
  "use strict";

  var root = this

  var HLP = {}, CryptoJS, BigInt
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = HLP = {}
    CryptoJS = require('../vendor/crypto.js')
    BigInt = require('../vendor/bigint.js')
  } else {
    if (root.OTR) root.OTR.HLP = HLP
    if (root.DSA) root.DSA.HLP = HLP
    CryptoJS = root.CryptoJS
    BigInt = root.BigInt
  }

  // data types (byte lengths)
  var DTS = {
      BYTE  : 1
    , SHORT : 2
    , INT   : 4
    , CTR   : 8
    , MAC   : 20
    , SIG   : 40
  }

  // otr message wrapper begin and end
  var WRAPPER_BEGIN = "?OTR"
    , WRAPPER_END   = "."

  var TWO = BigInt.str2bigInt('2', 10)

  HLP.debug = function (msg) {
    // used as HLP.debug.call(ctx, msg)
    if ( this.debug &&
         typeof this.debug !== 'function' &&
         typeof console !== 'undefined'
    ) console.log(msg)
  }

  HLP.extend = function (child, parent) {
    for (var key in parent) {
      if (Object.hasOwnProperty.call(parent, key))
        child[key] = parent[key]
    }
    function Ctor() { this.constructor = child }
    Ctor.prototype = parent.prototype
    child.prototype = new Ctor()
    child.__super__ = parent.prototype
  }

  // constant-time string comparison
  HLP.compare = function (str1, str2) {
    if (str1.length !== str2.length)
      return false
    var i = 0, result = 0
    for (; i < str1.length; i++)
      result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
    return result === 0
  }

  HLP.divMod = function (num, den, n) {
    return BigInt.multMod(num, BigInt.inverseMod(den, n), n)
  }

  HLP.subMod = function (one, two, n) {
    one = BigInt.mod(one, n)
    two = BigInt.mod(two, n)
    if (BigInt.greater(two, one)) one = BigInt.add(one, n)
    return BigInt.sub(one, two)
  }

  HLP.randomExponent = function () {
    return BigInt.randBigInt(1536)
  }

  HLP.smpHash = function (version, fmpi, smpi) {
    var sha256 = CryptoJS.algo.SHA256.create()
    sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(version, DTS.BYTE)))
    sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(fmpi)))
    if (smpi) sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(smpi)))
    var hash = sha256.finalize()
    return HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))
  }

  HLP.makeMac = function (aesctr, m) {
    var pass = CryptoJS.enc.Latin1.parse(m)
    var mac = CryptoJS.HmacSHA256(CryptoJS.enc.Latin1.parse(aesctr), pass)
    return HLP.mask(mac.toString(CryptoJS.enc.Latin1), 0, 160)
  }

  HLP.make1Mac = function (aesctr, m) {
    var pass = CryptoJS.enc.Latin1.parse(m)
    var mac = CryptoJS.HmacSHA1(CryptoJS.enc.Latin1.parse(aesctr), pass)
    return mac.toString(CryptoJS.enc.Latin1)
  }

  HLP.encryptAes = function (msg, c, iv) {
    var opts = {
        mode: CryptoJS.mode.CTR
      , iv: CryptoJS.enc.Latin1.parse(iv)
      , padding: CryptoJS.pad.NoPadding
    }
    var aesctr = CryptoJS.AES.encrypt(
        msg
      , CryptoJS.enc.Latin1.parse(c)
      , opts
    )
    var aesctr_decoded = CryptoJS.enc.Base64.parse(aesctr.toString())
    return CryptoJS.enc.Latin1.stringify(aesctr_decoded)
  }

  HLP.decryptAes = function (msg, c, iv) {
    msg = CryptoJS.enc.Latin1.parse(msg)
    var opts = {
        mode: CryptoJS.mode.CTR
      , iv: CryptoJS.enc.Latin1.parse(iv)
      , padding: CryptoJS.pad.NoPadding
    }
    return CryptoJS.AES.decrypt(
        CryptoJS.enc.Base64.stringify(msg)
      , CryptoJS.enc.Latin1.parse(c)
      , opts
    )
  }

  HLP.multPowMod = function (a, b, c, d, e) {
    return BigInt.multMod(BigInt.powMod(a, b, e), BigInt.powMod(c, d, e), e)
  }

  HLP.ZKP = function (v, c, d, e) {
    return BigInt.equals(c, HLP.smpHash(v, d, e))
  }

  // greater than, or equal
  HLP.GTOE = function (a, b) {
    return (BigInt.equals(a, b) || BigInt.greater(a, b))
  }

  HLP.between = function (x, a, b) {
    return (BigInt.greater(x, a) && BigInt.greater(b, x))
  }

  HLP.checkGroup = function (g, N_MINUS_2) {
    return HLP.GTOE(g, TWO) && HLP.GTOE(N_MINUS_2, g)
  }

  HLP.h1 = function (b, secbytes) {
    var sha1 = CryptoJS.algo.SHA1.create()
    sha1.update(CryptoJS.enc.Latin1.parse(b))
    sha1.update(CryptoJS.enc.Latin1.parse(secbytes))
    return (sha1.finalize()).toString(CryptoJS.enc.Latin1)
  }

  HLP.h2 = function (b, secbytes) {
    var sha256 = CryptoJS.algo.SHA256.create()
    sha256.update(CryptoJS.enc.Latin1.parse(b))
    sha256.update(CryptoJS.enc.Latin1.parse(secbytes))
    return (sha256.finalize()).toString(CryptoJS.enc.Latin1)
  }

  HLP.mask = function (bytes, start, n) {
    return bytes.substr(start / 8, n / 8)
  }

  HLP.twotothe = function (m) {
    var b = Math.floor(m / BigInt.bpe) + 2
    var t = new Array(b)
    for (var i = 0; i < b; i++) t[i] = 0
    t[b - 2] = 1 << (m % BigInt.bpe)
    return t
  }

  HLP.packBytes = function (val, bytes) {
    val = val.toString(16)
    var nex, res = ''  // big-endian, unsigned long
    for (; bytes > 0; bytes--) {
      nex = val.length ? val.substr(-2, 2) : '0'
      val = val.substr(0, val.length - 2)
      res = _toString(parseInt(nex, 16)) + res
    }
    return res
  }

  HLP.packINT = function (d) {
    return HLP.packBytes(d, DTS.INT)
  }

  HLP.packCtr = function (d) {
    return HLP.padCtr(HLP.packBytes(d, DTS.CTR))
  }

  HLP.padCtr = function (ctr) {
    return ctr + '\x00\x00\x00\x00\x00\x00\x00\x00'
  }

  HLP.unpackCtr = function (d) {
    d = HLP.toByteArray(d.substring(0, 8))
    return HLP.unpack(d)
  }

  HLP.unpack = function (arr) {
    var val = 0, i = 0, len = arr.length
    for (; i < len; i++) {
      val = (val * 256) + arr[i]
    }
    return val
  }

  HLP.packData = function (d) {
    return HLP.packINT(d.length) + d
  }

  HLP.bigInt2bits = function (bi, pad) {
    pad || (pad = 0)
    bi = BigInt.dup(bi)
    var ba = ''
    while (!BigInt.isZero(bi)) {
      ba = _num2bin[bi[0] & 0xff] + ba
      BigInt.rightShift_(bi, 8)
    }
    while (ba.length < pad) {
      ba = '\x00' + ba
    }
    return ba
  }

  HLP.bits2bigInt = function (bits) {
    bits = HLP.toByteArray(bits)
    return HLP.retMPI(bits)
  }

  HLP.packMPI = function (mpi) {
    return HLP.packData(HLP.bigInt2bits(BigInt.trim(mpi, 0)))
  }

  HLP.packSHORT = function (short) {
    return HLP.packBytes(short, DTS.SHORT)
  }

  HLP.unpackSHORT = function (short) {
    short = HLP.toByteArray(short)
    return HLP.unpack(short)
  }

  HLP.packTLV = function (type, value) {
    return HLP.packSHORT(type) + HLP.packSHORT(value.length) + value
  }

  HLP.readLen = function (msg) {
    msg = HLP.toByteArray(msg.substring(0, 4))
    return HLP.unpack(msg)
  }

  HLP.readData = function (data) {
    var n = HLP.unpack(data.splice(0, 4))
    return [n, data]
  }

  HLP.retMPI = function (data) {
    var mpi = BigInt.str2bigInt('0', 10, data.length)
    data.forEach(function (d, i) {
      if (i) BigInt.leftShift_(mpi, 8)
      mpi[0] |= d
    })
    return mpi
  }

  HLP.readMPI = function (data) {
    data = HLP.toByteArray(data)
    data = HLP.readData(data)
    return HLP.retMPI(data[1])
  }

  HLP.packMPIs = function (arr) {
    return arr.reduce(function (prv, cur) {
      return prv + HLP.packMPI(cur)
    }, '')
  }

  HLP.unpackMPIs = function (num, mpis) {
    var i = 0, arr = []
    for (; i < num; i++) arr.push('MPI')
    return (HLP.splitype(arr, mpis)).map(function (m) {
      return HLP.readMPI(m)
    })
  }

  HLP.wrapMsg = function (msg, fs, v3, our_it, their_it) {
    msg = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg))
    msg = WRAPPER_BEGIN + ":" + msg + WRAPPER_END

    var its
    if (v3) {
      its = '|'
      its += (HLP.readLen(our_it)).toString(16)
      its += '|'
      its += (HLP.readLen(their_it)).toString(16)
    }

    if (!fs) return [null, msg]

    var n = Math.ceil(msg.length / fs)
    if (n > 65535) return ['Too many fragments']
    if (n == 1) return [null, msg]

    var k, bi, ei, frag, mf, mfs = []
    for (k = 1; k <= n; k++) {
      bi = (k - 1) * fs
      ei = k * fs
      frag = msg.slice(bi, ei)
      mf = WRAPPER_BEGIN
      if (v3) mf += its
      mf += ',' + k + ','
      mf += n + ','
      mf += frag + ','
      mfs.push(mf)
    }

    return [null, mfs]
  }

  HLP.splitype = function splitype(arr, msg) {
    var data = []
    arr.forEach(function (a) {
      var str
      switch (a) {
        case 'PUBKEY':
          str = splitype(['SHORT', 'MPI', 'MPI', 'MPI', 'MPI'], msg).join('')
          break
        case 'DATA':  // falls through
        case 'MPI':
          str = msg.substring(0, HLP.readLen(msg) + 4)
          break
        default:
          str = msg.substring(0, DTS[a])
      }
      data.push(str)
      msg = msg.substring(str.length)
    })
    return data
  }

  // https://github.com/msgpack/msgpack-javascript/blob/master/msgpack.js

  var _bin2num = {}
    , _num2bin = {}
    , _toString = String.fromCharCode

  var i = 0, v

  for (; i < 0x100; ++i) {
    v = _toString(i)
    _bin2num[v] = i  // "\00" -> 0x00
    _num2bin[i] = v  //     0 -> "\00"
  }

  for (i = 0x80; i < 0x100; ++i) {  // [Webkit][Gecko]
    _bin2num[_toString(0xf700 + i)] = i  // "\f780" -> 0x80
  }

  HLP.toByteArray = function (data) {
    var rv = [], bin2num = _bin2num, remain
      , ary = data.split("")
      , i = -1
      , iz

    iz = ary.length
    remain = iz % 8

    while (remain--) {
      ++i
      rv[i] = bin2num[ary[i]]
    }
    remain = iz >> 3
    while (remain--) {
      rv.push(bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]],
              bin2num[ary[++i]], bin2num[ary[++i]])
    }
    return rv
  }

}).call(this)<|endoftext|>


<commit_before><commit_msg>Remove stray empty helpers.js<commit_after><|endoftext|>


<commit_before>"use strict";

/* CSI - control sequence introducer */
/* SGR - set graphic rendition */

var assign   = require("es5-ext/object/assign")
  , includes = require("es5-ext/string/#/contains")
  , forOwn   = require("es5-ext/object/for-each")
  , onlyKey  = require("es5-ext/object/first-key")
  , forEachRight = require("es5-ext/array/#/for-each-right")
  , uniq = require("es5-ext/array/#/uniq.js");

var CSI = "\x1b[";

var sgr = function (code) {
	return CSI + code + "m";
};

sgr.CSI = CSI;

var mods = assign({
	// Style
	bold: { _bold: [1, 22] },
	italic: { _italic: [3, 23] },
	underline: { _underline: [4, 24] },
	blink: { _blink: [5, 25] },
	inverse: { _inverse: [7, 27] },
	strike: { _strike: [9, 29] }

	// Color
}, ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"]
	.reduce(function (obj, color, index) {
		// foreground
		obj[color] = { _fg: [30 + index, 39] };
		obj[color + "Bright"] = { _fg: [90 + index, 39] };

		// background
		obj["bg" + color[0].toUpperCase() + color.slice(1)] = { _bg: [40 + index, 49] };
		obj["bg" + color[0].toUpperCase() + color.slice(1) + "Bright"] = { _bg: [100 + index, 49] };

		return obj;
	}, {}));

sgr.mods = mods;

sgr.openers = {};
sgr.closers = {};

forOwn(mods, function (mod) {
	var modPair = mod[onlyKey(mod)];

	sgr.openers[modPair[0]] = modPair;
	sgr.closers[modPair[1]] = modPair;
});

sgr.openStyle = function (mods, code) {
	mods.push(sgr.openers[code]);
};

sgr.closeStyle = function (mods, code) {
	forEachRight.call(mods, function (modPair, index) {
		if (modPair[1] === code) {
			mods.splice(index, 1);
		}
	});
};

/* prepend openers */
sgr.prepend = function (mods) {
	return mods.map(function (modPair, key) {
		return sgr(modPair[0]);
	});
};

/* complete non-closed openers with corresponding closers */
sgr.complete = function (mods, closerCodes) {
	closerCodes.forEach(function (code) {
		sgr.closeStyle(mods, code);
	});

	// mods must be closed from the last opened to first opened
	mods = mods.reverse();

	mods = mods.map(function (modPair, key) {
		return modPair[1];
	});

	// one closer can close many openers (31, 32 -> 39)
	mods = uniq.call(mods);

	return mods.map(sgr);
};

var hasCSI = function (str) {
	return includes.call(str, CSI);
};

sgr.hasCSI = hasCSI;

var extractCode = function (csi) {
	var code = csi.slice(2, -1);
	code = Number(code);
	return code;
};

sgr.extractCode = extractCode;

module.exports = sgr;
<commit_msg>style: prettier<commit_after>"use strict";

/* CSI - control sequence introducer */
/* SGR - set graphic rendition */

var assign       = require("es5-ext/object/assign")
  , includes     = require("es5-ext/string/#/contains")
  , forOwn       = require("es5-ext/object/for-each")
  , onlyKey      = require("es5-ext/object/first-key")
  , forEachRight = require("es5-ext/array/#/for-each-right")
  , uniq         = require("es5-ext/array/#/uniq.js");

var CSI = "\x1b[";

var sgr = function (code) { return CSI + code + "m"; };

sgr.CSI = CSI;

var mods = assign(
	{
		// Style
		bold: { _bold: [1, 22] },
		italic: { _italic: [3, 23] },
		underline: { _underline: [4, 24] },
		blink: { _blink: [5, 25] },
		inverse: { _inverse: [7, 27] },
		strike: { _strike: [9, 29] }

		// Color
	},
	["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"].reduce(function (
		obj,
		color,
		index
	) {
		// foreground
		obj[color] = { _fg: [30 + index, 39] };
		obj[color + "Bright"] = { _fg: [90 + index, 39] };

		// background
		obj["bg" + color[0].toUpperCase() + color.slice(1)] = { _bg: [40 + index, 49] };
		obj["bg" + color[0].toUpperCase() + color.slice(1) + "Bright"] = { _bg: [100 + index, 49] };

		return obj;
	}, {})
);

sgr.mods = mods;

sgr.openers = {};
sgr.closers = {};

forOwn(mods, function (mod) {
	var modPair = mod[onlyKey(mod)];

	sgr.openers[modPair[0]] = modPair;
	sgr.closers[modPair[1]] = modPair;
});

sgr.openStyle = function (mods, code) { mods.push(sgr.openers[code]); };

sgr.closeStyle = function (mods, code) {
	forEachRight.call(mods, function (modPair, index) {
		if (modPair[1] === code) {
			mods.splice(index, 1);
		}
	});
};

/* prepend openers */
sgr.prepend = function (mods) {
	return mods.map(function (modPair, key) { return sgr(modPair[0]); });
};

/* complete non-closed openers with corresponding closers */
sgr.complete = function (mods, closerCodes) {
	closerCodes.forEach(function (code) { sgr.closeStyle(mods, code); });

	// mods must be closed from the last opened to first opened
	mods = mods.reverse();

	mods = mods.map(function (modPair, key) { return modPair[1]; });

	// one closer can close many openers (31, 32 -> 39)
	mods = uniq.call(mods);

	return mods.map(sgr);
};

var hasCSI = function (str) { return includes.call(str, CSI); };

sgr.hasCSI = hasCSI;

var extractCode = function (csi) {
	var code = csi.slice(2, -1);
	code = Number(code);
	return code;
};

sgr.extractCode = extractCode;

module.exports = sgr;
<|endoftext|>


<commit_before>/*
 * nodeON-helpers
 * A collection of helper funcs
 * https://github.com/thanpolas/nodeON-helpers
 *
 * Copyright (c) 2014 Thanasis Polychronakis
 * Licensed under the MIT license.
 */

/**
 * @fileoverview Helpers.
 */

var __ = require('lodash');
var bcrypt = require('bcrypt');
var slug = require('slug');

var helpers = module.exports = {};

var noop = function() {};

/** @type {string} Internal store for salt. */
helpers.__salt = '';

/**
 * Set the Salt for crypto functions.
 *
 * @param {string} salt The salt.
 */
helpers.setSalt = function (salt) {
  helpers.__salt = salt;
};

/**
 * Adds a {@code getInstance} static method that always return the same instance
 * object.
 * @param {!Function} Ctor The constructor for the class to add the static
 *     method to.
 */
helpers.addSingletonGetter = function(Ctor) {
  Ctor.getInstance = function() {
    if (Ctor._instance) {
      return Ctor._instance;
    }
    return Ctor._instance = new Ctor();
  };
};

/**
 * Generate a random string.
 *
 * @param  {number=} optLength How long the string should be, default 32.
 * @return {string} a random string.
 */
helpers.generateRandomString = function(optLength) {
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';

  var length = optLength || 32;
  var string = '';
  var randomNumber = 0;
  for (var i = 0; i < length; i++) {
    randomNumber = Math.floor(Math.random() * chars.length);
    string += chars.substring(randomNumber, randomNumber + 1);
  }

  return string;
};

/**
 * Generate a random number, returns type string!.
 *
 * @param  {number=} optLength How long, default 20.
 * @return {string} A random number cast to string.
 */
helpers.generateRandomNumber = function(optLength) {
  var nums = '0123456789';
  var numLen = nums.length;
  var length = optLength || 20;

  var string = '';
  var randomNumber = 0;
  for (var i = 0; i < length; i++) {
    randomNumber = Math.floor(Math.random() * numLen);
    string += nums.substring(randomNumber, randomNumber + 1);
  }

  return string;
};
/**
 * Create a salted hash of the provided string.
 *
 * @param {string} src The string we want to hash.
 * @param {Object|Function(Error=, string=)=} optOpts Options or callback.
 * @param {Function(Error=, string=)=} optDone Callback.
 */
helpers.hash = function(src, optOpts, optDone) {

  var opts = {};
  var done = noop;

  if (__.isObject(optOpts)) {
    opts = optOpts;
  }
  if (__.isFunction(optOpts)) {
    done = optOpts;
  }
  if (__.isFunction(optDone)) {
    done = optDone;
  }

  bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(helpers.salt(src), salt, done);
  });
};

/**
 * Check if a string matches a hash.
 *
 * @param {string} hash The encrypted hash.
 * @param {string} src The plain text string to verify.
 * @param {Object|Function(boolean)=} optOpts Options or callback.
 * @param {Function(boolean)=} optDone callback, first arg will always be bool.
 */
helpers.hashVerify = function(hash, src, optOpts, optDone) {
  var opts = {};
  var done = noop;

  if (__.isObject(optOpts)) {
    opts = optOpts;
  }
  if (__.isFunction(optOpts)) {
    done = optOpts;
  }
  if (__.isFunction(optDone)) {
    done = optDone;
  }

  bcrypt.compare(helpers.salt(src), hash, function(err, res) {
    done(res);
  });
};

/**
 * Salt a string.
 *
 * @param  {string} src The string we want to salt.
 * @return {string} The string salted.
 */
helpers.salt = function(src) {
  return src + helpers.__salt;
};

/**
 * Returns a unique-ish url-friendly string,
 * uses a 6 random number to raise entropy.
 *
 * @param  {string} token The token you need to be urlified.
 * @param {number=} optRandLen Define how many random numbers, default 6,
 *  disable 0.
 * @return {string} urlefied string.
 */
helpers.urlify = function(token, optRandLen) {
  var randLen = 6;
  if (__.isNumber(optRandLen)) {
    randLen = optRandLen;
  }
  var out = '';
  if (randLen) {
    out += helpers.generateRandomNumber(randLen);
    out += '-';
  }
  out += slug(token).toLowerCase();
  return out;
};

/**
 * Truncates the argument number the function is invoked with.
 *
 * @param {Function} fn The function which arguments needs truncating.
 * @param {number} count
 * @return {Function} The function to use.
 * @cudos Petka Antonov
 */
helpers.truncateArgs = function (fn, count, optThisArg) {
  var thisArg = optThisArg || null;
  return function() {
    return fn.apply(thisArg, [].slice.call(arguments,0, count));
  };
};

/**
 * Skips the first n arguments of a function to be invoked.
 *
 * @param {Function} fn The function which arguments needs truncating.
 * @param {number} skip How many arguments to truncate from.
 * @return {Function=} optThisArg Context.
 * @return {Function} The function to use.
 */
helpers.skipArgs = function(fn, skip, optThisArg) {
  var thisArg = optThisArg || null;
  return function() {
    return fn.apply(thisArg, [].slice.call(arguments, skip));
  };
};

/**
 * Copy an array to another using push().
 *
 * @param {Array} src The src Array.
 * @param {Array} dst The dst Array.
 */
helpers.pushCopy = function(src, dst) {
  src.forEach(function(item) {
    dst.push(item);
  });
};

/**
 * Get the user's home directory.
 *
 * @return {string} The full path to the user's home directory.
 */
helpers.getUserHome = function getUserHome() {
  return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
};

/**
 * Determines if a value is a number type.
 *
 * @param {string} num The value to check
 * @return {boolean} Yes or no.
 * @see http://stackoverflow.com/questions/6449611/how-to-check-whether-a-value-is-a-number-in-javascript-or-jquery
 */
helpers.isNumeric = function(num) {
  return !isNaN(parseFloat(num)) && isFinite(num);
};

<commit_msg>add the isRequestJson helper<commit_after>/*
 * nodeON-helpers
 * A collection of helper funcs
 * https://github.com/thanpolas/nodeON-helpers
 *
 * Copyright (c) 2014 Thanasis Polychronakis
 * Licensed under the MIT license.
 */

/**
 * @fileoverview Helpers.
 */

var __ = require('lodash');
var bcrypt = require('bcrypt');
var slug = require('slug');

var helpers = module.exports = {};

var noop = function() {};

/** @type {string} Internal store for salt. */
helpers.__salt = '';

/**
 * Set the Salt for crypto functions.
 *
 * @param {string} salt The salt.
 */
helpers.setSalt = function (salt) {
  helpers.__salt = salt;
};

/**
 * Adds a {@code getInstance} static method that always return the same instance
 * object.
 * @param {!Function} Ctor The constructor for the class to add the static
 *     method to.
 */
helpers.addSingletonGetter = function(Ctor) {
  Ctor.getInstance = function() {
    if (Ctor._instance) {
      return Ctor._instance;
    }
    return Ctor._instance = new Ctor();
  };
};

/**
 * Generate a random string.
 *
 * @param  {number=} optLength How long the string should be, default 32.
 * @return {string} a random string.
 */
helpers.generateRandomString = function(optLength) {
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';

  var length = optLength || 32;
  var string = '';
  var randomNumber = 0;
  for (var i = 0; i < length; i++) {
    randomNumber = Math.floor(Math.random() * chars.length);
    string += chars.substring(randomNumber, randomNumber + 1);
  }

  return string;
};

/**
 * Generate a random number, returns type string!.
 *
 * @param  {number=} optLength How long, default 20.
 * @return {string} A random number cast to string.
 */
helpers.generateRandomNumber = function(optLength) {
  var nums = '0123456789';
  var numLen = nums.length;
  var length = optLength || 20;

  var string = '';
  var randomNumber = 0;
  for (var i = 0; i < length; i++) {
    randomNumber = Math.floor(Math.random() * numLen);
    string += nums.substring(randomNumber, randomNumber + 1);
  }

  return string;
};
/**
 * Create a salted hash of the provided string.
 *
 * @param {string} src The string we want to hash.
 * @param {Object|Function(Error=, string=)=} optOpts Options or callback.
 * @param {Function(Error=, string=)=} optDone Callback.
 */
helpers.hash = function(src, optOpts, optDone) {

  var opts = {};
  var done = noop;

  if (__.isObject(optOpts)) {
    opts = optOpts;
  }
  if (__.isFunction(optOpts)) {
    done = optOpts;
  }
  if (__.isFunction(optDone)) {
    done = optDone;
  }

  bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(helpers.salt(src), salt, done);
  });
};

/**
 * Check if a string matches a hash.
 *
 * @param {string} hash The encrypted hash.
 * @param {string} src The plain text string to verify.
 * @param {Object|Function(boolean)=} optOpts Options or callback.
 * @param {Function(boolean)=} optDone callback, first arg will always be bool.
 */
helpers.hashVerify = function(hash, src, optOpts, optDone) {
  var opts = {};
  var done = noop;

  if (__.isObject(optOpts)) {
    opts = optOpts;
  }
  if (__.isFunction(optOpts)) {
    done = optOpts;
  }
  if (__.isFunction(optDone)) {
    done = optDone;
  }

  bcrypt.compare(helpers.salt(src), hash, function(err, res) {
    done(res);
  });
};

/**
 * Salt a string.
 *
 * @param  {string} src The string we want to salt.
 * @return {string} The string salted.
 */
helpers.salt = function(src) {
  return src + helpers.__salt;
};

/**
 * Returns a unique-ish url-friendly string,
 * uses a 6 random number to raise entropy.
 *
 * @param  {string} token The token you need to be urlified.
 * @param {number=} optRandLen Define how many random numbers, default 6,
 *  disable 0.
 * @return {string} urlefied string.
 */
helpers.urlify = function(token, optRandLen) {
  var randLen = 6;
  if (__.isNumber(optRandLen)) {
    randLen = optRandLen;
  }
  var out = '';
  if (randLen) {
    out += helpers.generateRandomNumber(randLen);
    out += '-';
  }
  out += slug(token).toLowerCase();
  return out;
};

/**
 * Truncates the argument number the function is invoked with.
 *
 * @param {Function} fn The function which arguments needs truncating.
 * @param {number} count
 * @return {Function} The function to use.
 * @cudos Petka Antonov
 */
helpers.truncateArgs = function (fn, count, optThisArg) {
  var thisArg = optThisArg || null;
  return function() {
    return fn.apply(thisArg, [].slice.call(arguments,0, count));
  };
};

/**
 * Skips the first n arguments of a function to be invoked.
 *
 * @param {Function} fn The function which arguments needs truncating.
 * @param {number} skip How many arguments to truncate from.
 * @return {Function=} optThisArg Context.
 * @return {Function} The function to use.
 */
helpers.skipArgs = function(fn, skip, optThisArg) {
  var thisArg = optThisArg || null;
  return function() {
    return fn.apply(thisArg, [].slice.call(arguments, skip));
  };
};

/**
 * Copy an array to another using push().
 *
 * @param {Array} src The src Array.
 * @param {Array} dst The dst Array.
 */
helpers.pushCopy = function(src, dst) {
  src.forEach(function(item) {
    dst.push(item);
  });
};

/**
 * Get the user's home directory.
 *
 * @return {string} The full path to the user's home directory.
 */
helpers.getUserHome = function getUserHome() {
  return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
};

/**
 * Determines if a value is a number type.
 *
 * @param {string} num The value to check
 * @return {boolean} Yes or no.
 * @see http://stackoverflow.com/questions/6449611/how-to-check-whether-a-value-is-a-number-in-javascript-or-jquery
 */
helpers.isNumeric = function(num) {
  return !isNaN(parseFloat(num)) && isFinite(num);
};

/**
 * Determines if the request made accepts a JSON response.
 *
 * @param {Object} req The express request Object.
 * @return {boolean} True / false.
 */
helpers.isRequestJson = function(req) {
  return req.headers['accept'] && req.headers['accept'].match(/json/);
};
<|endoftext|>


<commit_before>import path from 'path';

export default {
    colors: true,
    files: [
        'lib/*.js'
    ],
    preprocessors: {
        'lib/*.js': 'webpack'
    },
    frameworks: [ 'mocha' ],
    webpack: {
        cache: true,
        resolve: {
            root: path.resolve('./')
        },
        module: {
            preLoaders: [
                {
                    test: /\.js$/,
                    exclude: [
                        path.resolve('lib/'),
                        path.resolve('node_modules/')
                    ],
                    loader: 'babel'
                },
                {
                    test: /\.js$/,
                    include: path.resolve('lib/'),
                    loader: 'isparta'
                }
            ]
        }
    },
    webpackMiddleware: {
        noInfo: true,
        quiet: true
    },
    coverageReporter: {
        dir: '../coverage',
        reporters: [
            { type: 'lcovonly', subdir: '.' }
        ]
    },
    browserNoActivityTimeout: 60 * 1000, // default 10 * 1000
    browserDisconnectTimeout: 10 * 1000, // default 2 * 1000
    browserDisconnectTolerance: 2, // default 0
    captureTimeout: 2 * 60 * 1000 // default 1 * 60 * 1000
};
<commit_msg>:space_invader: attempt to fix travis tests run<commit_after>import path from 'path';

export default {
    colors: true,
    basePath: path.resolve('./'),
    files: [
        'lib/*.js'
    ],
    preprocessors: {
        'lib/*.js': 'webpack'
    },
    frameworks: [ 'mocha' ],
    webpack: {
        cache: true,
        resolve: {
            root: path.resolve('./')
        },
        module: {
            preLoaders: [
                {
                    test: /\.js$/,
                    exclude: [
                        path.resolve('lib/'),
                        path.resolve('node_modules/')
                    ],
                    loader: 'babel'
                },
                {
                    test: /\.js$/,
                    include: path.resolve('lib/'),
                    loader: 'isparta'
                }
            ]
        }
    },
    webpackMiddleware: {
        noInfo: true,
        quiet: true
    },
    coverageReporter: {
        dir: '../coverage',
        reporters: [
            { type: 'lcovonly', subdir: '.' }
        ]
    },
    browserNoActivityTimeout: 60 * 1000, // default 10 * 1000
    browserDisconnectTimeout: 10 * 1000, // default 2 * 1000
    browserDisconnectTolerance: 2, // default 0
    captureTimeout: 2 * 60 * 1000 // default 1 * 60 * 1000
};
<|endoftext|>


<commit_before>'use strict';

const url = require('url');
const props = [
  'path',
  'pathname',
  'port',
  'hostname',
  'protocol',
  'auth',
  'hash'
];

const matchers = {
  protocol: (expected, actual, contains) => {
    return expected === actual || expected + ':' === actual;
  },
  hash: (expected, actual, contains) => {
    return matchers.default(expected, actual, contains) || matchers.default('#' + expected, actual, contains);
  },
  port: (expected, actual, contains) => {
    return expected === actual || expected === parseInt(actual, 10);
  },
  default: (expected, actual, contains) => {
    return contains ? actual.includes(expected) : actual === expected;
  }
};

module.exports = function (chai, utils) {
  const Assertion = chai.Assertion;

  props.forEach(prop => {
    Assertion.addMethod(prop, function (value) {
      const str = this._obj;

      // if url isn't a string we cannot continue
      new Assertion(str).to.be.a('string');

      const parsed = url.parse(str);
      const contains = utils.flag(this, 'contains');
      const matcher = matchers[prop] || matchers.default;
      const match = matcher(value, parsed[prop], contains);
      this.assert(
        match,
        `expected #{this} to have ${prop} #{exp} but got #{act}`,
        `expected #{this} to not to have ${prop} #{act}`,
        value,
        parsed[prop]
      );
    });
  });
};
<commit_msg>Don't allow `contains` for protocol or port - require exact match<commit_after>'use strict';

const url = require('url');
const props = [
  'path',
  'pathname',
  'port',
  'hostname',
  'protocol',
  'auth',
  'hash'
];

const matchers = {
  protocol: (expected, actual, contains) => {
    if (contains) {
      console.warn('chai-url: `contains` flag should not be used with protocol matching and will be ignored');
    }
    return expected === actual || expected + ':' === actual;
  },
  hash: (expected, actual, contains) => {
    return matchers.default(expected, actual, contains) || matchers.default('#' + expected, actual, contains);
  },
  port: (expected, actual, contains) => {
    if (contains) {
      console.warn('chai-url: `contains` flag should not be used with port matching and will be ignored');
    }
    return expected === actual || expected === parseInt(actual, 10);
  },
  default: (expected, actual, contains) => {
    return contains ? actual.includes(expected) : actual === expected;
  }
};

module.exports = function (chai, utils) {
  const Assertion = chai.Assertion;

  props.forEach(prop => {
    Assertion.addMethod(prop, function (value) {
      const str = this._obj;

      // if url isn't a string we cannot continue
      new Assertion(str).to.be.a('string');

      const parsed = url.parse(str);
      const contains = utils.flag(this, 'contains');
      const matcher = matchers[prop] || matchers.default;
      const match = matcher(value, parsed[prop], contains);
      this.assert(
        match,
        `expected #{this} to have ${prop} #{exp} but got #{act}`,
        `expected #{this} to not to have ${prop} #{act}`,
        value,
        parsed[prop]
      );
    });
  });
};
<|endoftext|>


<commit_before>var T = require('..');
var Prankcall = T.prankcall.Prankcall;
var sleep = Prankcall.sleep;
var http = require('http');
var request = require('co-request');

require('sinon-doublist-fs')('mocha');

describe('Prankcall - Examples', function(testDone) {
  'use strict';

  beforeEach(function() {
    this.prankcall = T.prankcall.create();
    this.portlandZip = 97204;
  });

  function getWeatherFromYahoo(location) {
    return function *getWeatherFromYahooGen() {
      var response = yield request('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20location%20%3D%20' + location + '&format=json');
      return response.body;
    };
  }

  it('should demo single call', function *() {
    var fs = require('co-fs');
    var filename = '/tmp/weather-latest.json';
    var expectedJson;
    var producerGenFn = getWeatherFromYahoo(this.portlandZip);
    var consumerGenFn = function *(dataFromProducer) {
      expectedJson = dataFromProducer;
      yield fs.writeFile(filename, dataFromProducer);
    };
    yield this.prankcall.recv(consumerGenFn).send(producerGenFn);
    (yield fs.readFile(filename)).toString().should.equal(expectedJson);
  });

  it.skip('should demo infinite calls with custom sleep and backoff', function *() {
    yield this.prankcall.send(this.send);
  });

  it.skip('should demo infinite producer-consumer flow', function *() {
    yield this.prankcall.send(this.send);
  });

  it.skip('should demo consumer ending a flow', function *() {
    yield this.prankcall.send(this.send);
  });
});
<commit_msg>test(examples): Init demo of producer stopped by consumer<commit_after>var T = require('..');
var Prankcall = T.prankcall.Prankcall;
var sleep = Prankcall.sleep;
var http = require('http');
var request = require('co-request');

require('sinon-doublist-fs')('mocha');

describe('Prankcall - Examples', function(testDone) {
  'use strict';

  beforeEach(function() {
    this.prankcall = T.prankcall.create();
  });

  function getWeatherFromYahoo(location) {
    return function *getWeatherFromYahooGen() {
      var response = yield request('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20location%20%3D%20' + location + '&format=json');
      return response.body;
    };
  }

  it('should demo single call', function *() {
    var fs = require('co-fs');
    var expectedJson;

    var filename = '/tmp/weather/latest.json';
    this.stubTree(filename);

    var producerGenFn = getWeatherFromYahoo(97204);

    var consumerGenFn = function *(dataFromProducer) {
      expectedJson = dataFromProducer;
      yield fs.writeFile(filename, dataFromProducer);
    };

    yield this.prankcall.recv(consumerGenFn).send(producerGenFn);

    (yield fs.readFile(filename)).toString().should.equal(expectedJson);
  });

  it('should demo producer dynamically stopped by consumer', function *() {
    var maxIter = 100;
    var curIter = 0;

    function *producer() {
      yield sleep(0);
      curIter++;
      return '';
    }

    function *consumer() {
      yield sleep(0);
      return curIter < maxIter;
    }

    this.prankcall.sleep(0);
    yield this.prankcall.recv(consumer).send(producer);

    curIter.should.equal(maxIter);
  });
});
<|endoftext|>


<commit_before>var expect = require('chai').expect;
var fs = require('fs');
var locater = require('../lib/locater');

describe("locater", function() {
  it("matches string and returns locations of results", function() {
    var input = fs.readFileSync(
      './test/fixtures/sample_input.txt', {encoding: 'utf8'});

    var result = locater('my', input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(4);
    expect(result[1].line).to.equal(2);
    expect(result[1].cursor).to.equal(1);
    expect(result[2].line).to.equal(3);
    expect(result[2].cursor).to.equal(27);
  });

  it("matches regex and returns locations of results", function() {
    var input = fs.readFileSync(
      './test/fixtures/sample_input.txt', {encoding: 'utf8'});

    var result = locater(/[a-zA-Z]{7}/g, input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(7);
    expect(result[1].line).to.equal(1);
    expect(result[1].cursor).to.equal(24);
    expect(result[2].line).to.equal(3);
    expect(result[2].cursor).to.equal(11);
  });

  it("can match more than once for the same line", function() {
    var input = "What ain't no country I've ever heard of. They speak English in What?";
    var result = locater('What', input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(1);
    expect(result[1].line).to.equal(1);
    expect(result[1].cursor).to.equal(65);
  });
});
<commit_msg>Add test for the case where there is no match<commit_after>var expect = require('chai').expect;
var fs = require('fs');
var locater = require('../lib/locater');

describe("locater", function() {
  it("matches string and returns locations of results", function() {
    var input = fs.readFileSync(
      './test/fixtures/sample_input.txt', {encoding: 'utf8'});

    var result = locater('my', input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(4);
    expect(result[1].line).to.equal(2);
    expect(result[1].cursor).to.equal(1);
    expect(result[2].line).to.equal(3);
    expect(result[2].cursor).to.equal(27);
  });

  it("matches regex and returns locations of results", function() {
    var input = fs.readFileSync(
      './test/fixtures/sample_input.txt', {encoding: 'utf8'});

    var result = locater(/[a-zA-Z]{7}/g, input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(7);
    expect(result[1].line).to.equal(1);
    expect(result[1].cursor).to.equal(24);
    expect(result[2].line).to.equal(3);
    expect(result[2].cursor).to.equal(11);
  });

  it("can match more than once for the same line", function() {
    var input = "What ain't no country I've ever heard of. They speak English in What?";
    var result = locater('What', input);

    expect(result[0].line).to.equal(1);
    expect(result[0].cursor).to.equal(1);
    expect(result[1].line).to.equal(1);
    expect(result[1].cursor).to.equal(65);
  });

  it("returns an empty array when no match is present", function() {
    var result = locater('What', "Zed's dead, baby. Zed's dead.");
    expect(result).to.have.length(0);
  });
});
<|endoftext|>


<commit_before>module.exports = isUndef

function isUndef(x) {
  return type(x) === 'undefined'
}

const type = require('./type')<commit_msg>Forgot to remove `isUndef`<commit_after><|endoftext|>