You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1592 lines
						
					
					
						
							48 KiB
						
					
					
				
			
		
		
	
	
							1592 lines
						
					
					
						
							48 KiB
						
					
					
				(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) { | 
						|
         then && then(err); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Check out a tag or revision, any number of additional arguments can be passed to the `git checkout` command | 
						|
    * by supplying either a string or array of strings as the `what` parameter. | 
						|
    * | 
						|
    * @param {string|string[]} what One or more commands to pass to `git checkout` | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.checkout = function (what, then) { | 
						|
      var command = ['checkout']; | 
						|
      command = command.concat(what); | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         then && then(err, !err && this._parseCheckout(data)); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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.checkout(['-b', branchName, startPoint], then); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Check out a local branch | 
						|
    * | 
						|
    * @param {string} branchName of branch | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.checkoutLocalBranch = function (branchName, then) { | 
						|
      return this.checkout(['-b', branchName], then); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Delete a local branch | 
						|
    * | 
						|
    * @param {string} branchName name of branch | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.deleteLocalBranch = function (branchName, then) { | 
						|
      return this.branch(['-d', branchName], then); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * List all branches | 
						|
    * | 
						|
    * @param {Object | string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.branch = function (options, then) { | 
						|
      var isDelete, responseHandler; | 
						|
      var next = Git.trailingFunctionArgument(arguments); | 
						|
      var command = ['branch']; | 
						|
 | 
						|
      command.push.apply(command, Git.trailingArrayArgument(arguments)); | 
						|
      Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); | 
						|
 | 
						|
      if (!arguments.length || next === options) { | 
						|
         command.push('-a'); | 
						|
      } | 
						|
 | 
						|
      isDelete = ['-d', '-D', '--delete'].reduce(function (isDelete, flag) { | 
						|
         return isDelete || command.indexOf(flag) > 0; | 
						|
      }, false); | 
						|
 | 
						|
      if (command.indexOf('-v') < 0) { | 
						|
         command.splice(1, 0, '-v'); | 
						|
      } | 
						|
 | 
						|
      responseHandler = isDelete | 
						|
         ? Git._responseHandler(next, 'BranchDeleteSummary', false) | 
						|
         : Git._responseHandler(next, 'BranchSummary'); | 
						|
 | 
						|
      return this._run(command, responseHandler); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Return list of local branches | 
						|
    * | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.branchLocal = function (then) { | 
						|
      return this.branch(['-v'], then); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Add config to local git instance | 
						|
    * | 
						|
    * @param {string} key configuration key (e.g user.name) | 
						|
    * @param {string} value for the given key (e.g your name) | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.addConfig = function (key, value, then) { | 
						|
      return this._run(['config', '--local', key, value], function (err, data) { | 
						|
         then && then(err, !err && data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Executes any command against the git binary. | 
						|
    * | 
						|
    * @param {string[]|Object} commands | 
						|
    * @param {Function} [then] | 
						|
    * | 
						|
    * @returns {Git} | 
						|
    */ | 
						|
   Git.prototype.raw = function (commands, then) { | 
						|
      var command = []; | 
						|
      if (Array.isArray(commands)) { | 
						|
         command = commands.slice(0); | 
						|
      } | 
						|
      else { | 
						|
         Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); | 
						|
      } | 
						|
 | 
						|
      var next = Git.trailingFunctionArgument(arguments); | 
						|
 | 
						|
      if (!command.length) { | 
						|
         return this.exec(function () { | 
						|
            next && next(new Error('Raw: must supply one or more command to execute'), null); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         next && next(err, !err && data || null); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Update submodules | 
						|
    * | 
						|
    * @param {string[]} [args] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.submoduleUpdate = function (args, then) { | 
						|
      if (typeof args === 'string') { | 
						|
         this._getLog('warn', 'Git#submoduleUpdate: args should be supplied as an array of individual arguments'); | 
						|
      } | 
						|
 | 
						|
      var next = Git.trailingFunctionArgument(arguments); | 
						|
      var command = (args !== next) ? args : []; | 
						|
 | 
						|
      return this.subModule(['update'].concat(command), function (err, args) { | 
						|
         next && next(err, args); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Initialize submodules | 
						|
    * | 
						|
    * @param {string[]} [args] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.submoduleInit = function (args, then) { | 
						|
      if (typeof args === 'string') { | 
						|
         this._getLog('warn', 'Git#submoduleInit: args should be supplied as an array of individual arguments'); | 
						|
      } | 
						|
 | 
						|
      var next = Git.trailingFunctionArgument(arguments); | 
						|
      var command = (args !== next) ? args : []; | 
						|
 | 
						|
      return this.subModule(['init'].concat(command), function (err, args) { | 
						|
         next && next(err, args); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Call any `git submodule` function with arguments passed as an array of strings. | 
						|
    * | 
						|
    * @param {string[]} options | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.subModule = function (options, then) { | 
						|
      if (!Array.isArray(options)) { | 
						|
         return this.exec(function () { | 
						|
            then && then(new TypeError("Git.subModule requires an array of arguments")); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      if (options[0] !== 'submodule') { | 
						|
         options.unshift('submodule'); | 
						|
      } | 
						|
 | 
						|
      return this._run(options, function (err, data) { | 
						|
         then && then(err || null, err ? null : 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; | 
						|
 | 
						|
      if (typeof data === 'string') { | 
						|
         this._getLog('warn', 'Git#listRemote: args should be supplied as an array of individual arguments'); | 
						|
      } | 
						|
 | 
						|
      return this._run(['ls-remote'].concat(data), function (err, data) { | 
						|
         next && next(err, data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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'] : []; | 
						|
 | 
						|
      return this.remote(args, function (err, data) { | 
						|
         next && next(err, !err && function () { | 
						|
            return data.trim().split('\n').filter(Boolean).reduce(function (remotes, remote) { | 
						|
               var detail = remote.trim().split(/\s+/); | 
						|
               var name = detail.shift(); | 
						|
 | 
						|
               if (!remotes[name]) { | 
						|
                  remotes[name] = remotes[remotes.length] = { | 
						|
                     name: name, | 
						|
                     refs: {} | 
						|
                  }; | 
						|
               } | 
						|
 | 
						|
               if (detail.length) { | 
						|
                  remotes[name].refs[detail.pop().replace(/[^a-z]/g, '')] = detail.pop(); | 
						|
               } | 
						|
 | 
						|
               return remotes; | 
						|
            }, []).slice(0); | 
						|
         }()); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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.exec(function () { | 
						|
            then && then(new TypeError("Git.remote requires an array of arguments")); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      if (options[0] !== 'remote') { | 
						|
         options.unshift('remote'); | 
						|
      } | 
						|
 | 
						|
      return this._run(options, function (err, data) { | 
						|
         then && then(err || null, err ? null : data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Merges from one branch to another, equivalent to running `git merge ${from} $[to}`, the `options` argument can | 
						|
    * either be an array of additional parameters to pass to the command or null / omitted to be ignored. | 
						|
    * | 
						|
    * @param {string} from | 
						|
    * @param {string} to | 
						|
    * @param {string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.mergeFromTo = function (from, to, options, then) { | 
						|
      var commands = [ | 
						|
         from, | 
						|
         to | 
						|
      ]; | 
						|
      var callback = Git.trailingFunctionArgument(arguments); | 
						|
 | 
						|
      if (Array.isArray(options)) { | 
						|
         commands = commands.concat(options); | 
						|
      } | 
						|
 | 
						|
      return this.merge(commands, callback); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Runs a merge, `options` can be either an array of arguments | 
						|
    * supported by the [`git merge`](https://git-scm.com/docs/git-merge) | 
						|
    * or an options object. | 
						|
    * | 
						|
    * Conflicts during the merge result in an error response, | 
						|
    * the response type whether it was an error or success will be a MergeSummary instance. | 
						|
    * When successful, the MergeSummary has all detail from a the PullSummary | 
						|
    * | 
						|
    * @param {Object | string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    * @returns {*} | 
						|
    * | 
						|
    * @see ./responses/MergeSummary.js | 
						|
    * @see ./responses/PullSummary.js | 
						|
    */ | 
						|
   Git.prototype.merge = function (options, then) { | 
						|
      var self = this; | 
						|
      var userHandler = Git.trailingFunctionArgument(arguments) || NOOP; | 
						|
      var mergeHandler = function (err, mergeSummary) { | 
						|
         if (!err && mergeSummary.failed) { | 
						|
            return Git.fail(self, mergeSummary, userHandler); | 
						|
         } | 
						|
 | 
						|
         userHandler(err, mergeSummary); | 
						|
      }; | 
						|
 | 
						|
      var command = []; | 
						|
      Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); | 
						|
      command.push.apply(command, Git.trailingArrayArgument(arguments)); | 
						|
 | 
						|
      if (command[0] !== 'merge') { | 
						|
         command.unshift('merge'); | 
						|
      } | 
						|
 | 
						|
      if (command.length === 1) { | 
						|
         return this.exec(function () { | 
						|
            then && then(new TypeError("Git.merge requires at least one option")); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, Git._responseHandler(mergeHandler, 'MergeSummary'), { | 
						|
         concatStdErr: true | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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) { | 
						|
      var command = []; | 
						|
      Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); | 
						|
      command.push.apply(command, Git.trailingArrayArgument(arguments)); | 
						|
 | 
						|
      if (command[0] !== 'tag') { | 
						|
         command.unshift('tag'); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments))); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Updates repository server info | 
						|
    * | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.updateServerInfo = function (then) { | 
						|
      return this._run(["update-server-info"], function (err, data) { | 
						|
         then && then(err, !err && data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Pushes the current committed changes to a remote, optionally specify the names of the remote and branch to use | 
						|
    * when pushing. Supply multiple options as an array of strings in the first argument - see examples below. | 
						|
    * | 
						|
    * @param {string|string[]} [remote] | 
						|
    * @param {string} [branch] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.push = function (remote, branch, then) { | 
						|
      var command = []; | 
						|
      var handler = Git.trailingFunctionArgument(arguments); | 
						|
 | 
						|
      if (typeof remote === 'string' && typeof branch === 'string') { | 
						|
         command.push(remote, branch); | 
						|
      } | 
						|
 | 
						|
      if (Array.isArray(remote)) { | 
						|
         command = command.concat(remote); | 
						|
      } | 
						|
 | 
						|
      Git._appendOptions(command, Git.trailingOptionsArgument(arguments)); | 
						|
 | 
						|
      if (command[0] !== 'push') { | 
						|
         command.unshift('push'); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         handler && handler(err, !err && 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'); | 
						|
 | 
						|
      then = typeof arguments[arguments.length - 1] === "function" ? arguments[arguments.length - 1] : null; | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         then && then(err, !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); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Returns a list of objects in a tree based on commit hash. Passing in an object hash returns the object's content, | 
						|
    * size, and type. | 
						|
    * | 
						|
    * Passing "-p" will instruct cat-file to determine the object type, and display its formatted contents. | 
						|
    * | 
						|
    * @param {string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.catFile = function (options, then) { | 
						|
      return this._catFile('utf-8', arguments); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Equivalent to `catFile` but will return the native `Buffer` of content from the git command's stdout. | 
						|
    * | 
						|
    * @param {string[]} options | 
						|
    * @param then | 
						|
    */ | 
						|
   Git.prototype.binaryCatFile = function (options, then) { | 
						|
      return this._catFile('buffer', arguments); | 
						|
   }; | 
						|
 | 
						|
   Git.prototype._catFile = function (format, args) { | 
						|
      var handler = Git.trailingFunctionArgument(args); | 
						|
      var command = ['cat-file']; | 
						|
      var options = args[0]; | 
						|
 | 
						|
      if (typeof options === 'string') { | 
						|
         throw new TypeError('Git#catFile: options must be supplied as an array of strings'); | 
						|
      } | 
						|
      else if (Array.isArray(options)) { | 
						|
         command.push.apply(command, options); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         handler && handler(err, data); | 
						|
      }, { | 
						|
         format: format | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Return repository changes. | 
						|
    * | 
						|
    * @param {string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.diff = function (options, then) { | 
						|
      var command = ['diff']; | 
						|
 | 
						|
      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); | 
						|
      } | 
						|
 | 
						|
      if (typeof arguments[arguments.length - 1] === 'function') { | 
						|
         then = arguments[arguments.length - 1]; | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         then && then(err, data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   Git.prototype.diffSummary = function (options, then) { | 
						|
      var next = Git.trailingFunctionArgument(arguments); | 
						|
      var command = ['--stat=4096']; | 
						|
 | 
						|
      if (options && options !== next) { | 
						|
         command.push.apply(command, [].concat(options)); | 
						|
      } | 
						|
 | 
						|
      return this.diff(command, Git._responseHandler(next, 'DiffSummary')); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Wraps `git rev-parse`. Primarily used to convert friendly commit references (ie branch names) to SHA1 hashes. | 
						|
    * | 
						|
    * Options should be an array of string options compatible with the `git rev-parse` | 
						|
    * | 
						|
    * @param {string|string[]} [options] | 
						|
    * @param {Function} [then] | 
						|
    * | 
						|
    * @see https://git-scm.com/docs/git-rev-parse | 
						|
    */ | 
						|
   Git.prototype.revparse = function (options, then) { | 
						|
      var command = ['rev-parse']; | 
						|
 | 
						|
      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); | 
						|
      } | 
						|
 | 
						|
      if (typeof arguments[arguments.length - 1] === 'function') { | 
						|
         then = arguments[arguments.length - 1]; | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         then && then(err, err ? null : String(data).trim()); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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) { | 
						|
         handler && handler(err, !err && data); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * @param {string} mode Required parameter "n" or "f" | 
						|
    * @param {string[]} options | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.clean = function (mode, options, then) { | 
						|
      var handler = Git.trailingFunctionArgument(arguments); | 
						|
 | 
						|
      if (typeof mode !== 'string' || !/[nf]/.test(mode)) { | 
						|
         return this.exec(function () { | 
						|
            handler && handler(new TypeError('Git clean mode parameter ("n" or "f") is required')); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      if (/[^dfinqxX]/.test(mode)) { | 
						|
         return this.exec(function () { | 
						|
            handler && handler(new TypeError('Git clean unknown option found in ' + JSON.stringify(mode))); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      var command = ['clean', '-' + mode]; | 
						|
      if (Array.isArray(options)) { | 
						|
         command = command.concat(options); | 
						|
      } | 
						|
 | 
						|
      if (command.some(interactiveMode)) { | 
						|
         return this.exec(function () { | 
						|
            handler && handler(new TypeError('Git clean interactive mode is not supported')); | 
						|
         }); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         handler && handler(err, !err && data); | 
						|
      }); | 
						|
 | 
						|
      function interactiveMode (option) { | 
						|
         if (/^-[^\-]/.test(option)) { | 
						|
            return option.indexOf('i') > 0; | 
						|
         } | 
						|
 | 
						|
         return option === '--interactive'; | 
						|
      } | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Call a simple function at the next step in the chain. | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.exec = function (then) { | 
						|
      this._run([], function () { | 
						|
         typeof then === 'function' && then(); | 
						|
      }); | 
						|
      return this; | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Deprecated means of adding a regular function call at the next step in the chain. Use the replacement | 
						|
    * Git#exec, the Git#then method will be removed in version 2.x | 
						|
    * | 
						|
    * @see exec | 
						|
    * @deprecated | 
						|
    */ | 
						|
   Git.prototype.then = function (then) { | 
						|
      this._getLog( | 
						|
         'error', ` | 
						|
Git#then is deprecated after version 1.72 and will be removed in version 2.x | 
						|
To use promises switch to importing 'simple-git/promise'.`); | 
						|
 | 
						|
      return this.exec(then); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Show commit logs from `HEAD` to the first commit. | 
						|
    * If provided between `options.from` and `options.to` tags or branch. | 
						|
    * | 
						|
    * Additionally you can provide options.file, which is the path to a file in your repository. Then only this file will be considered. | 
						|
    * | 
						|
    * To use a custom splitter in the log format, set `options.splitter` to be the string the log should be split on. | 
						|
    * | 
						|
    * Options can also be supplied as a standard options object for adding custom properties supported by the git log command. | 
						|
    * For any other set of options, supply options as an array of strings to be appended to the git log command. | 
						|
    * | 
						|
    * @param {Object|string[]} [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 {boolean} [options.multiLine] Optionally include multi-line commit messages | 
						|
    * | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.log = function (options, then) { | 
						|
      var handler = Git.trailingFunctionArgument(arguments); | 
						|
      var opt = (handler === then ? options : null) || {}; | 
						|
 | 
						|
      var splitter = opt.splitter || requireResponseHandler('ListLogSummary').SPLITTER; | 
						|
      var format = opt.format || { | 
						|
         hash: '%H', | 
						|
         date: '%ai', | 
						|
         message: '%s', | 
						|
         refs: '%D', | 
						|
         body: opt.multiLine ? '%B' : '%b', | 
						|
         author_name: '%aN', | 
						|
         author_email: '%ae' | 
						|
      }; | 
						|
      var rangeOperator = (opt.symmetric !== false) ? '...' : '..'; | 
						|
 | 
						|
      var fields = Object.keys(format); | 
						|
      var formatstr = fields.map(function (k) { | 
						|
         return format[k]; | 
						|
      }).join(splitter); | 
						|
      var suffix = []; | 
						|
      var command = ["log", "--pretty=format:" | 
						|
         + requireResponseHandler('ListLogSummary').START_BOUNDARY | 
						|
         + formatstr | 
						|
         + requireResponseHandler('ListLogSummary').COMMIT_BOUNDARY | 
						|
      ]; | 
						|
 | 
						|
      if (Array.isArray(opt)) { | 
						|
         command = command.concat(opt); | 
						|
         opt = {}; | 
						|
      } | 
						|
      else if (typeof arguments[0] === "string" || typeof arguments[1] === "string") { | 
						|
         this._getLog('warn', | 
						|
            'Git#log: supplying to or from as strings is now deprecated, switch to an options configuration object'); | 
						|
         opt = { | 
						|
            from: arguments[0], | 
						|
            to: arguments[1] | 
						|
         }; | 
						|
      } | 
						|
 | 
						|
      if (opt.n || opt['max-count']) { | 
						|
         command.push("--max-count=" + (opt.n || opt['max-count'])); | 
						|
      } | 
						|
 | 
						|
      if (opt.from && opt.to) { | 
						|
         command.push(opt.from + rangeOperator + opt.to); | 
						|
      } | 
						|
 | 
						|
      if (opt.file) { | 
						|
         suffix.push("--follow", options.file); | 
						|
      } | 
						|
 | 
						|
      'splitter n max-count file from to --pretty format symmetric multiLine'.split(' ').forEach(function (key) { | 
						|
         delete opt[key]; | 
						|
      }); | 
						|
 | 
						|
      Git._appendOptions(command, opt); | 
						|
 | 
						|
      return this._run( | 
						|
         command.concat(suffix), | 
						|
         Git._responseHandler(handler, 'ListLogSummary', [splitter, fields]) | 
						|
      ); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Clears the queue of pending commands and returns the wrapper instance for chaining. | 
						|
    * | 
						|
    * @returns {Git} | 
						|
    */ | 
						|
   Git.prototype.clearQueue = function () { | 
						|
      this._runCache.length = 0; | 
						|
      return this; | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Check if a pathname or pathnames are excluded by .gitignore | 
						|
    * | 
						|
    * @param {string|string[]} pathnames | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.checkIgnore = function (pathnames, then) { | 
						|
      var handler = Git.trailingFunctionArgument(arguments); | 
						|
      var command = ["check-ignore"]; | 
						|
 | 
						|
      if (handler !== pathnames) { | 
						|
         command = command.concat(pathnames); | 
						|
      } | 
						|
 | 
						|
      return this._run(command, function (err, data) { | 
						|
         handler && handler(err, !err && this._parseCheckIgnore(data)); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Validates that the current repo is a Git repo. | 
						|
    * | 
						|
    * @param {Function} [then] | 
						|
    */ | 
						|
   Git.prototype.checkIsRepo = function (then) { | 
						|
      function onError (exitCode, stdErr, done, fail) { | 
						|
         if (exitCode === 128 && /(Not a git repository|Kein Git-Repository)/i.test(stdErr)) { | 
						|
            return done(false); | 
						|
         } | 
						|
 | 
						|
         fail(stdErr); | 
						|
      } | 
						|
 | 
						|
      function handler (err, isRepo) { | 
						|
         then && then(err, String(isRepo).trim() === 'true'); | 
						|
      } | 
						|
 | 
						|
      return this._run(['rev-parse', '--is-inside-work-tree'], handler, {onError: onError}); | 
						|
   }; | 
						|
 | 
						|
   Git.prototype._rm = function (_files, options, then) { | 
						|
      var files = [].concat(_files); | 
						|
      var args = ['rm', options]; | 
						|
      args.push.apply(args, files); | 
						|
 | 
						|
      return this._run(args, function (err) { | 
						|
         then && then(err); | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   Git.prototype._parseCheckout = function (checkout) { | 
						|
      // TODO | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Parser for the `check-ignore` command - returns each | 
						|
    * @param {string} [files] | 
						|
    * @returns {string[]} | 
						|
    */ | 
						|
   Git.prototype._parseCheckIgnore = function (files) { | 
						|
      return files.split(/\n/g).filter(Boolean).map(function (file) { | 
						|
         return file.trim() | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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 | 
						|
    * @param {Object} [opt] | 
						|
    * @param {boolean} [opt.concatStdErr=false] Optionally concatenate stderr output into the stdout | 
						|
    * @param {boolean} [opt.format="utf-8"] The format to use when reading the content of stdout | 
						|
    * @param {Function} [opt.onError] Optional error handler for this command - can be used to allow non-clean exits | 
						|
    *                                  without killing the remaining stack of commands | 
						|
    * @param {number} [opt.onError.exitCode] | 
						|
    * @param {string} [opt.onError.stdErr] | 
						|
    * | 
						|
    * @returns {Git} | 
						|
    */ | 
						|
   Git.prototype._run = function (command, then, opt) { | 
						|
      if (typeof command === "string") { | 
						|
         command = command.split(" "); | 
						|
      } | 
						|
      this._runCache.push([command, then, opt || {}]); | 
						|
      this._schedule(); | 
						|
 | 
						|
      return this; | 
						|
   }; | 
						|
 | 
						|
   Git.prototype._schedule = function () { | 
						|
      if (!this._childProcess && this._runCache.length) { | 
						|
         var git = this; | 
						|
         var Buffer = git.Buffer; | 
						|
         var task = git._runCache.shift(); | 
						|
 | 
						|
         var command = task[0]; | 
						|
         var then = task[1]; | 
						|
         var options = task[2]; | 
						|
 | 
						|
         debug(command); | 
						|
 | 
						|
         var result = deferred(); | 
						|
 | 
						|
         var attempted = false; | 
						|
         var attemptClose = function attemptClose (e) { | 
						|
 | 
						|
            // closing when there is content, terminate immediately | 
						|
            if (attempted || stdErr.length || stdOut.length) { | 
						|
               result.resolve(e); | 
						|
               attempted = true; | 
						|
            } | 
						|
 | 
						|
            // first attempt at closing but no content yet, wait briefly for the close/exit that may follow | 
						|
            if (!attempted) { | 
						|
               attempted = true; | 
						|
               setTimeout(attemptClose.bind(this, e), 50); | 
						|
            } | 
						|
 | 
						|
         }; | 
						|
 | 
						|
         var stdOut = []; | 
						|
         var stdErr = []; | 
						|
         var spawned = git.ChildProcess.spawn(git._command, command.slice(0), { | 
						|
            cwd: git._baseDir, | 
						|
            env: git._env, | 
						|
            windowsHide: true | 
						|
         }); | 
						|
 | 
						|
         spawned.stdout.on('data', function (buffer) { | 
						|
            stdOut.push(buffer); | 
						|
         }); | 
						|
 | 
						|
         spawned.stderr.on('data', function (buffer) { | 
						|
            stdErr.push(buffer); | 
						|
         }); | 
						|
 | 
						|
         spawned.on('error', function (err) { | 
						|
            stdErr.push(Buffer.from(err.stack, 'ascii')); | 
						|
         }); | 
						|
 | 
						|
         spawned.on('close', attemptClose); | 
						|
         spawned.on('exit', attemptClose); | 
						|
 | 
						|
         result.promise.then(function (exitCode) { | 
						|
            function done (output) { | 
						|
               then.call(git, null, output); | 
						|
            } | 
						|
 | 
						|
            function fail (error) { | 
						|
               Git.fail(git, error, then); | 
						|
            } | 
						|
 | 
						|
            delete git._childProcess; | 
						|
 | 
						|
            if (exitCode && stdErr.length && options.onError) { | 
						|
               options.onError(exitCode, Buffer.concat(stdErr).toString('utf-8'), done, fail); | 
						|
            } | 
						|
            else if (exitCode && stdErr.length) { | 
						|
               fail(Buffer.concat(stdErr).toString('utf-8')); | 
						|
            } | 
						|
            else { | 
						|
               if (options.concatStdErr) { | 
						|
                  [].push.apply(stdOut, stdErr); | 
						|
               } | 
						|
 | 
						|
               var stdOutput = Buffer.concat(stdOut); | 
						|
               if (options.format !== 'buffer') { | 
						|
                  stdOutput = stdOutput.toString(options.format || 'utf-8'); | 
						|
               } | 
						|
 | 
						|
               done(stdOutput); | 
						|
            } | 
						|
 | 
						|
            process.nextTick(git._schedule.bind(git)); | 
						|
         }); | 
						|
 | 
						|
         git._childProcess = spawned; | 
						|
 | 
						|
         if (git._outputHandler) { | 
						|
            git._outputHandler(command[0], git._childProcess.stdout, git._childProcess.stderr); | 
						|
         } | 
						|
      } | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Handles an exception in the processing of a command. | 
						|
    */ | 
						|
   Git.fail = function (git, error, handler) { | 
						|
      git._getLog('error', error); | 
						|
      git._runCache.length = 0; | 
						|
      if (typeof handler === 'function') { | 
						|
         handler.call(git, error, null); | 
						|
      } | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * 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; | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Given any number of arguments, returns the trailing options argument, ignoring a trailing function argument | 
						|
    * if there is one. When not found, the return value is null. | 
						|
    * @returns {Object|null} | 
						|
    */ | 
						|
   Git.trailingOptionsArgument = function (args) { | 
						|
      var options = args[(args.length - (Git.trailingFunctionArgument(args) ? 2 : 1))]; | 
						|
      return Object.prototype.toString.call(options) === '[object Object]' ? options : null; | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Given any number of arguments, returns the trailing options array argument, ignoring a trailing function argument | 
						|
    * if there is one. When not found, the return value is an empty array. | 
						|
    * @returns {Array} | 
						|
    */ | 
						|
   Git.trailingArrayArgument = function (args) { | 
						|
      var options = args[(args.length - (Git.trailingFunctionArgument(args) ? 2 : 1))]; | 
						|
      return Object.prototype.toString.call(options) === '[object Array]' ? options : []; | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Mutates the supplied command array by merging in properties in the options object. When the | 
						|
    * value of the item in the options object is a string it will be concatenated to the key as | 
						|
    * a single `name=value` item, otherwise just the name will be used. | 
						|
    * | 
						|
    * @param {string[]} command | 
						|
    * @param {Object} options | 
						|
    * @private | 
						|
    */ | 
						|
   Git._appendOptions = function (command, options) { | 
						|
      if (options === null) { | 
						|
         return; | 
						|
      } | 
						|
 | 
						|
      Object.keys(options).forEach(function (key) { | 
						|
         var value = options[key]; | 
						|
         if (typeof value === 'string') { | 
						|
            command.push(key + '=' + value); | 
						|
         } | 
						|
         else { | 
						|
            command.push(key); | 
						|
         } | 
						|
      }); | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Given the type of response and the callback to receive the parsed response, | 
						|
    * uses the correct parser and calls back the callback. | 
						|
    * | 
						|
    * @param {Function} callback | 
						|
    * @param {string} [type] | 
						|
    * @param {Object[]} [args] | 
						|
    * | 
						|
    * @private | 
						|
    */ | 
						|
   Git._responseHandler = function (callback, type, args) { | 
						|
      return function (error, data) { | 
						|
         if (typeof callback !== 'function') { | 
						|
            return; | 
						|
         } | 
						|
 | 
						|
         if (error) { | 
						|
            return callback(error, null); | 
						|
         } | 
						|
 | 
						|
         if (!type) { | 
						|
            return callback(null, data); | 
						|
         } | 
						|
 | 
						|
         var handler = requireResponseHandler(type); | 
						|
         var result = handler.parse.apply(handler, [data].concat(args === undefined ? [] : args)); | 
						|
 | 
						|
         callback(null, result); | 
						|
      }; | 
						|
 | 
						|
   }; | 
						|
 | 
						|
   /** | 
						|
    * Marks the git instance as having had a fatal exception by clearing the pending queue of tasks and | 
						|
    * logging to the console. | 
						|
    * | 
						|
    * @param git | 
						|
    * @param error | 
						|
    * @param callback | 
						|
    */ | 
						|
   Git.exception = function (git, error, callback) { | 
						|
      git._runCache.length = 0; | 
						|
      if (typeof callback === 'function') { | 
						|
         callback(error instanceof Error ? error : new Error(error)); | 
						|
      } | 
						|
 | 
						|
      git._getLog('error', error); | 
						|
   }; | 
						|
 | 
						|
   module.exports = Git; | 
						|
 | 
						|
   /** | 
						|
    * Requires and returns a response handler based on its named type | 
						|
    * @param {string} type | 
						|
    */ | 
						|
   function requireResponseHandler (type) { | 
						|
      return responses[type]; | 
						|
   } | 
						|
 | 
						|
}());
 | 
						|
 |