(function () { 'use strict'; var debug = require('debug')('simple-git'); var deferred = require('./util/deferred'); var exists = require('./util/exists'); var NOOP = function () {}; var responses = require('./responses'); /** * 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 {Object} ChildProcess The ChildProcess module * @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; } /** * @type {string} The command to use to reference the git binary */ Git.prototype._command = 'git'; /** * @type {[key: string]: string} An object of key=value pairs to be passed as environment variables to the * spawned child process. */ Git.prototype._env = 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); /** * 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 an environment variable for the spawned child process, either supply both a name and value as strings or * a single object to entirely replace the current environment variables. * * @param {string|Object} name * @param {string} [value] * @returns {Git} */ Git.prototype.env = function (name, value) { if (arguments.length === 1 && typeof name === 'object') { this._env = name; } else { (this._env = this._env || {})[name] = value; } return this; }; /** * Sets the working directory of the subsequent commands. * * @param {string} workingDirectory * @param {Function} [then] * @returns {Git} */ Git.prototype.cwd = function (workingDirectory, then) { var git = this; var next = Git.trailingFunctionArgument(arguments); return this.exec(function () { git._baseDir = workingDirectory; if (!exists(workingDirectory, exists.FOLDER)) { Git.exception(git, 'Git.cwd: cannot change to non-directory "' + workingDirectory + '"', next); } else { next && next(null, workingDirectory); } }); }; /** * 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 https://nodejs.org/api/child_process.html#child_process_class_childprocess * @see https://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); if (bare === true) { commands.push('--bare'); } 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', '-b', '-u'], Git._responseHandler(then, 'StatusSummary') ); }; /** * List the stash(s) of the local repo * * @param {Object|Array} [options] * @param {Function} [then] */ Git.prototype.stashList = function (options, then) { var handler = Git.trailingFunctionArgument(arguments); var opt = (handler === then ? options : null) || {}; var splitter = opt.splitter || requireResponseHandler('ListLogSummary').SPLITTER; var command = ["stash", "list", "--pretty=format:" + requireResponseHandler('ListLogSummary').START_BOUNDARY + "%H %ai %s%d %aN %ae".replace(/\s+/g, splitter) + requireResponseHandler('ListLogSummary').COMMIT_BOUNDARY ]; if (Array.isArray(opt)) { command = command.concat(opt); } return this._run(command, Git._responseHandler(handler, 'ListLogSummary', splitter) ); }; /** * Stash the local repo * * @param {Object|Array} [options] * @param {Function} [then] */ Git.prototype.stash = function (options, then) { var command = ['stash']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); command.push.apply(command, Git.trailingArrayArgument(arguments)); return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments))); }; /** * Clone a git repo * * @param {string} repoPath * @param {string} localPath * @param {String[]} [options] Optional array of options to pass through to the clone command * @param {Function} [then] */ Git.prototype.clone = function (repoPath, localPath, options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['clone'].concat(Git.trailingArrayArgument(arguments)); for (var i = 0, iMax = arguments.length; i < iMax; i++) { if (typeof arguments[i] === 'string') { command.push(arguments[i]); } } return this._run(command, function (err, data) { next && next(err, data); }); }; /** * Mirror a git repo * * @param {string} repoPath * @param {string} localPath * @param {Function} [then] */ Git.prototype.mirror = function (repoPath, localPath, then) { return this.clone(repoPath, localPath, ['--mirror'], then); }; /** * Moves one or more files to a new destination. * * @see https://git-scm.com/docs/git-mv * * @param {string|string[]} from * @param {string} to * @param {Function} [then] */ Git.prototype.mv = function (from, to, then) { var handler = Git.trailingFunctionArgument(arguments); var command = [].concat(from); command.unshift('mv', '-v'); command.push(to); this._run(command, Git._responseHandler(handler, 'MoveSummary')) }; /** * 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(function () { git.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); }); }; /** * Commits changes in the current working directory - when specific file paths are supplied, only changes on those * files will be committed. * * @param {string|string[]} message * @param {string|string[]} [files] * @param {Object} [options] * @param {Function} [then] */ Git.prototype.commit = function (message, files, options, then) { var handler = Git.trailingFunctionArgument(arguments); var command = ['commit']; [].concat(message).forEach(function (message) { command.push('-m', message); }); [].push.apply(command, [].concat(typeof files === "string" || Array.isArray(files) ? files : [])); Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); return this._run( command, Git._responseHandler(handler, 'CommitSummary') ); }; /** * 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 ? NOOP : console[level].bind(console); if (arguments.length > 1) { log(message); } return log; }; /** * Pull the updated contents of the current repo * * @param {string} [remote] When supplied must also include the branch * @param {string} [branch] When supplied must also include the remote * @param {Object} [options] Optionally include set of options to merge into the command * @param {Function} [then] */ Git.prototype.pull = function (remote, branch, options, then) { var command = ["pull"]; var handler = Git.trailingFunctionArgument(arguments); if (typeof remote === 'string' && typeof branch === 'string') { command.push(remote, branch); } Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); return this._run(command, Git._responseHandler(handler, 'PullSummary')); }; /** * 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"]; var next = Git.trailingFunctionArgument(arguments); Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); if (typeof remote === 'string' && typeof branch === 'string') { command.push(remote, branch); } if (Array.isArray(remote)) { command = command.concat(remote); } return this._run( command, Git._responseHandler(next, 'FetchSummary'), { concatStdErr: true } ); }; /** * 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. When using git 2.7.0 or above, include an options object with `"--sort": "property-name"` to * sort the tags by that property instead of using the default semantic versioning sort. * * Note, supplying this option when it is not supported by your Git version will cause the operation to fail. * * @param {Object} [options] * @param {Function} [then] */ Git.prototype.tags = function (options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['-l']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); var hasCustomSort = command.some(function (option) { return /^--sort=/.test(option); }); return this.tag( command, Git._responseHandler(next, 'TagList', [hasCustomSort]) ); }; /** * Rebases the current working copy. Options can be supplied either as an array of string parameters * to be sent to the `git rebase` command, or a standard options object. * * @param {Object|String[]} [options] * @param {Function} [then] * @returns {Git} */ Git.prototype.rebase = function (options, then) { var command = ['rebase']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); command.push.apply(command, Git.trailingArrayArgument(arguments)); return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments))); }; /** * Reset a repo * * @param {string|string[]} [mode=soft] Either an array of arguments supported by the 'git reset' command, or the * string value 'soft' or 'hard' to set the reset mode. * @param {Function} [then] */ Git.prototype.reset = function (mode, then) { var command = ['reset']; var next = Git.trailingFunctionArgument(arguments); if (next === mode || typeof mode === 'string' || !mode) { var modeStr = ['mixed', 'soft', 'hard'].includes(mode) ? mode : 'soft'; command.push('--' + modeStr); } else if (Array.isArray(mode)) { command.push.apply(command, mode); } return this._run(command, function (err) { next && next(err || null); }); }; /** * Revert one or more commits in the local working copy * * @param {string} commit The commit to revert. Can be any hash, offset (eg: `HEAD~2`) or range (eg: `master~5..master~2`) * @param {Object} [options] Optional options object * @param {Function} [then] */ Git.prototype.revert = function (commit, options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['revert']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); if (typeof commit !== 'string') { return this.exec(function () { next && next(new TypeError("Commit must be a string")); }); } command.push(commit); return this._run(command, 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) { if (typeof name !== "string") { return this.exec(function () { then && then(new TypeError("Git.addTag requires a tag name")); }); } var command = [name]; return then ? this.tag(command, then) : this.tag(command); }; /** * 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) {Lines 1–500 of 1592. Load more
(function () { 'use strict'; var debug = require('debug')('simple-git'); var deferred = require('./util/deferred'); var exists = require('./util/exists'); var NOOP = function () {}; var responses = require('./responses'); /** * 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 {Object} ChildProcess The ChildProcess module * @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; } /** * @type {string} The command to use to reference the git binary */ Git.prototype._command = 'git'; /** * @type {[key: string]: string} An object of key=value pairs to be passed as environment variables to the * spawned child process. */ Git.prototype._env = 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); /** * 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 an environment variable for the spawned child process, either supply both a name and value as strings or * a single object to entirely replace the current environment variables. * * @param {string|Object} name * @param {string} [value] * @returns {Git} */ Git.prototype.env = function (name, value) { if (arguments.length === 1 && typeof name === 'object') { this._env = name; } else { (this._env = this._env || {})[name] = value; } return this; }; /** * Sets the working directory of the subsequent commands. * * @param {string} workingDirectory * @param {Function} [then] * @returns {Git} */ Git.prototype.cwd = function (workingDirectory, then) { var git = this; var next = Git.trailingFunctionArgument(arguments); return this.exec(function () { git._baseDir = workingDirectory; if (!exists(workingDirectory, exists.FOLDER)) { Git.exception(git, 'Git.cwd: cannot change to non-directory "' + workingDirectory + '"', next); } else { next && next(null, workingDirectory); } }); }; /** * 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 https://nodejs.org/api/child_process.html#child_process_class_childprocess * @see https://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); if (bare === true) { commands.push('--bare'); } 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', '-b', '-u'], Git._responseHandler(then, 'StatusSummary') ); }; /** * List the stash(s) of the local repo * * @param {Object|Array} [options] * @param {Function} [then] */ Git.prototype.stashList = function (options, then) { var handler = Git.trailingFunctionArgument(arguments); var opt = (handler === then ? options : null) || {}; var splitter = opt.splitter || requireResponseHandler('ListLogSummary').SPLITTER; var command = ["stash", "list", "--pretty=format:" + requireResponseHandler('ListLogSummary').START_BOUNDARY + "%H %ai %s%d %aN %ae".replace(/\s+/g, splitter) + requireResponseHandler('ListLogSummary').COMMIT_BOUNDARY ]; if (Array.isArray(opt)) { command = command.concat(opt); } return this._run(command, Git._responseHandler(handler, 'ListLogSummary', splitter) ); }; /** * Stash the local repo * * @param {Object|Array} [options] * @param {Function} [then] */ Git.prototype.stash = function (options, then) { var command = ['stash']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); command.push.apply(command, Git.trailingArrayArgument(arguments)); return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments))); }; /** * Clone a git repo * * @param {string} repoPath * @param {string} localPath * @param {String[]} [options] Optional array of options to pass through to the clone command * @param {Function} [then] */ Git.prototype.clone = function (repoPath, localPath, options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['clone'].concat(Git.trailingArrayArgument(arguments)); for (var i = 0, iMax = arguments.length; i < iMax; i++) { if (typeof arguments[i] === 'string') { command.push(arguments[i]); } } return this._run(command, function (err, data) { next && next(err, data); }); }; /** * Mirror a git repo * * @param {string} repoPath * @param {string} localPath * @param {Function} [then] */ Git.prototype.mirror = function (repoPath, localPath, then) { return this.clone(repoPath, localPath, ['--mirror'], then); }; /** * Moves one or more files to a new destination. * * @see https://git-scm.com/docs/git-mv * * @param {string|string[]} from * @param {string} to * @param {Function} [then] */ Git.prototype.mv = function (from, to, then) { var handler = Git.trailingFunctionArgument(arguments); var command = [].concat(from); command.unshift('mv', '-v'); command.push(to); this._run(command, Git._responseHandler(handler, 'MoveSummary')) }; /** * 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(function () { git.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); }); }; /** * Commits changes in the current working directory - when specific file paths are supplied, only changes on those * files will be committed. * * @param {string|string[]} message * @param {string|string[]} [files] * @param {Object} [options] * @param {Function} [then] */ Git.prototype.commit = function (message, files, options, then) { var handler = Git.trailingFunctionArgument(arguments); var command = ['commit']; [].concat(message).forEach(function (message) { command.push('-m', message); }); [].push.apply(command, [].concat(typeof files === "string" || Array.isArray(files) ? files : [])); Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); return this._run( command, Git._responseHandler(handler, 'CommitSummary') ); }; /** * 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 ? NOOP : console[level].bind(console); if (arguments.length > 1) { log(message); } return log; }; /** * Pull the updated contents of the current repo * * @param {string} [remote] When supplied must also include the branch * @param {string} [branch] When supplied must also include the remote * @param {Object} [options] Optionally include set of options to merge into the command * @param {Function} [then] */ Git.prototype.pull = function (remote, branch, options, then) { var command = ["pull"]; var handler = Git.trailingFunctionArgument(arguments); if (typeof remote === 'string' && typeof branch === 'string') { command.push(remote, branch); } Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); return this._run(command, Git._responseHandler(handler, 'PullSummary')); }; /** * 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"]; var next = Git.trailingFunctionArgument(arguments); Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); if (typeof remote === 'string' && typeof branch === 'string') { command.push(remote, branch); } if (Array.isArray(remote)) { command = command.concat(remote); } return this._run( command, Git._responseHandler(next, 'FetchSummary'), { concatStdErr: true } ); }; /** * 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. When using git 2.7.0 or above, include an options object with `"--sort": "property-name"` to * sort the tags by that property instead of using the default semantic versioning sort. * * Note, supplying this option when it is not supported by your Git version will cause the operation to fail. * * @param {Object} [options] * @param {Function} [then] */ Git.prototype.tags = function (options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['-l']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); var hasCustomSort = command.some(function (option) { return /^--sort=/.test(option); }); return this.tag( command, Git._responseHandler(next, 'TagList', [hasCustomSort]) ); }; /** * Rebases the current working copy. Options can be supplied either as an array of string parameters * to be sent to the `git rebase` command, or a standard options object. * * @param {Object|String[]} [options] * @param {Function} [then] * @returns {Git} */ Git.prototype.rebase = function (options, then) { var command = ['rebase']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); command.push.apply(command, Git.trailingArrayArgument(arguments)); return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments))); }; /** * Reset a repo * * @param {string|string[]} [mode=soft] Either an array of arguments supported by the 'git reset' command, or the * string value 'soft' or 'hard' to set the reset mode. * @param {Function} [then] */ Git.prototype.reset = function (mode, then) { var command = ['reset']; var next = Git.trailingFunctionArgument(arguments); if (next === mode || typeof mode === 'string' || !mode) { var modeStr = ['mixed', 'soft', 'hard'].includes(mode) ? mode : 'soft'; command.push('--' + modeStr); } else if (Array.isArray(mode)) { command.push.apply(command, mode); } return this._run(command, function (err) { next && next(err || null); }); }; /** * Revert one or more commits in the local working copy * * @param {string} commit The commit to revert. Can be any hash, offset (eg: `HEAD~2`) or range (eg: `master~5..master~2`) * @param {Object} [options] Optional options object * @param {Function} [then] */ Git.prototype.revert = function (commit, options, then) { var next = Git.trailingFunctionArgument(arguments); var command = ['revert']; Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); if (typeof commit !== 'string') { return this.exec(function () { next && next(new TypeError("Commit must be a string")); }); } command.push(commit); return this._run(command, 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) { if (typeof name !== "string") { return this.exec(function () { then && then(new TypeError("Git.addTag requires a tag name")); }); } var command = [name]; return then ? this.tag(command, then) : this.tag(command); }; /** * 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) {