├── bin ├── have-head ├── isgit ├── commit ├── stashes ├── ahead ├── dirty ├── untracked └── branch ├── .travis.yml ├── .appveyor.yml ├── .gitignore ├── package.json ├── LICENSE ├── index.js ├── README.md └── test.js /bin/have-head: -------------------------------------------------------------------------------- 1 | git show-ref 2 | -------------------------------------------------------------------------------- /bin/isgit: -------------------------------------------------------------------------------- 1 | git rev-parse --git-dir > /dev/null 2>&1 2 | -------------------------------------------------------------------------------- /bin/commit: -------------------------------------------------------------------------------- 1 | commit=`git rev-parse --short HEAD` 2 | echo $commit 3 | [ "$commit" == "" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - '9' 5 | - '8' 6 | - '7' 7 | - '6' 8 | - '5' 9 | - '4' 10 | -------------------------------------------------------------------------------- /bin/stashes: -------------------------------------------------------------------------------- 1 | stashes=`git stash list | wc -l | awk '{print $1}'` 2 | echo $stashes 3 | [ "$stashes" != "0" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /bin/ahead: -------------------------------------------------------------------------------- 1 | ahead=`git rev-list HEAD --not --remotes | wc -l | awk '{print $1}'` 2 | echo $ahead 3 | [ "$ahead" != "0" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /bin/dirty: -------------------------------------------------------------------------------- 1 | dirty=`git status -s | grep -v '^??' | wc -l | awk '{print $1}'` 2 | echo $dirty 3 | [ "$dirty" != "0" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /bin/untracked: -------------------------------------------------------------------------------- 1 | untracked=`git status -s | grep '^??' | wc -l | awk '{print $1}'` 2 | echo $untracked 3 | [ "$untracked" != "0" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /bin/branch: -------------------------------------------------------------------------------- 1 | branch=`git rev-parse --abbrev-ref HEAD` 2 | echo $branch 3 | [ "$branch" != "master" ] && [ "$branch" != "gh-pages" ] && exit 1 4 | exit 0 5 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: "8" 4 | - nodejs_version: "7" 5 | - nodejs_version: "6" 6 | - nodejs_version: "5" 7 | - nodejs_version: "4" 8 | 9 | # Install scripts. (runs after repo cloning) 10 | install: 11 | - ps: Install-Product node $env:nodejs_version 12 | - npm install 13 | 14 | test_script: 15 | # Output useful info for debugging. 16 | - node --version 17 | - npm --version 18 | # run tests 19 | - npm test 20 | 21 | # Don't actually build. 22 | build: off 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-state", 3 | "version": "4.1.0", 4 | "description": "Get the current state of any git repository", 5 | "main": "index.js", 6 | "scripts": { 7 | "pretest": "touch dummy.file", 8 | "test": "standard && tape test.js", 9 | "posttest": "rm dummy.file" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/watson/git-state.git" 14 | }, 15 | "dependencies": { 16 | "after-all-results": "^2.0.0" 17 | }, 18 | "devDependencies": { 19 | "standard": "^10.0.2", 20 | "tape": "^4.4.0" 21 | }, 22 | "engines": { 23 | "node": ">=4.0.0" 24 | }, 25 | "keywords": [ 26 | "git", 27 | "status", 28 | "state", 29 | "branch", 30 | "repo", 31 | "repository", 32 | "ahead", 33 | "dirty", 34 | "untracked" 35 | ], 36 | "author": "Thomas Watson Steen (https://twitter.com/wa7son)", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/watson/git-state/issues" 40 | }, 41 | "homepage": "https://github.com/watson/git-state", 42 | "coordinates": [ 43 | 55.777897, 44 | 12.592192 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2018 Thomas Watson Steen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var fs = require('fs') 4 | var path = require('path') 5 | var exec = require('child_process').exec 6 | var execSync = require('child_process').execSync 7 | var afterAll = require('after-all-results') 8 | 9 | // Prevent from failing on windows 10 | var nullPath = /^win/.test(process.platform) ? 'nul' : '/dev/null' 11 | 12 | // Consider EOL as \n because either Windows or *nix, this escape char will be there 13 | var EOL = /\r?\n/ 14 | 15 | exports.isGit = function isGit (dir, cb) { 16 | fs.stat(path.join(dir, '.git'), function (err) { 17 | cb(!err) // eslint-disable-line standard/no-callback-literal 18 | }) 19 | } 20 | 21 | exports.isGitSync = function isGitSync (dir) { 22 | return fs.existsSync(path.join(dir, '.git')) 23 | } 24 | 25 | exports.checkSync = function checkSync (repo, opts) { 26 | var branch = exports.branchSync(repo, opts) 27 | var ahead = exports.aheadSync(repo, opts) 28 | var status = statusSync(repo, opts) 29 | var stashes = exports.stashesSync(repo, opts) 30 | 31 | return { 32 | branch: branch, 33 | ahead: ahead, 34 | dirty: status.dirty, 35 | untracked: status.untracked, 36 | stashes: stashes 37 | } 38 | } 39 | 40 | exports.check = function check (repo, opts, cb) { 41 | if (typeof opts === 'function') return exports.check(repo, {}, opts) 42 | 43 | var next = afterAll(function (err, results) { 44 | if (err) return cb(err) 45 | 46 | var branch = results[0] 47 | var ahead = results[1] 48 | var stashes = results[2] 49 | var status = results[3] 50 | 51 | cb(null, { 52 | branch: branch, 53 | ahead: ahead, 54 | dirty: status.dirty, 55 | untracked: status.untracked, 56 | stashes: stashes 57 | }) 58 | }) 59 | 60 | exports.branch(repo, opts, next()) 61 | exports.ahead(repo, opts, next()) 62 | exports.stashes(repo, opts, next()) 63 | 64 | status(repo, opts, next()) 65 | } 66 | 67 | exports.untracked = function untracked (repo, opts, cb) { 68 | if (typeof opts === 'function') return exports.untracked(repo, {}, opts) 69 | 70 | status(repo, opts, function (err, result) { 71 | if (err) return cb(err) 72 | cb(null, result.untracked) 73 | }) 74 | } 75 | 76 | exports.dirty = function dirty (repo, opts, cb) { 77 | if (typeof opts === 'function') return exports.dirty(repo, {}, opts) 78 | 79 | status(repo, opts, function (err, result) { 80 | if (err) return cb(err) 81 | cb(null, result.dirty) 82 | }) 83 | } 84 | 85 | exports.branch = function branch (repo, opts, cb) { 86 | if (typeof opts === 'function') return exports.branch(repo, {}, opts) 87 | opts = opts || {} 88 | 89 | exec('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 90 | if (err) { 91 | if (err.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') return cb(err) 92 | if (err.message === 'stdout maxBuffer exceeded') return cb(err) 93 | return cb() // most likely the git repo doesn't have any commits yet 94 | } 95 | cb(null, stdout.trim()) 96 | }) 97 | } 98 | 99 | exports.ahead = function ahead (repo, opts, cb) { 100 | if (typeof opts === 'function') return exports.ahead(repo, {}, opts) 101 | opts = opts || {} 102 | 103 | exec('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 104 | if (err) { 105 | if (err.message === 'stdout maxBuffer exceeded') return cb(err) 106 | return cb(null, NaN) // depending on the state of the git repo, the command might return non-0 exit code 107 | } 108 | stdout = stdout.trim() 109 | cb(null, !stdout ? 0 : parseInt(stdout.split(EOL).length, 10)) 110 | }) 111 | } 112 | 113 | function status (repo, opts, cb) { 114 | opts = opts || {} 115 | exec('git status -s', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 116 | if (err) return cb(err) 117 | var status = { dirty: 0, untracked: 0 } 118 | stdout.trim().split(EOL).filter(truthy).forEach(function (file) { 119 | if (file.substr(0, 2) === '??') status.untracked++ 120 | else status.dirty++ 121 | }) 122 | cb(null, status) 123 | }) 124 | } 125 | 126 | function truthy (obj) { 127 | return !!obj 128 | } 129 | 130 | exports.commit = function commit (repo, opts, cb) { 131 | if (typeof opts === 'function') return exports.commit(repo, {}, opts) 132 | opts = opts || {} 133 | 134 | exec('git rev-parse --short HEAD', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 135 | if (err) return cb(err) 136 | var commitHash = stdout.trim() 137 | cb(null, commitHash) 138 | }) 139 | } 140 | 141 | exports.stashes = function stashes (repo, opts, cb) { 142 | if (typeof opts === 'function') return exports.stashes(repo, {}, opts) 143 | opts = opts || {} 144 | 145 | exec('git stash list', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 146 | if (err) return cb(err) 147 | var stashes = stdout.trim().split(EOL).filter(truthy) 148 | cb(null, stashes.length) 149 | }) 150 | } 151 | 152 | exports.message = function message (repo, opts, cb) { 153 | if (typeof opts === 'function') return exports.message(repo, {}, opts) 154 | opts = opts || {} 155 | 156 | exec('git log -1 --pretty=%B', {cwd: repo, maxBuffer: opts.maxBuffer}, function (err, stdout, stderr) { 157 | if (err) return cb(err) 158 | cb(null, stdout.toString().trim()) 159 | }) 160 | } 161 | 162 | //* SYNC methods *// 163 | exports.untrackedSync = function untrackedSync (repo, opts) { 164 | return statusSync(repo, opts).untracked 165 | } 166 | 167 | exports.dirtySync = function dirtySync (repo, opts) { 168 | return statusSync(repo, opts).dirty 169 | } 170 | 171 | exports.branchSync = function branchSync (repo, opts) { 172 | opts = opts || {} 173 | try { 174 | var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', {cwd: repo, maxBuffer: opts.maxBuffer}).toString() 175 | return stdout.trim() 176 | } catch (err) { 177 | if (err.code === 'ENOBUFS') throw err 178 | return null // most likely the git repo doesn't have any commits yet 179 | } 180 | } 181 | 182 | exports.aheadSync = function aheadSync (repo, opts) { 183 | opts = opts || {} 184 | try { 185 | var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', {cwd: repo, maxBuffer: opts.maxBuffer}).toString() 186 | stdout = stdout.trim() 187 | return !stdout ? 0 : parseInt(stdout.split(EOL).length, 10) 188 | } catch (err) { 189 | if (err.code === 'ENOBUFS') throw err 190 | return NaN 191 | } 192 | } 193 | 194 | // Throws error 195 | var statusSync = function statusSync (repo, opts) { 196 | opts = opts || {} 197 | var stdout = execSync('git status -s', {cwd: repo, maxBuffer: opts.maxBuffer}).toString() 198 | var status = { dirty: 0, untracked: 0 } 199 | stdout.trim().split(EOL).filter(truthy).forEach(function (file) { 200 | if (file.substr(0, 2) === '??') status.untracked++ 201 | else status.dirty++ 202 | }) 203 | return status 204 | } 205 | 206 | // Throws error 207 | exports.commitSync = function commitSync (repo, opts) { 208 | opts = opts || {} 209 | var stdout = execSync('git rev-parse --short HEAD', {cwd: repo, maxBuffer: opts.maxBuffer}).toString() 210 | var commitHash = stdout.trim() 211 | return commitHash 212 | } 213 | 214 | // Throws error 215 | exports.stashesSync = function stashesSync (repo, opts) { 216 | opts = opts || {} 217 | var stdout = execSync('git stash list', {cwd: repo, maxBuffer: opts.maxBuffer}).toString() 218 | var stashes = stdout.trim().split(EOL).filter(truthy) 219 | return stashes.length 220 | } 221 | 222 | // Throws error 223 | exports.messageSync = function messageSync (repo, opts) { 224 | opts = opts || {} 225 | return execSync('git log -1 --pretty=%B', {cwd: repo, maxBuffer: opts.maxBuffer}).toString().trim() 226 | } 227 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # git-state 2 | 3 | Get the current state of any git repository. 4 | 5 | [![npm](https://img.shields.io/npm/v/git-state.svg)](https://www.npmjs.com/package/git-state) 6 | [![Build status](https://travis-ci.org/watson/git-state.svg?branch=master)](https://travis-ci.org/watson/git-state) 7 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) 8 | 9 | ## Installation 10 | 11 | ``` 12 | npm install git-state --save 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | var git = require('git-state') 19 | 20 | var path = '/path/to/git/repo' 21 | 22 | git.isGit(path, function (exists) { 23 | if (!exists) return 24 | 25 | git.check(path, function (err, result) { 26 | if (err) throw err 27 | console.log(result) // => { branch: 'master', 28 | // ahead: 0, 29 | // dirty: 9, 30 | // untracked: 1, 31 | // stashes: 0 } 32 | }) 33 | }) 34 | ``` 35 | 36 | ## API 37 | 38 | #### `isGit(path, callback)` 39 | 40 | Calls the `callback` with a boolean which is either `true` or `false` 41 | depending on if the given path contains a git repository. 42 | 43 | #### `isGitSync(path)` 44 | 45 | Synchronous version of `isGit()` which returns either `true` or `false` 46 | depending on if the given path contains a git repository. 47 | 48 | #### `check(path[, options], callback)` 49 | 50 | Will check the state of the git repository at the given `path` and call 51 | the `callback`. The `callback` will be called with two arguments: An 52 | optional error object and a result object. 53 | 54 | The result object contains the following properties: 55 | 56 | - `branch` - The currently checked out branch 57 | - `ahead` - The amount of commits the current branch is ahead of the 58 | remote (may be `NaN` if there for instance is no remote) 59 | - `dirty` - The number of dirty files 60 | - `untracked` - The number of untracked files 61 | - `stashes` - The number of stored stashes 62 | 63 | Supports the following `options`: 64 | 65 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 66 | stderr - if exceeded child process is killed (default: `200*1024`) 67 | 68 | #### `checkSync(path[, options])` 69 | 70 | Synchronous version of `check()`. 71 | 72 | Can throw error. This typically happens if you are running a too old 73 | version of Node.js (< 0.12), if git isn't found or if the path isn't 74 | a git repository. 75 | 76 | #### `untracked(path[, options], callback)` 77 | 78 | Get the amount of untracked files in the git repository at the given 79 | `path`. 80 | 81 | The `callback` will be called with two arguments: An optional error 82 | object and a number representing the amount of untracked files. 83 | 84 | Supports the following `options`: 85 | 86 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 87 | stderr - if exceeded child process is killed (default: `200*1024`) 88 | 89 | #### `untrackedSync(path[, options])` 90 | 91 | Synchronous version of `untracked()`. 92 | 93 | Can throw error. This typically happens if you are running a too old 94 | version of Node.js (< 0.12), if git isn't found or if the path isn't 95 | a git repository. 96 | 97 | #### `dirty(path[, options], callback)` 98 | 99 | Get the amount of dirty files in the git repository at the given 100 | `path`. 101 | 102 | The `callback` will be called with two arguments: An optional error 103 | object and a number representing the amount of dirty files. 104 | 105 | Supports the following `options`: 106 | 107 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 108 | stderr - if exceeded child process is killed (default: `200*1024`) 109 | 110 | #### `dirtySync(path[, options])` 111 | 112 | Synchronous version of `dirty() `. 113 | 114 | Can throw error. This typically happens if you are running a too old 115 | version of Node.js (< 0.12), if git isn't found or if the path isn't 116 | a git repository. 117 | 118 | #### `branch(path[, options], callback)` 119 | 120 | Get the currently checked out branch in the git repository at the given 121 | `path`. 122 | 123 | The `callback` will be called with two arguments: An optional error 124 | object and a string with the branch name. 125 | 126 | If the branch name cannot be found, a falsy value will be returned. 127 | 128 | Supports the following `options`: 129 | 130 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 131 | stderr - if exceeded child process is killed (default: `200*1024`) 132 | 133 | #### `branchSync(path[, options])` 134 | 135 | Synchronous version of `branch()`. Returns null if no branch is set. 136 | 137 | #### `ahead(path[, options], callback)` 138 | 139 | Get the amount of commits the current branch in the git repository at 140 | the given `path` is ahead of its remote. 141 | 142 | The `callback` will be called with two arguments: An optional error 143 | object and a number indicating the amount of commits the branch is ahead 144 | of its remote. 145 | 146 | If the number cannot be determined, `NaN` will be returned instead. 147 | 148 | Supports the following `options`: 149 | 150 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 151 | stderr - if exceeded child process is killed (default: `200*1024`) 152 | 153 | #### `aheadSync(path[, options])` 154 | 155 | Synchronous version of `ahead()`. 156 | 157 | If the number cannot be determined, `NaN` will be returned instead. 158 | 159 | #### `commit(path[, options], callback)` 160 | 161 | Get the short-hash (e.g. `7b0a3ab`) for the latest commit at `HEAD` in 162 | the git repository at the given `path`. 163 | 164 | The `callback` will be called with two arguments: An optional error 165 | object and a string containing the short-hash. 166 | 167 | Supports the following `options`: 168 | 169 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 170 | stderr - if exceeded child process is killed (default: `200*1024`) 171 | 172 | #### `commitSync(path[, options])` 173 | 174 | Synchronous version of `commit()`. 175 | 176 | Can throw error. This typically happens if you are running a too old 177 | version of Node.js (< 0.12), if git isn't found or if the path isn't 178 | a git repository. 179 | 180 | #### `stashes(path[, options], callback)` 181 | 182 | Get the amount of stashed changes in the git repository at the given 183 | `path`. 184 | 185 | The `callback` will be called with two arguments: An optional error 186 | object and a number representing the amount of stashed changes. 187 | 188 | Supports the following `options`: 189 | 190 | - `maxBuffer` - largest amount of data (in bytes) allowed on stdout or 191 | stderr - if exceeded child process is killed (default: `200*1024`) 192 | 193 | #### `stashesSync(path[, options])` 194 | 195 | Synchronous version of `stashes()`. 196 | 197 | Can throw error. This typically happens if you are running a too old 198 | version of Node.js (< 0.12), if git isn't found or if the path isn't 199 | a git repository. 200 | 201 | #### `message(path[, options], callback)` 202 | 203 | Get the commit message of the latest commit. 204 | 205 | The `callback` will be called with two arguments: An optional error 206 | object and a string containing the commit message. 207 | 208 | #### `messageSync(path[, options])` 209 | 210 | Synchronous version of `message()`. 211 | 212 | Can throw error. This typically happens if you are running a too old 213 | version of Node.js (< 0.12), if git isn't found or if the path isn't 214 | a git repository. 215 | 216 | ## Shell implementation 217 | 218 | Inside the [`bin`](https://github.com/watson/git-state/tree/master/bin) 219 | folder is a set of shell scripts which will perform the same checks as 220 | the `isGit()` and `check()` functions, but just in pure bash. This 221 | allows you for instance to modify your command prompt without having to 222 | invoke node (which can be kind of slow if done at every request). In 223 | fact this is exactly what the 224 | [git-ps1](https://github.com/watson/git-ps1) module does for you. 225 | 226 | - `bin/isgit` - exit code will be 0 if cwd is inside a git repo, 227 | otherwise 1 228 | - `bin/ahead` - exit code will be 0 if result is `0`, otherwise 1 229 | - `bin/branch` - exit code will be 0 if result is `master`, otherwise 1 230 | - `bin/dirty` - exit code will be 0 if result is `0`, otherwise 1 231 | - `bin/untracked` - exit code will be 0 if result is `0`, otherwise 1 232 | - `bin/stashes` - exit code will be 0 if result is `0`, otherwise 1 233 | - `bin/commit` - exit code will be 0 if a commit can be found, otherwise 1 234 | 235 | ## License 236 | 237 | [MIT](LICENSE) 238 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var path = require('path') 4 | var test = require('tape') 5 | var git = require('./') 6 | 7 | test('#isGit()', function (t) { 8 | var dir = process.cwd() 9 | git.isGit(dir, function (exists) { 10 | t.equal(exists, true) 11 | t.end() 12 | }) 13 | }) 14 | 15 | test('#isGit() negative', function (t) { 16 | var dir = path.join(process.cwd(), '..') 17 | git.isGit(dir, function (exists) { 18 | t.equal(exists, false) 19 | t.end() 20 | }) 21 | }) 22 | 23 | test('#isGitSync()', function (t) { 24 | var dir = process.cwd() 25 | var result = git.isGitSync(dir) 26 | t.equal(result, true) 27 | t.end() 28 | }) 29 | 30 | test('#check()', function (t) { 31 | var dir = process.cwd() 32 | git.check(dir, function (err, result) { 33 | t.error(err) 34 | t.deepEqual(Object.keys(result), ['branch', 'ahead', 'dirty', 'untracked', 'stashes']) 35 | t.equal(typeof result.branch, 'string') 36 | t.equal(typeof result.ahead, 'number') 37 | t.equal(typeof result.dirty, 'number') 38 | t.equal(typeof result.untracked, 'number') 39 | t.equal(typeof result.stashes, 'number') 40 | t.end() 41 | }) 42 | }) 43 | 44 | test('#check() with maxBuffer', function (t) { 45 | var dir = process.cwd() 46 | git.check(dir, {maxBuffer: 1}, testMaxBuffer(t)) 47 | }) 48 | 49 | test('#checkSync()', function (t) { 50 | var dir = process.cwd() 51 | try { 52 | var result = git.checkSync(dir) 53 | t.deepEqual(Object.keys(result), ['branch', 'ahead', 'dirty', 'untracked', 'stashes']) 54 | t.equal(typeof result.branch, 'string') 55 | t.equal(typeof result.ahead, 'number') 56 | t.equal(typeof result.dirty, 'number') 57 | t.equal(typeof result.untracked, 'number') 58 | t.equal(typeof result.stashes, 'number') 59 | } catch (err) { 60 | t.error(err) 61 | } 62 | t.end() 63 | }) 64 | 65 | test('#checkSync() with maxBuffer', function (t) { 66 | var dir = process.cwd() 67 | t.throws(function () { 68 | git.checkSync(dir, {maxBuffer: 1}) 69 | }, /ENOBUFS/) 70 | t.end() 71 | }) 72 | 73 | test('#untracked()', function (t) { 74 | var dir = process.cwd() 75 | git.untracked(dir, function (err, result) { 76 | t.error(err) 77 | t.equal(typeof result, 'number') 78 | t.end() 79 | }) 80 | }) 81 | 82 | test('#untracked() with maxBuffer', function (t) { 83 | var dir = process.cwd() 84 | git.untracked(dir, {maxBuffer: 1}, testMaxBuffer(t)) 85 | }) 86 | 87 | test('#untrackedSync()', function (t) { 88 | var dir = process.cwd() 89 | try { 90 | var result = git.untrackedSync(dir) 91 | t.equal(typeof result, 'number') 92 | } catch (err) { 93 | t.error(err) 94 | } 95 | t.end() 96 | }) 97 | 98 | test('#untrackedSync() with maxBuffer', function (t) { 99 | var dir = process.cwd() 100 | t.throws(function () { 101 | git.untrackedSync(dir, {maxBuffer: 1}) 102 | }, /ENOBUFS/) 103 | t.end() 104 | }) 105 | 106 | test('#dirty()', function (t) { 107 | var dir = process.cwd() 108 | git.dirty(dir, function (err, result) { 109 | t.error(err) 110 | t.equal(typeof result, 'number') 111 | t.end() 112 | }) 113 | }) 114 | 115 | test('#dirty() with maxBuffer', function (t) { 116 | var dir = process.cwd() 117 | git.dirty(dir, {maxBuffer: 1}, testMaxBuffer(t)) 118 | }) 119 | 120 | test('#dirtySync()', function (t) { 121 | var dir = process.cwd() 122 | try { 123 | var result = git.dirtySync(dir) 124 | t.equal(typeof result, 'number') 125 | } catch (err) { 126 | t.error(err) 127 | } 128 | t.end() 129 | }) 130 | 131 | test('#dirtySync() with maxBuffer', function (t) { 132 | var dir = process.cwd() 133 | t.throws(function () { 134 | git.dirtySync(dir, {maxBuffer: 1}) 135 | }, /ENOBUFS/) 136 | t.end() 137 | }) 138 | 139 | test('#branch()', function (t) { 140 | var dir = process.cwd() 141 | git.branch(dir, function (err, result) { 142 | t.error(err) 143 | t.equal(typeof result, 'string') 144 | t.end() 145 | }) 146 | }) 147 | 148 | test('#branch() with maxBuffer', function (t) { 149 | var dir = process.cwd() 150 | git.branch(dir, {maxBuffer: 1}, testMaxBuffer(t)) 151 | }) 152 | 153 | test('#branchSync()', function (t) { 154 | var dir = process.cwd() 155 | try { 156 | var result = git.branchSync(dir) 157 | t.equal(typeof result, 'string') 158 | } catch (err) { 159 | t.error(err) 160 | } 161 | t.end() 162 | }) 163 | 164 | test('#branchSync() with maxBuffer', function (t) { 165 | var dir = process.cwd() 166 | t.throws(function () { 167 | git.branchSync(dir, {maxBuffer: 1}) 168 | }, /ENOBUFS/) 169 | t.end() 170 | }) 171 | 172 | test('#ahead()', function (t) { 173 | var dir = process.cwd() 174 | git.ahead(dir, function (err, result) { 175 | t.error(err) 176 | t.equal(typeof result, 'number') 177 | t.end() 178 | }) 179 | }) 180 | 181 | // TODO: Find way to test this as currently none of the buffer is used 182 | // test('#ahead() with maxBuffer', function (t) { 183 | // var dir = process.cwd() 184 | // git.ahead(dir, {maxBuffer: 1}, testMaxBuffer(t)) 185 | // }) 186 | 187 | test('#aheadSync()', function (t) { 188 | var dir = process.cwd() 189 | try { 190 | var result = git.aheadSync(dir) 191 | t.equal(typeof result, 'number') 192 | } catch (err) { 193 | t.error(err) 194 | } 195 | t.end() 196 | }) 197 | 198 | // TODO: Find way to test this as currently none of the buffer is used 199 | // test('#aheadSync() with maxBuffer', function (t) { 200 | // var dir = process.cwd() 201 | // t.throws(function () { 202 | // git.aheadSync(dir, {maxBuffer: 1}) 203 | // }, /ENOBUFS/) 204 | // t.end() 205 | // }) 206 | 207 | test('#commit()', function (t) { 208 | var dir = process.cwd() 209 | git.commit(dir, function (err, result) { 210 | t.error(err) 211 | t.equal(typeof result, 'string') 212 | t.end() 213 | }) 214 | }) 215 | 216 | test('#commit() with maxBuffer', function (t) { 217 | var dir = process.cwd() 218 | git.commit(dir, {maxBuffer: 1}, testMaxBuffer(t)) 219 | }) 220 | 221 | test('#commitSync()', function (t) { 222 | var dir = process.cwd() 223 | try { 224 | var result = git.commitSync(dir) 225 | t.equal(typeof result, 'string') 226 | } catch (err) { 227 | t.error(err) 228 | } 229 | t.end() 230 | }) 231 | 232 | test('#commitSync() with maxBuffer', function (t) { 233 | var dir = process.cwd() 234 | t.throws(function () { 235 | git.commitSync(dir, {maxBuffer: 1}) 236 | }, /ENOBUFS/) 237 | t.end() 238 | }) 239 | 240 | test('#stashes()', function (t) { 241 | var dir = process.cwd() 242 | git.stashes(dir, function (err, result) { 243 | t.error(err) 244 | t.equal(typeof result, 'number') 245 | t.end() 246 | }) 247 | }) 248 | 249 | // TODO: Find way to test this as currently none of the buffer is used 250 | // test('#stashes() with maxBuffer', function (t) { 251 | // var dir = process.cwd() 252 | // git.stashes(dir, {maxBuffer: 1}, testMaxBuffer(t)) 253 | // }) 254 | 255 | test('#stashesSync()', function (t) { 256 | var dir = process.cwd() 257 | try { 258 | var result = git.stashesSync(dir) 259 | t.equal(typeof result, 'number') 260 | } catch (err) { 261 | t.error(err) 262 | } 263 | t.end() 264 | }) 265 | 266 | // TODO: Find way to test this as currently none of the buffer is used 267 | // test('#stashesSync() with maxBuffer', function (t) { 268 | // var dir = process.cwd() 269 | // t.throws(function () { 270 | // git.stashesSync(dir, {maxBuffer: 1}) 271 | // }, /ENOBUFS/) 272 | // t.end() 273 | // }) 274 | 275 | test('#message()', function (t) { 276 | var dir = process.cwd() 277 | git.message(dir, function (err, result) { 278 | t.error(err) 279 | console.log(JSON.stringify(result)) 280 | t.equal(typeof result, 'string') 281 | t.ok(result.length > 0, 'message should be longer than 0 bytes') 282 | t.ok(/^[^\s].*[^\s]$/.test(result), 'should not have leading or trailing whitespace') 283 | t.end() 284 | }) 285 | }) 286 | 287 | test('#messageSync()', function (t) { 288 | var dir = process.cwd() 289 | try { 290 | var result = git.messageSync(dir) 291 | t.equal(typeof result, 'string') 292 | t.ok(result.length > 0, 'message should be longer than 0 bytes') 293 | t.ok(/^[^\s].*[^\s]$/.test(result), 'should not have leading or trailing whitespace') 294 | } catch (err) { 295 | t.error(err) 296 | } 297 | t.end() 298 | }) 299 | 300 | function testMaxBuffer (t) { 301 | return function (err) { 302 | t.ok(err) 303 | if (err.code) { 304 | t.equal(err.code, 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') 305 | } else { 306 | t.equal(err.message, 'stdout maxBuffer exceeded') 307 | } 308 | t.end() 309 | } 310 | } 311 | --------------------------------------------------------------------------------