diff --git a/.travis.yml b/.travis.yml index b532c0c..064309e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ +sudo: false language: node_js node_js: - - "0.8" + - "0.12" - "0.10" - - "0.11" -before_install: - - "npm install -g npm@1.4.x" + - "4" + - "iojs" script: - "npm run test-travis" after_script: - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls" +matrix: + fast_finish: true diff --git a/README.md b/README.md index 82a2e94..75e911a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ **pre-push** is a pre-push hook installer for `git`. It will ensure that your `npm test` (or other specified scripts) passes before you can push your -changes. This all conveniently configured in your package.json. +changes. This all conveniently configured in your `package.json`. But don't worry, you can still force a push by telling `git` to skip the `pre-push` hooks by simply pushing using `--no-verify`. @@ -32,7 +32,7 @@ the existing `pre-push` file in your `.git/hooks` folder. Existing `pre-push` will try to run your `npm test` command in the root of the git repository by default unless it's the default value that is set by the `npm -init` script. +init` script. But `pre-push` is not limited to just running your `npm test`'s during the push hook. It's also capable of running every other script that you've @@ -45,7 +45,7 @@ could ensure that: - Contribution licenses signed etc. The only thing you need to do is add a `pre-push` array to your `package.json` -that specifies which scripts should be run and in which order: +that specifies which scripts you want to have ran and in which order: ```js { @@ -96,7 +96,7 @@ The examples above are all the same. In addition to configuring which scripts should be ran you can also configure the following options: - **silent** Don't output the prefixed `pre-push:` messages when things fail - or when we have nothing to run. Should a boolean. + or when we have nothing to run. Should be a boolean. - **colors** Don't output colors when we write messages. Should be a boolean. - **template** Path to a file who's content should be used as template for the git push body. diff --git a/hook b/hook index eb51d00..fd90974 100755 --- a/hook +++ b/hook @@ -1,24 +1,50 @@ -#!/bin/bash +#!/usr/bin/env bash -git stash -q --keep-index +HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> /dev/null` + +# +# There are some issues with Source Tree because paths are not set correctly for +# the given environment. Sourcing the bash_profile seems to resolve this for bash users, +# sourcing the zshrc for zshell users. +# +# https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly +# +function source_home_file { + file="$HOME/$1" + [[ -f "${file}" ]] && source "${file}" +} + +if [[ -z "$HAS_NODE" ]]; then + source_home_file ".bash_profile" || source_home_file ".zshrc" || source_home_file ".bashrc" || true +fi NODE=`which node 2> /dev/null` NODEJS=`which nodejs 2> /dev/null` IOJS=`which iojs 2> /dev/null` LOCAL="/usr/local/bin/node" +BINARY= -if [[ -n $NODE ]]; then - "$NODE" $("$NODE" -e "console.log(require.resolve('pre-push'))") -elif [[ -n $NODEJS ]]; then - "$NODEJS" $("$NODEJS" -e "console.log(require.resolve('pre-push'))") -elif [[ -n $IOJS ]]; then - "$IOJS" $("$IOJS" -e "console.log(require.resolve('pre-push'))") -elif [[ -x $LOCAL ]]; then - "$LOCAL" $("$LOCAL" -e "console.log(require.resolve('pre-push'))") +# +# Figure out which binary we need to use for our script execution. +# +if [[ -n "$NODE" ]]; then + BINARY="$NODE" +elif [[ -n "$NODEJS" ]]; then + BINARY="$NODEJS" +elif [[ -n "$IOJS" ]]; then + BINARY="$IOJS" +elif [[ -x "$LOCAL" ]]; then + BINARY="$LOCAL" fi -RESULT=$? - -git stash pop -q -[ $RESULT -ne 0 ] && exit 1 -exit 0 +# +# Add --dry-run cli flag support so we can execute this hook without side affects +# and see if it works in the current environment +# +if [[ $* == *--dry-run* ]]; then + if [[ -z "$BINARY" ]]; then + exit 1 + fi +else + "$BINARY" "$("$BINARY" -e "console.log(require.resolve('pre-push'))")" +fi diff --git a/index.js b/index.js index c3dcb56..6a19ec8 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ 'use strict'; var spawn = require('cross-spawn') - , shelly = require('shelljs') + , which = require('which') , path = require('path') , util = require('util') , tty = require('tty'); @@ -56,6 +56,20 @@ Object.defineProperty(Hook.prototype, 'colors', { } }); +/** + * Execute a binary. + * + * @param {String} bin Binary that needs to be executed + * @param {Array} args Arguments for the binary + * @returns {Object} + * @api private + */ +Hook.prototype.exec = function exec(bin, args) { + return spawn.sync(bin, args, { + stdio: 'pipe' + }); +}; + /** * Parse the package.json so we can create an normalize it's contents to * a usable configuration structure. @@ -134,7 +148,7 @@ Hook.prototype.log = function log(lines, exit) { */ Hook.prototype.initialize = function initialize() { ['git', 'npm'].forEach(function each(binary) { - try { this[binary] = this.shelly.which(binary); } + try { this[binary] = which.sync(binary); } catch (e) {} }, this); @@ -145,7 +159,7 @@ Hook.prototype.initialize = function initialize() { if (!this.npm) { try { process.env.PATH += path.delimiter + path.dirname(process.env._); - this.npm = this.shelly.which('npm'); + this.npm = which.sync('npm'); } catch (e) { return this.log(this.format(Hook.log.binary, 'npm'), 0); } @@ -156,30 +170,24 @@ Hook.prototype.initialize = function initialize() { // if (!this.git) return this.log(this.format(Hook.log.binary, 'git'), 0); - this.root = this.shelly.exec(this.git +' rev-parse --show-toplevel', { - silent: true - }); - + this.root = this.exec(this.git, ['rev-parse', '--show-toplevel']); + if (this.root.code) return this.log(Hook.log.root, 0); - - this.root = this.root.output.trim(); + + this.root = this.root.stdout.toString().trim(); try { this.json = require(path.join(this.root, 'package.json')); this.parse(); } catch (e) { return this.log(this.format(Hook.log.json, e.message), 0); } - - // // If we have a git template we should configure it before checking for // scripts so it will still be applied even if we don't have anything to // execute. // if (this.config.template) { - this.shelly.exec(this.git +' config push.template "'+ this.config.template +'"', { - silent: true - }); + this.exec(this.git, ['config', 'push.template', this.config.template]); } if (!this.config.run) return this.log(Hook.log.run, 0); @@ -200,7 +208,7 @@ Hook.prototype.run = function runner() { // // There's a reason on why we're using an async `spawn` here instead of the - // `shelly.exec`. The sync `exec` is a hack that writes writes a file to + // `shelljs.exec`. The sync `exec` is a hack that writes writes a file to // disk and they poll with sync fs calls to see for results. The problem is // that the way they capture the output which us using input redirection and // this doesn't have the required `isAtty` information that libraries use to @@ -226,7 +234,6 @@ Hook.prototype.run = function runner() { * @public */ Hook.prototype.format = util.format; -Hook.prototype.shelly = shelly; /** * The various of error and status messages that we can output. diff --git a/install.js b/install.js index 2b38059..867bc80 100644 --- a/install.js +++ b/install.js @@ -5,8 +5,9 @@ // var fs = require('fs') , path = require('path') - , hook = path.join(__dirname, './hook') - , root = path.resolve(__dirname, '../..') + , os = require('os') + , hook = path.join(__dirname, 'hook') + , root = path.resolve(__dirname, '..', '..') , exists = fs.existsSync || path.existsSync; // @@ -15,15 +16,60 @@ var fs = require('fs') // `pre-push` file. The path needs to be absolute in order for the symlinking // to work correctly. // -var git = path.resolve(root, '.git') - , hooks = path.resolve(git, 'hooks') - , prepush = path.resolve(hooks, 'pre-push'); + +var git = getGitFolderPath(root); + +// Function to recursively finding .git folder +function getGitFolderPath(currentPath) { + var git = path.resolve(currentPath, '.git') + + if (!exists(git) || !fs.lstatSync(git).isDirectory()) { + console.log('pre-push:'); + console.log('pre-push: Not found .git folder in', git); + + var newPath = path.resolve(currentPath, '..'); + + // Stop if we on top folder + if (currentPath === newPath) { + return null; + } + + return getGitFolderPath(newPath); + } + + console.log('pre-push:'); + console.log('pre-push: Found .git folder in', git); + return git; +} + +// +// Resolve git directory for submodules +// +if (exists(git) && fs.lstatSync(git).isFile()) { + var gitinfo = fs.readFileSync(git).toString() + , gitdirmatch = /gitdir: (.+)/.exec(gitinfo) + , gitdir = gitdirmatch.length == 2 ? gitdirmatch[1] : null; + + if (gitdir !== null) { + git = path.resolve(root, gitdir); + hooks = path.resolve(git, 'hooks'); + prepush = path.resolve(hooks, 'pre-push'); + } +} // // Bail out if we don't have an `.git` directory as the hooks will not get // triggered. If we do have directory create a hooks folder if it doesn't exist. // -if (!exists(git) || !fs.lstatSync(git).isDirectory()) return; +if (!git) { + console.log('pre-push:'); + console.log('pre-push: Not found any .git folder for installing pre-push hook'); + return; +} + +var hooks = path.resolve(git, 'hooks') + , prepush = path.resolve(hooks, 'pre-push'); + if (!exists(hooks)) fs.mkdirSync(hooks); // @@ -46,16 +92,39 @@ if (exists(prepush) && !fs.lstatSync(prepush).isSymbolicLink()) { try { fs.unlinkSync(prepush); } catch (e) {} +// Create generic prepush hook that launches this modules hook (as well +// as stashing - unstashing the unstaged changes) +// TODO: we could keep launching the old pre-push scripts +var hookRelativeUnixPath = hook.replace(root, '.'); + +if(os.platform() === 'win32') { + hookRelativeUnixPath = hookRelativeUnixPath.replace(/[\\\/]+/g, '/'); +} + +var prepushContent = '#!/usr/bin/env bash' + os.EOL + + hookRelativeUnixPath + os.EOL + + 'RESULT=$?' + os.EOL + + '[ $RESULT -ne 0 ] && exit 1' + os.EOL + + 'exit 0' + os.EOL; + // // It could be that we do not have rights to this folder which could cause the // installation of this module to completely fail. We should just output the // error instead destroying the whole npm install process. // -try { fs.symlinkSync(hook, prepush, 'file'); } +try { fs.writeFileSync(prepush, prepushContent); } catch (e) { console.error('pre-push:'); - console.error('pre-push: Failed to symlink the hook file in your .git/hooks folder because:'); + console.error('pre-push: Failed to create the hook file in your .git/hooks folder because:'); console.error('pre-push: '+ e.message); console.error('pre-push: The hook was not installed.'); console.error('pre-push:'); } + +try { fs.chmodSync(prepush, '777'); } +catch (e) { + console.error('pre-push:'); + console.error('pre-push: chmod 0777 the pre-push file in your .git/hooks folder because:'); + console.error('pre-push: '+ e.message); + console.error('pre-push:'); +} diff --git a/package.json b/package.json index c7c4202..a3bfe33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-push", - "version": "0.1.1", + "version": "0.1.2", "description": "Automatically install pre-push hooks for your npm modules.", "main": "index.js", "scripts": { @@ -30,14 +30,14 @@ "homepage": "https://github.com/dflourusso/pre-push", "license": "MIT", "dependencies": { - "spawn-sync": "^1.0.15", - "cross-spawn": "^5.1.0", - "shelljs": "0.3.x" + "cross-spawn": "^5.0.1", + "spawn-sync": "^1.0.15", + "which": "1.2.x" }, "devDependencies": { - "assume": "1.1.x", - "istanbul": "0.3.x", - "mocha": "2.1.x", + "assume": "~1.5.0", + "istanbul": "0.4.x", + "mocha": "~3.3.0", "pre-push": "git://github.com/dflourusso/pre-push.git" }, "bugs": { diff --git a/uninstall.js b/uninstall.js index c7a9c7f..71773db 100644 --- a/uninstall.js +++ b/uninstall.js @@ -3,7 +3,26 @@ var fs = require('fs') , path = require('path') , exists = fs.existsSync || path.existsSync - , prepush = path.resolve(__dirname, '../..', '.git', 'hooks', 'pre-push'); + , root = path.resolve(__dirname, '..', '..') + , git = path.resolve(root, '.git'); + +// +// Resolve git directory for submodules +// +if (exists(git) && fs.lstatSync(git).isFile()) { + var gitinfo = fs.readFileSync(git).toString() + , gitdirmatch = /gitdir: (.+)/.exec(gitinfo) + , gitdir = gitdirmatch.length == 2 ? gitdirmatch[1] : null; + + if (gitdir !== null) { + git = path.resolve(root, gitdir); + } +} + +// +// Location of pre-push hook, if it exists +// +var prepush = path.resolve(git, 'hooks', 'pre-push'); // // Bail out if we don't have pre-push file, it might be removed manually. diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..493788c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,620 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +assume@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/assume/-/assume-1.5.1.tgz#9c241668526be1fac4be5207776e8e8fe89358cb" + dependencies: + deep-eql "0.1.x" + fn.name "1.0.x" + object-inspect "1.0.x" + pathval "0.1.x" + pruddy-error "1.0.x" + +async@1.x, async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.4.7: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +debug@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" + dependencies: + ms "0.7.2" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-eql@0.1.x: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fn.name@1.0.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.0.1.tgz#8015ad149c1011a116cdb89eba4cc11d9039add8" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +handlebars@^4.0.1: + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +is-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +istanbul@0.4.x: + version "0.4.5" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +js-yaml@3.x: + version "3.9.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +"minimatch@2 || 3", minimatch@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@0.5.1, mkdirp@0.5.x: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.0" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +object-inspect@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.0.2.tgz#a97885b553e575eb4009ebc09bdda9b1cd21979a" + +once@1.x, once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-shim@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +pathval@0.1.x: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-0.1.1.tgz#08f911cdca9cce5942880da7817bc0b723b66d82" + +"pre-push@git://github.com/dflourusso/pre-push.git": + version "0.1.1" + resolved "git://github.com/dflourusso/pre-push.git#0396b931b43bbecff01fb802c391e3e3689ef220" + dependencies: + cross-spawn "^5.1.0" + shelljs "0.3.x" + spawn-sync "^1.0.15" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +pruddy-error@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pruddy-error/-/pruddy-error-1.0.2.tgz#b37ec1a38bf9107c0cdc5bc663d3d4e80354ae80" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +readable-stream@^2.2.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + dependencies: + amdefine ">=0.0.4" + +source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +spawn-sync@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" + dependencies: + concat-stream "^1.4.7" + os-shim "^0.1.2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@^2.6: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +which@1.2.x: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + +which@^1.1.1, which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0"