simple-git
Advanced tools
Comparing version 1.14.0 to 1.15.0
@@ -8,2 +8,6 @@ module.exports = function (grunt) { | ||
nodeunit: { | ||
all: ['test/test*.js'] | ||
}, | ||
release: { | ||
@@ -19,2 +23,3 @@ options: { | ||
grunt.loadNpmTasks('grunt-contrib-nodeunit'); | ||
grunt.loadNpmTasks('grunt-release-steps'); | ||
@@ -26,8 +31,9 @@ | ||
grunt.registerTask('patch', ['release:bump:patch', '-to-git']); | ||
grunt.registerTask('minor', ['release:bump:minor', '-tag', '-to-git', '-to-npm']); | ||
grunt.registerTask('major', ['release:bump:major', '-tag', '-to-git', '-to-npm']); | ||
grunt.registerTask('patch', ['test', 'release:bump:patch', '-to-git']); | ||
grunt.registerTask('minor', ['test', 'release:bump:minor', '-tag', '-to-git', '-to-npm']); | ||
grunt.registerTask('major', ['test', 'release:bump:major', '-tag', '-to-git', '-to-npm']); | ||
grunt.registerTask('default', ['patch']); | ||
grunt.registerTask('test', ['nodeunit:all']); | ||
}; |
{ | ||
"name": "simple-git", | ||
"description": "Simple GIT interface for node.js", | ||
"version": "1.14.0", | ||
"version": "1.15.0", | ||
"author": "Steve King <steve@mydev.co>", | ||
@@ -15,2 +15,3 @@ "contributors": [ | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-nodeunit": "^0.4.1", | ||
"grunt-release-steps": "~0.3.7", | ||
@@ -17,0 +18,0 @@ "nodeunit": "^0.9.1", |
@@ -44,2 +44,4 @@ # Simple Git | ||
`.addAnnotatedTag(tagName, tagMessage, handlerFn)` adds an annotated tag to the head of the current branch | ||
`.log([options], handlerFn)` list commits between `options.from` and `options.to` tags or branch | ||
@@ -46,0 +48,0 @@ (if not specified will show all history). Additionally you can provide `options.file`, which is the path to a file in |
1483
src/git.js
(function () { | ||
/** | ||
* Git handling for node. All public functions can be chained and all `then` handlers are optional. | ||
* | ||
* @param {String} baseDir base directory for all processes to run | ||
* | ||
* @param {Function} ChildProcess The ChildProcess constructor to use | ||
* @param {Function} Buffer The Buffer implementation to use | ||
* | ||
* @constructor | ||
*/ | ||
function Git (baseDir, ChildProcess, Buffer) { | ||
this._baseDir = baseDir; | ||
this._runCache = []; | ||
/** | ||
* Git handling for node. All public functions can be chained and all `then` handlers are optional. | ||
* | ||
* @param {string} baseDir base directory for all processes to run | ||
* | ||
* @param {Function} ChildProcess The ChildProcess constructor to use | ||
* @param {Function} Buffer The Buffer implementation to use | ||
* | ||
* @constructor | ||
*/ | ||
function Git (baseDir, ChildProcess, Buffer) { | ||
this._baseDir = baseDir; | ||
this._runCache = []; | ||
this.ChildProcess = ChildProcess; | ||
this.Buffer = Buffer; | ||
} | ||
this.ChildProcess = ChildProcess; | ||
this.Buffer = Buffer; | ||
} | ||
/** | ||
* @type {string} The command to use to reference the git binary | ||
*/ | ||
Git.prototype._command = 'git'; | ||
/** | ||
* @type {string} The command to use to reference the git binary | ||
*/ | ||
Git.prototype._command = 'git'; | ||
/** | ||
* @type {Function} An optional handler to use when a child process is created | ||
*/ | ||
Git.prototype._outputHandler = null; | ||
/** | ||
* @type {Function} An optional handler to use when a child process is created | ||
*/ | ||
Git.prototype._outputHandler = null; | ||
/** | ||
* @type {boolean} Property showing whether logging will be silenced - defaults to true in a production environment | ||
*/ | ||
Git.prototype._silentLogging = /prod/.test(process.env.NODE_ENV); | ||
/** | ||
* @type {boolean} Property showing whether logging will be silenced - defaults to true in a production environment | ||
*/ | ||
Git.prototype._silentLogging = /prod/.test(process.env.NODE_ENV); | ||
/** | ||
* Sets the path to a custom git binary, should either be `git` when there is an installation of git available on | ||
* the system path, or a fully qualified path to the executable. | ||
* | ||
* @param {string} command | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.customBinary = function (command) { | ||
this._command = command; | ||
return this; | ||
}; | ||
/** | ||
* Sets the path to a custom git binary, should either be `git` when there is an installation of git available on | ||
* the system path, or a fully qualified path to the executable. | ||
* | ||
* @param {string} command | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.customBinary = function (command) { | ||
this._command = command; | ||
return this; | ||
}; | ||
/** | ||
* Sets a handler function to be called whenever a new child process is created, the handler function will be called | ||
* with the name of the command being run and the stdout & stderr streams used by the ChildProcess. | ||
* | ||
* @example | ||
* require('simple-git') | ||
* .outputHandler(function (command, stdout, stderr) { | ||
/** | ||
* Sets a handler function to be called whenever a new child process is created, the handler function will be called | ||
* with the name of the command being run and the stdout & stderr streams used by the ChildProcess. | ||
* | ||
* @example | ||
* require('simple-git') | ||
* .outputHandler(function (command, stdout, stderr) { | ||
* stdout.pipe(process.stdout); | ||
* }) | ||
* .checkout('https://github.com/user/repo.git'); | ||
* | ||
* @see http://nodejs.org/api/child_process.html#child_process_class_childprocess | ||
* @see http://nodejs.org/api/stream.html#stream_class_stream_readable | ||
* @param {Function} outputHandler | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.outputHandler = function (outputHandler) { | ||
this._outputHandler = outputHandler; | ||
return this; | ||
}; | ||
* .checkout('https://github.com/user/repo.git'); | ||
* | ||
* @see http://nodejs.org/api/child_process.html#child_process_class_childprocess | ||
* @see http://nodejs.org/api/stream.html#stream_class_stream_readable | ||
* @param {Function} outputHandler | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.outputHandler = function (outputHandler) { | ||
this._outputHandler = outputHandler; | ||
return this; | ||
}; | ||
/** | ||
* Initialize a git repo | ||
* | ||
* @param {Boolean} [bare=false] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.init = function (bare, then) { | ||
var commands = ['init']; | ||
var next = Git.trailingFunctionArgument(arguments); | ||
/** | ||
* Initialize a git repo | ||
* | ||
* @param {Boolean} [bare=false] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.init = function (bare, then) { | ||
var commands = ['init']; | ||
var next = Git.trailingFunctionArgument(arguments); | ||
if (bare === true) { | ||
commands.push('--bare'); | ||
} | ||
if (bare === true) { | ||
commands.push('--bare'); | ||
} | ||
return this._run(commands, function (err) { | ||
next && next(err); | ||
}); | ||
}; | ||
return this._run(commands, function (err) { | ||
next && next(err); | ||
}); | ||
}; | ||
/** | ||
* Check the status of the local repo | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.status = function (then) { | ||
return this._run(['status', '--porcelain'], function (err, data) { | ||
then && then(err, !err && this._parseStatus(data)); | ||
}); | ||
}; | ||
/** | ||
* Check the status of the local repo | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.status = function (then) { | ||
return this._run(['status', '--porcelain'], function (err, data) { | ||
then && then(err, !err && this._parseStatus(data)); | ||
}); | ||
}; | ||
/** | ||
* Clone a git repo | ||
* | ||
* @param {String} repoPath | ||
* @param {String} localPath | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.clone = function (repoPath, localPath, then) { | ||
return this._run(['clone', repoPath, localPath], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Clone a git repo | ||
* | ||
* @param {string} repoPath | ||
* @param {string} localPath | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.clone = function (repoPath, localPath, then) { | ||
return this._run(['clone', repoPath, localPath], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Internally uses pull and tags to get the list of tags then checks out the latest tag. | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutLatestTag = function (then) { | ||
var git = this; | ||
return this.pull().tags(function (err, tags) { | ||
git.checkout(tags.latest, then); | ||
}); | ||
}; | ||
/** | ||
* Internally uses pull and tags to get the list of tags then checks out the latest tag. | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutLatestTag = function (then) { | ||
var git = this; | ||
return this.pull().tags(function (err, tags) { | ||
git.checkout(tags.latest, then); | ||
}); | ||
}; | ||
/** | ||
* Adds one or more files to source control | ||
* | ||
* @param {String|String[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.add = function (files, then) { | ||
return this._run(['add'].concat(files), function (err, data) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Adds one or more files to source control | ||
* | ||
* @param {string|string[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.add = function (files, then) { | ||
return this._run(['add'].concat(files), function (err, data) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Commits changes in the current working directory - when specific file paths are supplied, only changes on those | ||
* files will be committed. | ||
* | ||
* @param {String} message | ||
* @param {String|String[]} [files] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.commit = function (message, files, then) { | ||
var git = this; | ||
if (!then && typeof files === "function") { | ||
then = files; | ||
files = []; | ||
} | ||
/** | ||
* Commits changes in the current working directory - when specific file paths are supplied, only changes on those | ||
* files will be committed. | ||
* | ||
* @param {string} message | ||
* @param {string|string[]} [files] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.commit = function (message, files, then) { | ||
var git = this; | ||
if (!then && typeof files === "function") { | ||
then = files; | ||
files = []; | ||
} | ||
return this._run(['commit', '-m', message].concat([].concat(files || [])), function (err, data) { | ||
then && then(err, !err && require('./CommitSummary').parse(data)); | ||
}); | ||
}; | ||
return this._run(['commit', '-m', message].concat([].concat(files || [])), function (err, data) { | ||
then && then(err, !err && require('./CommitSummary').parse(data)); | ||
}); | ||
}; | ||
/** | ||
* Gets a function to be used for logging. | ||
* | ||
* @param {string} level | ||
* @param {string} [message] | ||
* | ||
* @returns {Function} | ||
* @private | ||
*/ | ||
Git.prototype._getLog = function (level, message) { | ||
var log = this._silentLogging ? function () {} : console[level].bind(console); | ||
if (arguments.length > 1) { | ||
log(message); | ||
} | ||
return log; | ||
}; | ||
/** | ||
* Gets a function to be used for logging. | ||
* | ||
* @param {string} level | ||
* @param {string} [message] | ||
* | ||
* @returns {Function} | ||
* @private | ||
*/ | ||
Git.prototype._getLog = function (level, message) { | ||
var log = this._silentLogging ? function () { | ||
} : console[level].bind(console); | ||
if (arguments.length > 1) { | ||
log(message); | ||
} | ||
return log; | ||
}; | ||
/** | ||
* Pull the updated contents of the current repo | ||
* @param {String} [remote] | ||
* @param {String} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.pull = function (remote, branch, then) { | ||
var command = ["pull"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
/** | ||
* Pull the updated contents of the current repo | ||
* @param {string} [remote] | ||
* @param {string} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.pull = function (remote, branch, then) { | ||
var command = ["pull"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && this._parsePull(data)); | ||
}); | ||
}; | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && this._parsePull(data)); | ||
}); | ||
}; | ||
/** | ||
* Fetch the updated contents of the current repo. | ||
* | ||
* @example | ||
* .fetch('upstream', 'master') // fetches from master on remote named upstream | ||
* .fetch(function () {}) // runs fetch against default remote and branch and calls function | ||
* | ||
* @param {String} [remote] | ||
* @param {String} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.fetch = function (remote, branch, then) { | ||
var command = ["fetch"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
/** | ||
* Fetch the updated contents of the current repo. | ||
* | ||
* @example | ||
* .fetch('upstream', 'master') // fetches from master on remote named upstream | ||
* .fetch(function () {}) // runs fetch against default remote and branch and calls function | ||
* | ||
* @param {string} [remote] | ||
* @param {string} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.fetch = function (remote, branch, then) { | ||
var command = ["fetch"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && this._parseFetch(data)); | ||
}); | ||
}; | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && this._parseFetch(data)); | ||
}); | ||
}; | ||
/** | ||
* Disables/enables the use of the console for printing warnings and errors, by default messages are not shown in | ||
* a production environment. | ||
* | ||
* @param {boolean} silence | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.silent = function (silence) { | ||
this._silentLogging = !!silence; | ||
return this; | ||
}; | ||
/** | ||
* Disables/enables the use of the console for printing warnings and errors, by default messages are not shown in | ||
* a production environment. | ||
* | ||
* @param {boolean} silence | ||
* @returns {Git} | ||
*/ | ||
Git.prototype.silent = function (silence) { | ||
this._silentLogging = !!silence; | ||
return this; | ||
}; | ||
/** | ||
* List all tags | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.tags = function (then) { | ||
return this._run(['tag', '-l'], function (err, data) { | ||
then && then(err, !err && this._parseListTags(data)); | ||
}); | ||
}; | ||
/** | ||
* List all tags | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.tags = function (then) { | ||
return this.tag(['-l'], function (err, data) { | ||
then && then(err, !err && this._parseListTags(data)); | ||
}); | ||
}; | ||
/** | ||
* Reset a repo | ||
* | ||
* @param {string} [mode=soft] Either 'soft' or 'hard' | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.reset = function (mode, then) { | ||
var resetMode = '--' + (mode === 'hard' ? mode : 'soft'); | ||
var next = (typeof arguments[arguments.length - 1] === "function") ? arguments[arguments.length - 1] : null; | ||
/** | ||
* Reset a repo | ||
* | ||
* @param {string} [mode=soft] Either 'soft' or 'hard' | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.reset = function (mode, then) { | ||
var resetMode = '--' + (mode === 'hard' ? mode : 'soft'); | ||
var next = (typeof arguments[arguments.length - 1] === "function") ? arguments[arguments.length - 1] : null; | ||
return this._run(['reset', resetMode], function (err) { | ||
next && next(err || null); | ||
}); | ||
}; | ||
return this._run(['reset', resetMode], function (err) { | ||
next && next(err || null); | ||
}); | ||
}; | ||
/** | ||
* Add a lightweight tag to the head of the current branch | ||
* | ||
* @param {String} name | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.addTag = function (name, then) { | ||
return this._run(['tag', name], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Add a lightweight tag to the head of the current branch | ||
* | ||
* @param {string} name | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.addTag = function (name, then) { | ||
if (typeof name !== "string") { | ||
return this.then(function () { | ||
then && then(new TypeError("Git.addTag requires a tag name")); | ||
}); | ||
} | ||
/** | ||
* Check out a tag or revision | ||
* | ||
* @param {String} what | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkout = function (what, then) { | ||
return this._run(['checkout', what], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
return this.tag([name], then); | ||
}; | ||
/** | ||
* Check out a remote branch | ||
* | ||
* @param {String} branchName name of branch | ||
* @param {String} startPoint (e.g origin/development) | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutBranch = function (branchName, startPoint, then) { | ||
return this._run(['checkout', '-b', branchName, startPoint], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
/** | ||
* Add an annotated tag to the head of the current branch | ||
* | ||
* @param {string} tagName | ||
* @param {string} tagMessage | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.addAnnotatedTag = function (tagName, tagMessage, then) { | ||
return this.tag(['-a', '-m', tagMessage, tagName], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Check out a local branch | ||
* | ||
* @param {String} branchName of branch | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutLocalBranch = function (branchName, then) { | ||
return this._run(['checkout', '-b', branchName], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
/** | ||
* Check out a tag or revision | ||
* | ||
* @param {string} what | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkout = function (what, then) { | ||
return this._run(['checkout', what], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
/** | ||
* Add a submodule | ||
* | ||
* @param {String} repo | ||
* @param {String} path | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.submoduleAdd = function (repo, path, then) { | ||
return this._run(['submodule', 'add', repo, path], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
/** | ||
* Check out a remote branch | ||
* | ||
* @param {string} branchName name of branch | ||
* @param {string} startPoint (e.g origin/development) | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutBranch = function (branchName, startPoint, then) { | ||
return this._run(['checkout', '-b', branchName, startPoint], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
/** | ||
* List remote | ||
* | ||
* @param {String[]} [args] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.listRemote = function (args, then) { | ||
var next = Git.trailingFunctionArgument(arguments); | ||
var data = next === args || args === undefined ? [] : args; | ||
/** | ||
* Check out a local branch | ||
* | ||
* @param {string} branchName of branch | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.checkoutLocalBranch = function (branchName, then) { | ||
return this._run(['checkout', '-b', branchName], function (err, data) { | ||
then && then(err, !err && this._parseCheckout(data)); | ||
}); | ||
}; | ||
if (typeof data === 'string') { | ||
this._getLog('warn', 'Git#listRemote: args should be supplied as an array of individual arguments'); | ||
} | ||
/** | ||
* Add a submodule | ||
* | ||
* @param {string} repo | ||
* @param {string} path | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.submoduleAdd = function (repo, path, then) { | ||
return this._run(['submodule', 'add', repo, path], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
return this._run(['ls-remote'].concat(data), function (err, data) { | ||
next && next(err, data); | ||
}); | ||
}; | ||
/** | ||
* List remote | ||
* | ||
* @param {string[]} [args] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.listRemote = function (args, then) { | ||
var next = Git.trailingFunctionArgument(arguments); | ||
var data = next === args || args === undefined ? [] : args; | ||
/** | ||
* Adds a remote to the list of remotes. | ||
* | ||
* @param {String} remoteName Name of the repository - eg "upstream" | ||
* @param {String} remoteRepo Fully qualified SSH or HTTP(S) path to the remote repo | ||
* @param {Function} [then] | ||
* @returns {*} | ||
*/ | ||
Git.prototype.addRemote = function (remoteName, remoteRepo, then) { | ||
return this._run(['remote', 'add', remoteName, remoteRepo], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
if (typeof data === 'string') { | ||
this._getLog('warn', 'Git#listRemote: args should be supplied as an array of individual arguments'); | ||
} | ||
/** | ||
* Removes an entry from the list of remotes. | ||
* | ||
* @param {String} remoteName Name of the repository - eg "upstream" | ||
* @param {Function} [then] | ||
* @returns {*} | ||
*/ | ||
Git.prototype.removeRemote = function (remoteName, then) { | ||
return this._run(['remote', 'remove', remoteName], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
return this._run(['ls-remote'].concat(data), function (err, data) { | ||
next && next(err, data); | ||
}); | ||
}; | ||
/** | ||
* Gets the currently available remotes, setting the optional verbose argument to true includes additional | ||
* detail on the remotes themselves. | ||
* | ||
* @param {boolean} [verbose=false] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.getRemotes = function (verbose, then) { | ||
var next = Git.trailingFunctionArgument(arguments); | ||
var args = verbose === true ? ['-v'] : []; | ||
/** | ||
* Adds a remote to the list of remotes. | ||
* | ||
* @param {string} remoteName Name of the repository - eg "upstream" | ||
* @param {string} remoteRepo Fully qualified SSH or HTTP(S) path to the remote repo | ||
* @param {Function} [then] | ||
* @returns {*} | ||
*/ | ||
Git.prototype.addRemote = function (remoteName, remoteRepo, then) { | ||
return this._run(['remote', 'add', remoteName, remoteRepo], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
return this.remote(args, function (err, data) { | ||
next(err, !err && function () { | ||
return data.trim().split('\n').reduce(function (remotes, remote) { | ||
var detail = remote.trim().split(/\s+/); | ||
var name = detail.shift(); | ||
/** | ||
* Removes an entry from the list of remotes. | ||
* | ||
* @param {string} remoteName Name of the repository - eg "upstream" | ||
* @param {Function} [then] | ||
* @returns {*} | ||
*/ | ||
Git.prototype.removeRemote = function (remoteName, then) { | ||
return this._run(['remote', 'remove', remoteName], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
if (!remotes[name]) { | ||
remotes[name] = remotes[remotes.length] = { | ||
name: name, | ||
refs: {} | ||
}; | ||
} | ||
/** | ||
* Gets the currently available remotes, setting the optional verbose argument to true includes additional | ||
* detail on the remotes themselves. | ||
* | ||
* @param {boolean} [verbose=false] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.getRemotes = function (verbose, then) { | ||
var next = Git.trailingFunctionArgument(arguments); | ||
var args = verbose === true ? ['-v'] : []; | ||
if (detail.length) { | ||
remotes[name].refs[detail.pop().replace(/[^a-z]/g, '')] = detail.pop(); | ||
} | ||
return this.remote(args, function (err, data) { | ||
next(err, !err && function () { | ||
return data.trim().split('\n').reduce(function (remotes, remote) { | ||
var detail = remote.trim().split(/\s+/); | ||
var name = detail.shift(); | ||
return remotes; | ||
}, []).slice(0); | ||
}()); | ||
}); | ||
}; | ||
if (!remotes[name]) { | ||
remotes[name] = remotes[remotes.length] = { | ||
name: name, | ||
refs: {} | ||
}; | ||
} | ||
/** | ||
* Call any `git remote` function with arguments passed as an array of strings. | ||
* | ||
* @param {string[]} options | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.remote = function (options, then) { | ||
if (!Array.isArray(options)) { | ||
return this.then(function () { | ||
then && then(new TypeError("Git.remote requires an array of arguments")); | ||
}); | ||
} | ||
if (detail.length) { | ||
remotes[name].refs[detail.pop().replace(/[^a-z]/g, '')] = detail.pop(); | ||
} | ||
if (options[0] !== 'remote') { | ||
options.unshift('remote'); | ||
} | ||
return remotes; | ||
}, []).slice(0); | ||
}()); | ||
}); | ||
}; | ||
return this._run(options, function (err, data) { | ||
then && then(err || null, err ? null : data); | ||
}); | ||
}; | ||
/** | ||
* Call any `git remote` function with arguments passed as an array of strings. | ||
* | ||
* @param {string[]} options | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.remote = function (options, then) { | ||
if (!Array.isArray(options)) { | ||
return this.then(function () { | ||
then && then(new TypeError("Git.remote requires an array of arguments")); | ||
}); | ||
} | ||
/** | ||
* Pushes the current committed changes to a remote, optionally specify the names of the remote and branch to use | ||
* when pushing. | ||
* | ||
* @param {String} [remote] | ||
* @param {String} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.push = function (remote, branch, then) { | ||
var command = ["push"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
if (options[0] !== 'remote') { | ||
options.unshift('remote'); | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && data); | ||
}); | ||
}; | ||
return this._run(options, function (err, data) { | ||
then && then(err || null, err ? null : data); | ||
}); | ||
}; | ||
/** | ||
* Pushes the current tag changes to a remote which can be either a URL or named remote. When not specified uses the | ||
* default configured remote spec. | ||
* | ||
* @param {String} [remote] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.pushTags = function (remote, then) { | ||
var command = ['push']; | ||
if (typeof remote === "string") { | ||
command.push(remote); | ||
} | ||
command.push('--tags'); | ||
/** | ||
* Call any `git tag` function with arguments passed as an array of strings. | ||
* | ||
* @param {string[]} options | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.tag = function (options, then) { | ||
if (!Array.isArray(options)) { | ||
return this.then(function () { | ||
then && then(new TypeError("Git.tag requires an array of arguments")); | ||
}); | ||
} | ||
then = typeof arguments[arguments.length - 1] === "function" ? arguments[arguments.length - 1] : null; | ||
if (options[0] !== 'tag') { | ||
options.unshift('tag'); | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && data); | ||
}); | ||
}; | ||
return this._run(options, function (err, data) { | ||
then && then(err || null, err ? null : data); | ||
}); | ||
}; | ||
/** | ||
* Removes the named files from source control. | ||
* | ||
* @param {String|String[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.rm = function (files, then) { | ||
return this._rm(files, '-f', then); | ||
}; | ||
/** | ||
* Pushes the current committed changes to a remote, optionally specify the names of the remote and branch to use | ||
* when pushing. | ||
* | ||
* @param {string} [remote] | ||
* @param {string} [branch] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.push = function (remote, branch, then) { | ||
var command = ["push"]; | ||
if (typeof remote === 'string' && typeof branch === 'string') { | ||
command.push(remote, branch); | ||
} | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
/** | ||
* Removes the named files from source control but keeps them on disk rather than deleting them entirely. To | ||
* completely remove the files, use `rm`. | ||
* | ||
* @param {String|String[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.rmKeepLocal = function (files, then) { | ||
return this._rm(files, '--cached', then); | ||
}; | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && data); | ||
}); | ||
}; | ||
/** | ||
* Return repository changes. | ||
* | ||
* @param {String} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.diff = function (options, then) { | ||
var command = ['diff']; | ||
/** | ||
* Pushes the current tag changes to a remote which can be either a URL or named remote. When not specified uses the | ||
* default configured remote spec. | ||
* | ||
* @param {string} [remote] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.pushTags = function (remote, then) { | ||
var command = ['push']; | ||
if (typeof remote === "string") { | ||
command.push(remote); | ||
} | ||
command.push('--tags'); | ||
if (typeof options === 'string') { | ||
command[0] += ' ' + options; | ||
this._getLog('warn', | ||
'Git#diff: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
then = typeof arguments[arguments.length - 1] === "function" ? arguments[arguments.length - 1] : null; | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, !err && data); | ||
}); | ||
}; | ||
return this._run(command, function (err, data) { | ||
then && then(err, data); | ||
}); | ||
}; | ||
/** | ||
* Removes the named files from source control. | ||
* | ||
* @param {string|string[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.rm = function (files, then) { | ||
return this._rm(files, '-f', then); | ||
}; | ||
/** | ||
* rev-parse. | ||
* | ||
* @param {String|String[]} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.revparse = function(options, then) { | ||
var command = ['rev-parse']; | ||
/** | ||
* Removes the named files from source control but keeps them on disk rather than deleting them entirely. To | ||
* completely remove the files, use `rm`. | ||
* | ||
* @param {string|string[]} files | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.rmKeepLocal = function (files, then) { | ||
return this._rm(files, '--cached', then); | ||
}; | ||
if (typeof options === 'string') { | ||
command = command + ' ' + options; | ||
this._getLog('warn', | ||
'Git#revparse: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
/** | ||
* Return repository changes. | ||
* | ||
* @param {string} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.diff = function (options, then) { | ||
var command = ['diff']; | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
if (typeof options === 'string') { | ||
command[0] += ' ' + options; | ||
this._getLog('warn', | ||
'Git#diff: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
return this._run(command, function(err, data) { | ||
then && then(err, data); | ||
}); | ||
}; | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
/** | ||
* Show various types of objects, for example the file at a certain commit | ||
* | ||
* @param {String} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.show = function(options, then) { | ||
var args = [].slice.call(arguments, 0); | ||
var handler = typeof args[args.length - 1] === "function" ? args.pop() : null; | ||
var command = ['show']; | ||
if (typeof options === 'string') { | ||
command = command + ' ' + options; | ||
this._getLog('warn', | ||
'Git#show: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
return this._run(command, function (err, data) { | ||
then && then(err, data); | ||
}); | ||
}; | ||
return this._run(command, function(err, data) { | ||
handler && handler(err, !err && data); | ||
}); | ||
}; | ||
/** | ||
* rev-parse. | ||
* | ||
* @param {string|string[]} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.revparse = function (options, then) { | ||
var command = ['rev-parse']; | ||
/** | ||
* Call a simple function | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.then = function (then) { | ||
this._run([], function () { | ||
typeof then === 'function' && then(); | ||
}); | ||
return this; | ||
}; | ||
if (typeof options === 'string') { | ||
command = command + ' ' + options; | ||
this._getLog('warn', | ||
'Git#revparse: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
/** | ||
* Show commit logs. | ||
* | ||
* @param {Object} [options] | ||
* @param {string} [options.from] The first commit to include | ||
* @param {string} [options.to] The most recent commit to include | ||
* @param {string} [options.file] A single file to include in the result | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.log = function (options, then) { | ||
var command = ["log", "--pretty=format:'%H;%ai;%s%d;%aN;%ae'"]; | ||
var opt = {}; | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
then = arguments[arguments.length - 1]; | ||
} | ||
var args = [].slice.call(arguments, 0); | ||
var handler = typeof args[args.length - 1] === "function" ? args.pop() : null; | ||
return this._run(command, function (err, data) { | ||
then && then(err, data); | ||
}); | ||
}; | ||
if (!args.length) { | ||
opt = {}; | ||
} | ||
else if (typeof args[0] === "object") { | ||
opt = args[0]; | ||
} | ||
else if (typeof args[0] === "string" || typeof args[1] === "string") { | ||
this._getLog('warn', | ||
'Git#log: supplying to or from as strings is now deprecated, switch to an options configuration object'); | ||
opt = { | ||
from: args[0], | ||
to: args[1] | ||
}; | ||
} | ||
/** | ||
* Show various types of objects, for example the file at a certain commit | ||
* | ||
* @param {string} [options] | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.show = function (options, then) { | ||
var args = [].slice.call(arguments, 0); | ||
var handler = typeof args[args.length - 1] === "function" ? args.pop() : null; | ||
var command = ['show']; | ||
if (typeof options === 'string') { | ||
command = command + ' ' + options; | ||
this._getLog('warn', | ||
'Git#show: supplying options as a single string is now deprecated, switch to an array of strings'); | ||
} | ||
else if (Array.isArray(options)) { | ||
command.push.apply(command, options); | ||
} | ||
if (opt.from && opt.to) { | ||
command.push(opt.from + "..." + opt.to); | ||
} | ||
return this._run(command, function (err, data) { | ||
handler && handler(err, !err && data); | ||
}); | ||
}; | ||
if (opt.file) { | ||
command.push("--follow", options.file); | ||
} | ||
/** | ||
* Call a simple function | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.then = function (then) { | ||
this._run([], function () { | ||
typeof then === 'function' && then(); | ||
}); | ||
return this; | ||
}; | ||
if (opt.n || opt['max-count']) { | ||
command.push("--max-count=" + (opt.n || opt['max-count'])); | ||
} | ||
/** | ||
* Show commit logs. | ||
* | ||
* @param {Object} [options] | ||
* @param {string} [options.from] The first commit to include | ||
* @param {string} [options.to] The most recent commit to include | ||
* @param {string} [options.file] A single file to include in the result | ||
* | ||
* @param {Function} [then] | ||
*/ | ||
Git.prototype.log = function (options, then) { | ||
var command = ["log", "--pretty=format:'%H;%ai;%s%d;%aN;%ae'"]; | ||
var opt = {}; | ||
return this._run(command, function (err, data) { | ||
handler && handler(err, !err && this._parseListLog(data)); | ||
}); | ||
}; | ||
var args = [].slice.call(arguments, 0); | ||
var handler = typeof args[args.length - 1] === "function" ? args.pop() : null; | ||
Git.prototype._rm = function (files, options, then) { | ||
return this._run(['rm', options, [].concat(files)], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
if (!args.length) { | ||
opt = {}; | ||
} | ||
else if (typeof args[0] === "object") { | ||
opt = args[0]; | ||
} | ||
else if (typeof args[0] === "string" || typeof args[1] === "string") { | ||
this._getLog('warn', | ||
'Git#log: supplying to or from as strings is now deprecated, switch to an options configuration object'); | ||
opt = { | ||
from: args[0], | ||
to: args[1] | ||
}; | ||
} | ||
Git.prototype._parsePull = function (pull) { | ||
var changes = { | ||
files: [], | ||
insertions: {}, | ||
deletions: {}, | ||
summary: { | ||
changes: 0, | ||
insertions: 0, | ||
deletions: 0 | ||
} | ||
}; | ||
if (opt.from && opt.to) { | ||
command.push(opt.from + "..." + opt.to); | ||
} | ||
var fileUpdateRegex = /^\s*(.+)\s\|\s(\d+)\s([\+]+)/; | ||
for (var lines = pull.split('\n'), i = 0, l = lines.length; i < l; i++) { | ||
var update = fileUpdateRegex.exec(lines[i]); | ||
if (opt.file) { | ||
command.push("--follow", options.file); | ||
} | ||
// search for update statement for each file | ||
if (update) { | ||
changes.files.push(update[1]); | ||
if (opt.n || opt['max-count']) { | ||
command.push("--max-count=" + (opt.n || opt['max-count'])); | ||
} | ||
var insertions = update[3].length; | ||
if (insertions) { | ||
changes.insertions[update[1]] = insertions; | ||
} | ||
if (update[2] > insertions) { | ||
changes.deletions[update[1]] = update[2] - insertions; | ||
} | ||
} | ||
return this._run(command, function (err, data) { | ||
handler && handler(err, !err && this._parseListLog(data)); | ||
}); | ||
}; | ||
// summary appears after updates | ||
else if (changes.files.length && (update = /(\d+)\D+(\d+)\D+(\d+)/.exec(lines[i]))) { | ||
changes.summary.changes = +update[1]; | ||
changes.summary.insertions = +update[2]; | ||
changes.summary.deletions = +update[3]; | ||
} | ||
} | ||
Git.prototype._rm = function (files, options, then) { | ||
return this._run(['rm', options, [].concat(files)], function (err) { | ||
then && then(err); | ||
}); | ||
}; | ||
return changes; | ||
}; | ||
Git.prototype._parsePull = function (pull) { | ||
var changes = { | ||
files: [], | ||
insertions: {}, | ||
deletions: {}, | ||
summary: { | ||
changes: 0, | ||
insertions: 0, | ||
deletions: 0 | ||
} | ||
}; | ||
Git.prototype._parseListTags = function (tags) { | ||
var tagList = tags.split('\n').sort(function (tagA, tagB) { | ||
var partsA = tagA.split('.'); | ||
var partsB = tagB.split('.'); | ||
var fileUpdateRegex = /^\s*(.+)\s\|\s(\d+)\s([\+]+)/; | ||
for (var lines = pull.split('\n'), i = 0, l = lines.length; i < l; i++) { | ||
var update = fileUpdateRegex.exec(lines[i]); | ||
for (var i = 0, l = Math.max(partsA.length, partsB.length); i < l; i++) { | ||
var diff = partsA[i] - partsB[i]; | ||
if (diff) { | ||
return diff > 0 ? 1 : -1; | ||
} | ||
// search for update statement for each file | ||
if (update) { | ||
changes.files.push(update[1]); | ||
var insertions = update[3].length; | ||
if (insertions) { | ||
changes.insertions[update[1]] = insertions; | ||
} | ||
if (update[2] > insertions) { | ||
changes.deletions[update[1]] = update[2] - insertions; | ||
} | ||
} | ||
return 0; | ||
}); | ||
// summary appears after updates | ||
else if (changes.files.length && (update = /(\d+)\D+(\d+)\D+(\d+)/.exec(lines[i]))) { | ||
changes.summary.changes = +update[1]; | ||
changes.summary.insertions = +update[2]; | ||
changes.summary.deletions = +update[3]; | ||
} | ||
} | ||
return { | ||
latest: tagList.length && tagList[tagList.length - 1], | ||
all: tagList | ||
}; | ||
}; | ||
return changes; | ||
}; | ||
Git.prototype._parseStatus = function (status) { | ||
var line; | ||
var lines = status.trim().split('\n'); | ||
Git.prototype._parseListTags = function (tags) { | ||
var tagList = tags.split('\n').sort(function (tagA, tagB) { | ||
var partsA = tagA.split('.'); | ||
var partsB = tagB.split('.'); | ||
var not_added = []; | ||
var deleted = []; | ||
var modified = []; | ||
var created = []; | ||
for (var i = 0, l = Math.max(partsA.length, partsB.length); i < l; i++) { | ||
var diff = partsA[i] - partsB[i]; | ||
if (diff) { | ||
return diff > 0 ? 1 : -1; | ||
} | ||
} | ||
var whitespace = /\s+/; | ||
return 0; | ||
}); | ||
while (line = lines.shift()) { | ||
line = line.trim().split(whitespace); | ||
return { | ||
latest: tagList.length && tagList[tagList.length - 1], | ||
all: tagList | ||
}; | ||
}; | ||
switch (line.shift()) { | ||
case "??": | ||
not_added.push(line.join()); | ||
break; | ||
case "D": | ||
deleted.push(line.join()); | ||
break; | ||
case "M": | ||
modified.push(line.join()); | ||
break; | ||
case "A": | ||
case "AM": | ||
created.push(line.join()); | ||
break; | ||
} | ||
} | ||
Git.prototype._parseStatus = function (status) { | ||
var line; | ||
var lines = status.trim().split('\n'); | ||
return { | ||
not_added: not_added, | ||
deleted: deleted, | ||
modified: modified, | ||
created: created | ||
}; | ||
}; | ||
var not_added = []; | ||
var deleted = []; | ||
var modified = []; | ||
var created = []; | ||
Git.prototype._parseCheckout = function (checkout) { | ||
// TODO | ||
}; | ||
var whitespace = /\s+/; | ||
Git.prototype._parseFetch = function (fetch) { | ||
return fetch; | ||
}; | ||
while (line = lines.shift()) { | ||
line = line.trim().split(whitespace); | ||
Git.prototype._parseListLog = function (logs) { | ||
var logList = logs.split('\n').map(function (item) { | ||
var parts = item.split(';'); | ||
switch (line.shift()) { | ||
case "??": | ||
not_added.push(line.join()); | ||
break; | ||
case "D": | ||
deleted.push(line.join()); | ||
break; | ||
case "M": | ||
modified.push(line.join()); | ||
break; | ||
case "A": | ||
case "AM": | ||
created.push(line.join()); | ||
break; | ||
} | ||
} | ||
return { | ||
hash: parts[0], | ||
date: parts[1], | ||
message: parts[2], | ||
author_name: parts[3], | ||
author_email: parts[4] | ||
} | ||
}); | ||
return { | ||
not_added: not_added, | ||
deleted: deleted, | ||
modified: modified, | ||
created: created | ||
}; | ||
}; | ||
return { | ||
latest: logList.length && logList[logList.length - 1], | ||
total: logList.length, | ||
all: logList | ||
}; | ||
}; | ||
Git.prototype._parseCheckout = function (checkout) { | ||
// TODO | ||
}; | ||
/** | ||
* Schedules the supplied command to be run, the command should not include the name of the git binary and should | ||
* either be a string, or an array where the first argument is a formatted string accepted by `format` in the util | ||
* module that uses the other entities in the array as the template data. | ||
* | ||
* @param {string|string[]} command | ||
* @param {Function} [then] | ||
* @see http://nodejs.org/api/util.html#util_util_format_format | ||
* @returns {Git} | ||
*/ | ||
Git.prototype._run = function (command, then) { | ||
if (typeof command === "string") { | ||
command = command.split(" "); | ||
} | ||
this._runCache.push([command, then]); | ||
this._schedule(); | ||
Git.prototype._parseFetch = function (fetch) { | ||
return fetch; | ||
}; | ||
return this; | ||
}; | ||
Git.prototype._parseListLog = function (logs) { | ||
var logList = logs.split('\n').map(function (item) { | ||
var parts = item.split(';'); | ||
Git.prototype._schedule = function () { | ||
if (!this._childProcess && this._runCache.length) { | ||
var Buffer = this.Buffer; | ||
var task = this._runCache.shift(); | ||
var command = task[0]; | ||
var then = task[1]; | ||
return { | ||
hash: parts[0], | ||
date: parts[1], | ||
message: parts[2], | ||
author_name: parts[3], | ||
author_email: parts[4] | ||
} | ||
}); | ||
var stdOut = []; | ||
var stdErr = []; | ||
var spawned = this.ChildProcess.spawn(this._command, command.slice(0), { | ||
cwd: this._baseDir | ||
}); | ||
return { | ||
latest: logList.length && logList[logList.length - 1], | ||
total: logList.length, | ||
all: logList | ||
}; | ||
}; | ||
spawned.stdout.on('data', function (buffer) { stdOut.push(buffer); }); | ||
spawned.stderr.on('data', function (buffer) { stdErr.push(buffer); }); | ||
/** | ||
* Schedules the supplied command to be run, the command should not include the name of the git binary and should | ||
* be an array of strings passed as the arguments to the git binary. | ||
* | ||
* @param {string[]} command | ||
* @param {Function} [then] | ||
* | ||
* @returns {Git} | ||
*/ | ||
Git.prototype._run = function (command, then) { | ||
if (typeof command === "string") { | ||
command = command.split(" "); | ||
} | ||
this._runCache.push([command, then]); | ||
this._schedule(); | ||
spawned.on('close', function (exitCode, exitSignal) { | ||
delete this._childProcess; | ||
return this; | ||
}; | ||
if (exitCode && stdErr.length) { | ||
stdErr = Buffer.concat(stdErr).toString('utf-8'); | ||
Git.prototype._schedule = function () { | ||
if (!this._childProcess && this._runCache.length) { | ||
var Buffer = this.Buffer; | ||
var task = this._runCache.shift(); | ||
var command = task[0]; | ||
var then = task[1]; | ||
this._getLog('error', stdErr); | ||
this._runCache = []; | ||
then.call(this, stdErr, null); | ||
} | ||
else { | ||
then.call(this, null, Buffer.concat(stdOut).toString('utf-8')); | ||
} | ||
var stdOut = []; | ||
var stdErr = []; | ||
var spawned = this.ChildProcess.spawn(this._command, command.slice(0), { | ||
cwd: this._baseDir | ||
}); | ||
process.nextTick(this._schedule.bind(this)); | ||
}.bind(this)); | ||
spawned.stdout.on('data', function (buffer) { | ||
stdOut.push(buffer); | ||
}); | ||
spawned.stderr.on('data', function (buffer) { | ||
stdErr.push(buffer); | ||
}); | ||
this._childProcess = spawned; | ||
spawned.on('close', function (exitCode, exitSignal) { | ||
delete this._childProcess; | ||
if (this._outputHandler) { | ||
this._outputHandler(command[0], | ||
this._childProcess.stdout, | ||
this._childProcess.stderr); | ||
if (exitCode && stdErr.length) { | ||
stdErr = Buffer.concat(stdErr).toString('utf-8'); | ||
this._getLog('error', stdErr); | ||
this._runCache = []; | ||
then.call(this, stdErr, null); | ||
} | ||
} | ||
}; | ||
else { | ||
then.call(this, null, Buffer.concat(stdOut).toString('utf-8')); | ||
} | ||
/** | ||
* Given any number of arguments, returns the last argument if it is a function, otherwise returns null. | ||
* @returns {Function|null} | ||
*/ | ||
Git.trailingFunctionArgument = function (args) { | ||
var trailing = args[args.length - 1]; | ||
return (typeof trailing === "function") ? trailing : null; | ||
}; | ||
process.nextTick(this._schedule.bind(this)); | ||
}.bind(this)); | ||
module.exports = Git; | ||
this._childProcess = spawned; | ||
if (this._outputHandler) { | ||
this._outputHandler(command[0], | ||
this._childProcess.stdout, | ||
this._childProcess.stderr); | ||
} | ||
} | ||
}; | ||
/** | ||
* Given any number of arguments, returns the last argument if it is a function, otherwise returns null. | ||
* @returns {Function|null} | ||
*/ | ||
Git.trailingFunctionArgument = function (args) { | ||
var trailing = args[args.length - 1]; | ||
return (typeof trailing === "function") ? trailing : null; | ||
}; | ||
module.exports = Git; | ||
}()); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1210
171
51183
5