History

Update Git documentation (2.30.0)

Simon Legner committed 5 years ago

Commit 3600a9f1 parent 8f17cfa41 files · +4398 −1Browse files

Showing the changes to node_modules/simple-git/src (18 of 41 files). Show all

Unified · Split

18 files
  1. node_modules/simple-git/src/git.js +1592 −0
  2. node_modules/simple-git/src/index.js +14 −0
  3. node_modules/simple-git/src/responses/BranchDeleteSummary.js +26 −0
  4. node_modules/simple-git/src/responses/BranchSummary.js +52 −0
  5. node_modules/simple-git/src/responses/CommitSummary.js +60 −0
  6. node_modules/simple-git/src/responses/DiffSummary.js +92 −0
  7. node_modules/simple-git/src/responses/FetchSummary.js +55 −0
  8. node_modules/simple-git/src/responses/FileStatusSummary.js +22 −0
  9. node_modules/simple-git/src/responses/ListLogSummary.js +72 −0
  10. node_modules/simple-git/src/responses/MergeSummary.js +103 −0
  11. node_modules/simple-git/src/responses/MoveSummary.js +32 −0
  12. node_modules/simple-git/src/responses/PullSummary.js +137 −0
  13. node_modules/simple-git/src/responses/StatusSummary.js +188 −0
  14. node_modules/simple-git/src/responses/TagList.js +50 −0
  15. node_modules/simple-git/src/responses/index.js +15 −0
  16. node_modules/simple-git/src/util/deferred.js +10 −0
  17. node_modules/simple-git/src/util/dependencies.js +12 −0
  18. node_modules/simple-git/src/util/exists.js +33 −0
node_modules/simple-git/src/git.js+1592−0
@@ -0,0 +1,1592 @@
1+(function () {
2+
3+ 'use strict';
4+
5+ var debug = require('debug')('simple-git');
6+ var deferred = require('./util/deferred');
7+ var exists = require('./util/exists');
8+ var NOOP = function () {};
9+ var responses = require('./responses');
10+
11+ /**
12+ * Git handling for node. All public functions can be chained and all `then` handlers are optional.
13+ *
14+ * @param {string} baseDir base directory for all processes to run
15+ *
16+ * @param {Object} ChildProcess The ChildProcess module
17+ * @param {Function} Buffer The Buffer implementation to use
18+ *
19+ * @constructor
20+ */
21+ function Git (baseDir, ChildProcess, Buffer) {
22+ this._baseDir = baseDir;
23+ this._runCache = [];
24+
25+ this.ChildProcess = ChildProcess;
26+ this.Buffer = Buffer;
27+ }
28+
29+ /**
30+ * @type {string} The command to use to reference the git binary
31+ */
32+ Git.prototype._command = 'git';
33+
34+ /**
35+ * @type {[key: string]: string} An object of key=value pairs to be passed as environment variables to the
36+ * spawned child process.
37+ */
38+ Git.prototype._env = null;
39+
40+ /**
41+ * @type {Function} An optional handler to use when a child process is created
42+ */
43+ Git.prototype._outputHandler = null;
44+
45+ /**
46+ * @type {boolean} Property showing whether logging will be silenced - defaults to true in a production environment
47+ */
48+ Git.prototype._silentLogging = /prod/.test(process.env.NODE_ENV);
49+
50+ /**
51+ * Sets the path to a custom git binary, should either be `git` when there is an installation of git available on
52+ * the system path, or a fully qualified path to the executable.
53+ *
54+ * @param {string} command
55+ * @returns {Git}
56+ */
57+ Git.prototype.customBinary = function (command) {
58+ this._command = command;
59+ return this;
60+ };
61+
62+ /**
63+ * Sets an environment variable for the spawned child process, either supply both a name and value as strings or
64+ * a single object to entirely replace the current environment variables.
65+ *
66+ * @param {string|Object} name
67+ * @param {string} [value]
68+ * @returns {Git}
69+ */
70+ Git.prototype.env = function (name, value) {
71+ if (arguments.length === 1 && typeof name === 'object') {
72+ this._env = name;
73+ }
74+ else {
75+ (this._env = this._env || {})[name] = value;
76+ }
77+
78+ return this;
79+ };
80+
81+ /**
82+ * Sets the working directory of the subsequent commands.
83+ *
84+ * @param {string} workingDirectory
85+ * @param {Function} [then]
86+ * @returns {Git}
87+ */
88+ Git.prototype.cwd = function (workingDirectory, then) {
89+ var git = this;
90+ var next = Git.trailingFunctionArgument(arguments);
91+
92+ return this.exec(function () {
93+ git._baseDir = workingDirectory;
94+ if (!exists(workingDirectory, exists.FOLDER)) {
95+ Git.exception(git, 'Git.cwd: cannot change to non-directory "' + workingDirectory + '"', next);
96+ }
97+ else {
98+ next && next(null, workingDirectory);
99+ }
100+ });
101+ };
102+
103+ /**
104+ * Sets a handler function to be called whenever a new child process is created, the handler function will be called
105+ * with the name of the command being run and the stdout & stderr streams used by the ChildProcess.
106+ *
107+ * @example
108+ * require('simple-git')
109+ * .outputHandler(function (command, stdout, stderr) {
110+ * stdout.pipe(process.stdout);
111+ * })
112+ * .checkout('https://github.com/user/repo.git');
113+ *
114+ * @see https://nodejs.org/api/child_process.html#child_process_class_childprocess
115+ * @see https://nodejs.org/api/stream.html#stream_class_stream_readable
116+ * @param {Function} outputHandler
117+ * @returns {Git}
118+ */
119+ Git.prototype.outputHandler = function (outputHandler) {
120+ this._outputHandler = outputHandler;
121+ return this;
122+ };
123+
124+ /**
125+ * Initialize a git repo
126+ *
127+ * @param {Boolean} [bare=false]
128+ * @param {Function} [then]
129+ */
130+ Git.prototype.init = function (bare, then) {
131+ var commands = ['init'];
132+ var next = Git.trailingFunctionArgument(arguments);
133+
134+ if (bare === true) {
135+ commands.push('--bare');
136+ }
137+
138+ return this._run(commands, function (err) {
139+ next && next(err);
140+ });
141+ };
142+
143+ /**
144+ * Check the status of the local repo
145+ *
146+ * @param {Function} [then]
147+ */
148+ Git.prototype.status = function (then) {
149+ return this._run(
150+ ['status', '--porcelain', '-b', '-u'],
151+ Git._responseHandler(then, 'StatusSummary')
152+ );
153+ };
154+
155+ /**
156+ * List the stash(s) of the local repo
157+ *
158+ * @param {Object|Array} [options]
159+ * @param {Function} [then]
160+ */
161+ Git.prototype.stashList = function (options, then) {
162+ var handler = Git.trailingFunctionArgument(arguments);
163+ var opt = (handler === then ? options : null) || {};
164+
165+ var splitter = opt.splitter || requireResponseHandler('ListLogSummary').SPLITTER;
166+ var command = ["stash", "list", "--pretty=format:"
167+ + requireResponseHandler('ListLogSummary').START_BOUNDARY
168+ + "%H %ai %s%d %aN %ae".replace(/\s+/g, splitter)
169+ + requireResponseHandler('ListLogSummary').COMMIT_BOUNDARY
170+ ];
171+
172+ if (Array.isArray(opt)) {
173+ command = command.concat(opt);
174+ }
175+
176+ return this._run(command,
177+ Git._responseHandler(handler, 'ListLogSummary', splitter)
178+ );
179+ };
180+
181+ /**
182+ * Stash the local repo
183+ *
184+ * @param {Object|Array} [options]
185+ * @param {Function} [then]
186+ */
187+ Git.prototype.stash = function (options, then) {
188+ var command = ['stash'];
189+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
190+ command.push.apply(command, Git.trailingArrayArgument(arguments));
191+
192+ return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments)));
193+ };
194+
195+ /**
196+ * Clone a git repo
197+ *
198+ * @param {string} repoPath
199+ * @param {string} localPath
200+ * @param {String[]} [options] Optional array of options to pass through to the clone command
201+ * @param {Function} [then]
202+ */
203+ Git.prototype.clone = function (repoPath, localPath, options, then) {
204+ var next = Git.trailingFunctionArgument(arguments);
205+ var command = ['clone'].concat(Git.trailingArrayArgument(arguments));
206+
207+ for (var i = 0, iMax = arguments.length; i < iMax; i++) {
208+ if (typeof arguments[i] === 'string') {
209+ command.push(arguments[i]);
210+ }
211+ }
212+
213+ return this._run(command, function (err, data) {
214+ next && next(err, data);
215+ });
216+ };
217+
218+ /**
219+ * Mirror a git repo
220+ *
221+ * @param {string} repoPath
222+ * @param {string} localPath
223+ * @param {Function} [then]
224+ */
225+ Git.prototype.mirror = function (repoPath, localPath, then) {
226+ return this.clone(repoPath, localPath, ['--mirror'], then);
227+ };
228+
229+ /**
230+ * Moves one or more files to a new destination.
231+ *
232+ * @see https://git-scm.com/docs/git-mv
233+ *
234+ * @param {string|string[]} from
235+ * @param {string} to
236+ * @param {Function} [then]
237+ */
238+ Git.prototype.mv = function (from, to, then) {
239+ var handler = Git.trailingFunctionArgument(arguments);
240+
241+ var command = [].concat(from);
242+ command.unshift('mv', '-v');
243+ command.push(to);
244+
245+ this._run(command, Git._responseHandler(handler, 'MoveSummary'))
246+ };
247+
248+ /**
249+ * Internally uses pull and tags to get the list of tags then checks out the latest tag.
250+ *
251+ * @param {Function} [then]
252+ */
253+ Git.prototype.checkoutLatestTag = function (then) {
254+ var git = this;
255+ return this.pull(function () {
256+ git.tags(function (err, tags) {
257+ git.checkout(tags.latest, then);
258+ });
259+ });
260+ };
261+
262+ /**
263+ * Adds one or more files to source control
264+ *
265+ * @param {string|string[]} files
266+ * @param {Function} [then]
267+ */
268+ Git.prototype.add = function (files, then) {
269+ return this._run(['add'].concat(files), function (err, data) {
270+ then && then(err);
271+ });
272+ };
273+
274+ /**
275+ * Commits changes in the current working directory - when specific file paths are supplied, only changes on those
276+ * files will be committed.
277+ *
278+ * @param {string|string[]} message
279+ * @param {string|string[]} [files]
280+ * @param {Object} [options]
281+ * @param {Function} [then]
282+ */
283+ Git.prototype.commit = function (message, files, options, then) {
284+ var handler = Git.trailingFunctionArgument(arguments);
285+
286+ var command = ['commit'];
287+
288+ [].concat(message).forEach(function (message) {
289+ command.push('-m', message);
290+ });
291+
292+ [].push.apply(command, [].concat(typeof files === "string" || Array.isArray(files) ? files : []));
293+
294+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
295+
296+ return this._run(
297+ command,
298+ Git._responseHandler(handler, 'CommitSummary')
299+ );
300+ };
301+
302+ /**
303+ * Gets a function to be used for logging.
304+ *
305+ * @param {string} level
306+ * @param {string} [message]
307+ *
308+ * @returns {Function}
309+ * @private
310+ */
311+ Git.prototype._getLog = function (level, message) {
312+ var log = this._silentLogging ? NOOP : console[level].bind(console);
313+ if (arguments.length > 1) {
314+ log(message);
315+ }
316+ return log;
317+ };
318+
319+ /**
320+ * Pull the updated contents of the current repo
321+ *
322+ * @param {string} [remote] When supplied must also include the branch
323+ * @param {string} [branch] When supplied must also include the remote
324+ * @param {Object} [options] Optionally include set of options to merge into the command
325+ * @param {Function} [then]
326+ */
327+ Git.prototype.pull = function (remote, branch, options, then) {
328+ var command = ["pull"];
329+ var handler = Git.trailingFunctionArgument(arguments);
330+
331+ if (typeof remote === 'string' && typeof branch === 'string') {
332+ command.push(remote, branch);
333+ }
334+
335+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
336+
337+ return this._run(command, Git._responseHandler(handler, 'PullSummary'));
338+ };
339+
340+ /**
341+ * Fetch the updated contents of the current repo.
342+ *
343+ * @example
344+ * .fetch('upstream', 'master') // fetches from master on remote named upstream
345+ * .fetch(function () {}) // runs fetch against default remote and branch and calls function
346+ *
347+ * @param {string} [remote]
348+ * @param {string} [branch]
349+ * @param {Function} [then]
350+ */
351+ Git.prototype.fetch = function (remote, branch, then) {
352+ var command = ["fetch"];
353+ var next = Git.trailingFunctionArgument(arguments);
354+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
355+
356+ if (typeof remote === 'string' && typeof branch === 'string') {
357+ command.push(remote, branch);
358+ }
359+
360+ if (Array.isArray(remote)) {
361+ command = command.concat(remote);
362+ }
363+
364+ return this._run(
365+ command,
366+ Git._responseHandler(next, 'FetchSummary'),
367+ {
368+ concatStdErr: true
369+ }
370+ );
371+ };
372+
373+ /**
374+ * Disables/enables the use of the console for printing warnings and errors, by default messages are not shown in
375+ * a production environment.
376+ *
377+ * @param {boolean} silence
378+ * @returns {Git}
379+ */
380+ Git.prototype.silent = function (silence) {
381+ this._silentLogging = !!silence;
382+ return this;
383+ };
384+
385+ /**
386+ * List all tags. When using git 2.7.0 or above, include an options object with `"--sort": "property-name"` to
387+ * sort the tags by that property instead of using the default semantic versioning sort.
388+ *
389+ * Note, supplying this option when it is not supported by your Git version will cause the operation to fail.
390+ *
391+ * @param {Object} [options]
392+ * @param {Function} [then]
393+ */
394+ Git.prototype.tags = function (options, then) {
395+ var next = Git.trailingFunctionArgument(arguments);
396+
397+ var command = ['-l'];
398+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
399+
400+ var hasCustomSort = command.some(function (option) {
401+ return /^--sort=/.test(option);
402+ });
403+
404+ return this.tag(
405+ command,
406+ Git._responseHandler(next, 'TagList', [hasCustomSort])
407+ );
408+ };
409+
410+ /**
411+ * Rebases the current working copy. Options can be supplied either as an array of string parameters
412+ * to be sent to the `git rebase` command, or a standard options object.
413+ *
414+ * @param {Object|String[]} [options]
415+ * @param {Function} [then]
416+ * @returns {Git}
417+ */
418+ Git.prototype.rebase = function (options, then) {
419+ var command = ['rebase'];
420+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
421+ command.push.apply(command, Git.trailingArrayArgument(arguments));
422+
423+
424+ return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments)));
425+ };
426+
427+ /**
428+ * Reset a repo
429+ *
430+ * @param {string|string[]} [mode=soft] Either an array of arguments supported by the 'git reset' command, or the
431+ * string value 'soft' or 'hard' to set the reset mode.
432+ * @param {Function} [then]
433+ */
434+ Git.prototype.reset = function (mode, then) {
435+ var command = ['reset'];
436+ var next = Git.trailingFunctionArgument(arguments);
437+ if (next === mode || typeof mode === 'string' || !mode) {
438+ var modeStr = ['mixed', 'soft', 'hard'].includes(mode) ? mode : 'soft';
439+ command.push('--' + modeStr);
440+ }
441+ else if (Array.isArray(mode)) {
442+ command.push.apply(command, mode);
443+ }
444+
445+ return this._run(command, function (err) {
446+ next && next(err || null);
447+ });
448+ };
449+
450+ /**
451+ * Revert one or more commits in the local working copy
452+ *
453+ * @param {string} commit The commit to revert. Can be any hash, offset (eg: `HEAD~2`) or range (eg: `master~5..master~2`)
454+ * @param {Object} [options] Optional options object
455+ * @param {Function} [then]
456+ */
457+ Git.prototype.revert = function (commit, options, then) {
458+ var next = Git.trailingFunctionArgument(arguments);
459+ var command = ['revert'];
460+
461+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
462+
463+ if (typeof commit !== 'string') {
464+ return this.exec(function () {
465+ next && next(new TypeError("Commit must be a string"));
466+ });
467+ }
468+
469+ command.push(commit);
470+ return this._run(command, function (err) {
471+ next && next(err || null);
472+ });
473+ };
474+
475+ /**
476+ * Add a lightweight tag to the head of the current branch
477+ *
478+ * @param {string} name
479+ * @param {Function} [then]
480+ */
481+ Git.prototype.addTag = function (name, then) {
482+ if (typeof name !== "string") {
483+ return this.exec(function () {
484+ then && then(new TypeError("Git.addTag requires a tag name"));
485+ });
486+ }
487+
488+ var command = [name];
489+ return then ? this.tag(command, then) : this.tag(command);
490+ };
491+
492+ /**
493+ * Add an annotated tag to the head of the current branch
494+ *
495+ * @param {string} tagName
496+ * @param {string} tagMessage
497+ * @param {Function} [then]
498+ */
499+ Git.prototype.addAnnotatedTag = function (tagName, tagMessage, then) {
500+ return this.tag(['-a', '-m', tagMessage, tagName], function (err) {
501+ then && then(err);
502+ });
503+ };
504+
505+ /**
506+ * Check out a tag or revision, any number of additional arguments can be passed to the `git checkout` command
507+ * by supplying either a string or array of strings as the `what` parameter.
508+ *
509+ * @param {string|string[]} what One or more commands to pass to `git checkout`
510+ * @param {Function} [then]
511+ */
512+ Git.prototype.checkout = function (what, then) {
513+ var command = ['checkout'];
514+ command = command.concat(what);
515+
516+ return this._run(command, function (err, data) {
517+ then && then(err, !err && this._parseCheckout(data));
518+ });
519+ };
520+
521+ /**
522+ * Check out a remote branch
523+ *
524+ * @param {string} branchName name of branch
525+ * @param {string} startPoint (e.g origin/development)
526+ * @param {Function} [then]
527+ */
528+ Git.prototype.checkoutBranch = function (branchName, startPoint, then) {
529+ return this.checkout(['-b', branchName, startPoint], then);
530+ };
531+
532+ /**
533+ * Check out a local branch
534+ *
535+ * @param {string} branchName of branch
536+ * @param {Function} [then]
537+ */
538+ Git.prototype.checkoutLocalBranch = function (branchName, then) {
539+ return this.checkout(['-b', branchName], then);
540+ };
541+
542+ /**
543+ * Delete a local branch
544+ *
545+ * @param {string} branchName name of branch
546+ * @param {Function} [then]
547+ */
548+ Git.prototype.deleteLocalBranch = function (branchName, then) {
549+ return this.branch(['-d', branchName], then);
550+ };
551+
552+ /**
553+ * List all branches
554+ *
555+ * @param {Object | string[]} [options]
556+ * @param {Function} [then]
557+ */
558+ Git.prototype.branch = function (options, then) {
559+ var isDelete, responseHandler;
560+ var next = Git.trailingFunctionArgument(arguments);
561+ var command = ['branch'];
562+
563+ command.push.apply(command, Git.trailingArrayArgument(arguments));
564+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
565+
566+ if (!arguments.length || next === options) {
567+ command.push('-a');
568+ }
569+
570+ isDelete = ['-d', '-D', '--delete'].reduce(function (isDelete, flag) {
571+ return isDelete || command.indexOf(flag) > 0;
572+ }, false);
573+
574+ if (command.indexOf('-v') < 0) {
575+ command.splice(1, 0, '-v');
576+ }
577+
578+ responseHandler = isDelete
579+ ? Git._responseHandler(next, 'BranchDeleteSummary', false)
580+ : Git._responseHandler(next, 'BranchSummary');
581+
582+ return this._run(command, responseHandler);
583+ };
584+
585+ /**
586+ * Return list of local branches
587+ *
588+ * @param {Function} [then]
589+ */
590+ Git.prototype.branchLocal = function (then) {
591+ return this.branch(['-v'], then);
592+ };
593+
594+ /**
595+ * Add config to local git instance
596+ *
597+ * @param {string} key configuration key (e.g user.name)
598+ * @param {string} value for the given key (e.g your name)
599+ * @param {Function} [then]
600+ */
601+ Git.prototype.addConfig = function (key, value, then) {
602+ return this._run(['config', '--local', key, value], function (err, data) {
603+ then && then(err, !err && data);
604+ });
605+ };
606+
607+ /**
608+ * Executes any command against the git binary.
609+ *
610+ * @param {string[]|Object} commands
611+ * @param {Function} [then]
612+ *
613+ * @returns {Git}
614+ */
615+ Git.prototype.raw = function (commands, then) {
616+ var command = [];
617+ if (Array.isArray(commands)) {
618+ command = commands.slice(0);
619+ }
620+ else {
621+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
622+ }
623+
624+ var next = Git.trailingFunctionArgument(arguments);
625+
626+ if (!command.length) {
627+ return this.exec(function () {
628+ next && next(new Error('Raw: must supply one or more command to execute'), null);
629+ });
630+ }
631+
632+ return this._run(command, function (err, data) {
633+ next && next(err, !err && data || null);
634+ });
635+ };
636+
637+ /**
638+ * Add a submodule
639+ *
640+ * @param {string} repo
641+ * @param {string} path
642+ * @param {Function} [then]
643+ */
644+ Git.prototype.submoduleAdd = function (repo, path, then) {
645+ return this._run(['submodule', 'add', repo, path], function (err) {
646+ then && then(err);
647+ });
648+ };
649+
650+ /**
651+ * Update submodules
652+ *
653+ * @param {string[]} [args]
654+ * @param {Function} [then]
655+ */
656+ Git.prototype.submoduleUpdate = function (args, then) {
657+ if (typeof args === 'string') {
658+ this._getLog('warn', 'Git#submoduleUpdate: args should be supplied as an array of individual arguments');
659+ }
660+
661+ var next = Git.trailingFunctionArgument(arguments);
662+ var command = (args !== next) ? args : [];
663+
664+ return this.subModule(['update'].concat(command), function (err, args) {
665+ next && next(err, args);
666+ });
667+ };
668+
669+ /**
670+ * Initialize submodules
671+ *
672+ * @param {string[]} [args]
673+ * @param {Function} [then]
674+ */
675+ Git.prototype.submoduleInit = function (args, then) {
676+ if (typeof args === 'string') {
677+ this._getLog('warn', 'Git#submoduleInit: args should be supplied as an array of individual arguments');
678+ }
679+
680+ var next = Git.trailingFunctionArgument(arguments);
681+ var command = (args !== next) ? args : [];
682+
683+ return this.subModule(['init'].concat(command), function (err, args) {
684+ next && next(err, args);
685+ });
686+ };
687+
688+ /**
689+ * Call any `git submodule` function with arguments passed as an array of strings.
690+ *
691+ * @param {string[]} options
692+ * @param {Function} [then]
693+ */
694+ Git.prototype.subModule = function (options, then) {
695+ if (!Array.isArray(options)) {
696+ return this.exec(function () {
697+ then && then(new TypeError("Git.subModule requires an array of arguments"));
698+ });
699+ }
700+
701+ if (options[0] !== 'submodule') {
702+ options.unshift('submodule');
703+ }
704+
705+ return this._run(options, function (err, data) {
706+ then && then(err || null, err ? null : data);
707+ });
708+ };
709+
710+ /**
711+ * List remote
712+ *
713+ * @param {string[]} [args]
714+ * @param {Function} [then]
715+ */
716+ Git.prototype.listRemote = function (args, then) {
717+ var next = Git.trailingFunctionArgument(arguments);
718+ var data = next === args || args === undefined ? [] : args;
719+
720+ if (typeof data === 'string') {
721+ this._getLog('warn', 'Git#listRemote: args should be supplied as an array of individual arguments');
722+ }
723+
724+ return this._run(['ls-remote'].concat(data), function (err, data) {
725+ next && next(err, data);
726+ });
727+ };
728+
729+ /**
730+ * Adds a remote to the list of remotes.
731+ *
732+ * @param {string} remoteName Name of the repository - eg "upstream"
733+ * @param {string} remoteRepo Fully qualified SSH or HTTP(S) path to the remote repo
734+ * @param {Function} [then]
735+ * @returns {*}
736+ */
737+ Git.prototype.addRemote = function (remoteName, remoteRepo, then) {
738+ return this._run(['remote', 'add', remoteName, remoteRepo], function (err) {
739+ then && then(err);
740+ });
741+ };
742+
743+ /**
744+ * Removes an entry from the list of remotes.
745+ *
746+ * @param {string} remoteName Name of the repository - eg "upstream"
747+ * @param {Function} [then]
748+ * @returns {*}
749+ */
750+ Git.prototype.removeRemote = function (remoteName, then) {
751+ return this._run(['remote', 'remove', remoteName], function (err) {
752+ then && then(err);
753+ });
754+ };
755+
756+ /**
757+ * Gets the currently available remotes, setting the optional verbose argument to true includes additional
758+ * detail on the remotes themselves.
759+ *
760+ * @param {boolean} [verbose=false]
761+ * @param {Function} [then]
762+ */
763+ Git.prototype.getRemotes = function (verbose, then) {
764+ var next = Git.trailingFunctionArgument(arguments);
765+ var args = verbose === true ? ['-v'] : [];
766+
767+ return this.remote(args, function (err, data) {
768+ next && next(err, !err && function () {
769+ return data.trim().split('\n').filter(Boolean).reduce(function (remotes, remote) {
770+ var detail = remote.trim().split(/\s+/);
771+ var name = detail.shift();
772+
773+ if (!remotes[name]) {
774+ remotes[name] = remotes[remotes.length] = {
775+ name: name,
776+ refs: {}
777+ };
778+ }
779+
780+ if (detail.length) {
781+ remotes[name].refs[detail.pop().replace(/[^a-z]/g, '')] = detail.pop();
782+ }
783+
784+ return remotes;
785+ }, []).slice(0);
786+ }());
787+ });
788+ };
789+
790+ /**
791+ * Call any `git remote` function with arguments passed as an array of strings.
792+ *
793+ * @param {string[]} options
794+ * @param {Function} [then]
795+ */
796+ Git.prototype.remote = function (options, then) {
797+ if (!Array.isArray(options)) {
798+ return this.exec(function () {
799+ then && then(new TypeError("Git.remote requires an array of arguments"));
800+ });
801+ }
802+
803+ if (options[0] !== 'remote') {
804+ options.unshift('remote');
805+ }
806+
807+ return this._run(options, function (err, data) {
808+ then && then(err || null, err ? null : data);
809+ });
810+ };
811+
812+ /**
813+ * Merges from one branch to another, equivalent to running `git merge ${from} $[to}`, the `options` argument can
814+ * either be an array of additional parameters to pass to the command or null / omitted to be ignored.
815+ *
816+ * @param {string} from
817+ * @param {string} to
818+ * @param {string[]} [options]
819+ * @param {Function} [then]
820+ */
821+ Git.prototype.mergeFromTo = function (from, to, options, then) {
822+ var commands = [
823+ from,
824+ to
825+ ];
826+ var callback = Git.trailingFunctionArgument(arguments);
827+
828+ if (Array.isArray(options)) {
829+ commands = commands.concat(options);
830+ }
831+
832+ return this.merge(commands, callback);
833+ };
834+
835+ /**
836+ * Runs a merge, `options` can be either an array of arguments
837+ * supported by the [`git merge`](https://git-scm.com/docs/git-merge)
838+ * or an options object.
839+ *
840+ * Conflicts during the merge result in an error response,
841+ * the response type whether it was an error or success will be a MergeSummary instance.
842+ * When successful, the MergeSummary has all detail from a the PullSummary
843+ *
844+ * @param {Object | string[]} [options]
845+ * @param {Function} [then]
846+ * @returns {*}
847+ *
848+ * @see ./responses/MergeSummary.js
849+ * @see ./responses/PullSummary.js
850+ */
851+ Git.prototype.merge = function (options, then) {
852+ var self = this;
853+ var userHandler = Git.trailingFunctionArgument(arguments) || NOOP;
854+ var mergeHandler = function (err, mergeSummary) {
855+ if (!err && mergeSummary.failed) {
856+ return Git.fail(self, mergeSummary, userHandler);
857+ }
858+
859+ userHandler(err, mergeSummary);
860+ };
861+
862+ var command = [];
863+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
864+ command.push.apply(command, Git.trailingArrayArgument(arguments));
865+
866+ if (command[0] !== 'merge') {
867+ command.unshift('merge');
868+ }
869+
870+ if (command.length === 1) {
871+ return this.exec(function () {
872+ then && then(new TypeError("Git.merge requires at least one option"));
873+ });
874+ }
875+
876+ return this._run(command, Git._responseHandler(mergeHandler, 'MergeSummary'), {
877+ concatStdErr: true
878+ });
879+ };
880+
881+ /**
882+ * Call any `git tag` function with arguments passed as an array of strings.
883+ *
884+ * @param {string[]} options
885+ * @param {Function} [then]
886+ */
887+ Git.prototype.tag = function (options, then) {
888+ var command = [];
889+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
890+ command.push.apply(command, Git.trailingArrayArgument(arguments));
891+
892+ if (command[0] !== 'tag') {
893+ command.unshift('tag');
894+ }
895+
896+ return this._run(command, Git._responseHandler(Git.trailingFunctionArgument(arguments)));
897+ };
898+
899+ /**
900+ * Updates repository server info
901+ *
902+ * @param {Function} [then]
903+ */
904+ Git.prototype.updateServerInfo = function (then) {
905+ return this._run(["update-server-info"], function (err, data) {
906+ then && then(err, !err && data);
907+ });
908+ };
909+
910+ /**
911+ * Pushes the current committed changes to a remote, optionally specify the names of the remote and branch to use
912+ * when pushing. Supply multiple options as an array of strings in the first argument - see examples below.
913+ *
914+ * @param {string|string[]} [remote]
915+ * @param {string} [branch]
916+ * @param {Function} [then]
917+ */
918+ Git.prototype.push = function (remote, branch, then) {
919+ var command = [];
920+ var handler = Git.trailingFunctionArgument(arguments);
921+
922+ if (typeof remote === 'string' && typeof branch === 'string') {
923+ command.push(remote, branch);
924+ }
925+
926+ if (Array.isArray(remote)) {
927+ command = command.concat(remote);
928+ }
929+
930+ Git._appendOptions(command, Git.trailingOptionsArgument(arguments));
931+
932+ if (command[0] !== 'push') {
933+ command.unshift('push');
934+ }
935+
936+ return this._run(command, function (err, data) {
937+ handler && handler(err, !err && data);
938+ });
939+ };
940+
941+ /**
942+ * Pushes the current tag changes to a remote which can be either a URL or named remote. When not specified uses the
943+ * default configured remote spec.
944+ *
945+ * @param {string} [remote]
946+ * @param {Function} [then]
947+ */
948+ Git.prototype.pushTags = function (remote, then) {
949+ var command = ['push'];
950+ if (typeof remote === "string") {
951+ command.push(remote);
952+ }
953+ command.push('--tags');
954+
955+ then = typeof arguments[arguments.length - 1] === "function" ? arguments[arguments.length - 1] : null;
956+
957+ return this._run(command, function (err, data) {
958+ then && then(err, !err && data);
959+ });
960+ };
961+
962+ /**
963+ * Removes the named files from source control.
964+ *
965+ * @param {string|string[]} files
966+ * @param {Function} [then]
967+ */
968+ Git.prototype.rm = function (files, then) {
969+ return this._rm(files, '-f', then);
970+ };
971+
972+ /**
973+ * Removes the named files from source control but keeps them on disk rather than deleting them entirely. To
974+ * completely remove the files, use `rm`.
975+ *
976+ * @param {string|string[]} files
977+ * @param {Function} [then]
978+ */
979+ Git.prototype.rmKeepLocal = function (files, then) {
980+ return this._rm(files, '--cached', then);
981+ };
982+
983+ /**
984+ * Returns a list of objects in a tree based on commit hash. Passing in an object hash returns the object's content,
985+ * size, and type.
986+ *
987+ * Passing "-p" will instruct cat-file to determine the object type, and display its formatted contents.
988+ *
989+ * @param {string[]} [options]
990+ * @param {Function} [then]
991+ */
992+ Git.prototype.catFile = function (options, then) {
993+ return this._catFile('utf-8', arguments);
994+ };
995+
996+ /**
997+ * Equivalent to `catFile` but will return the native `Buffer` of content from the git command's stdout.
998+ *
999+ * @param {string[]} options
1000+ * @param then
1001+ */
1002+ Git.prototype.binaryCatFile = function (options, then) {
1003+ return this._catFile('buffer', arguments);
1004+ };
1005+
1006+ Git.prototype._catFile = function (format, args) {
1007+ var handler = Git.trailingFunctionArgument(args);
1008+ var command = ['cat-file'];
1009+ var options = args[0];
1010+
1011+ if (typeof options === 'string') {
1012+ throw new TypeError('Git#catFile: options must be supplied as an array of strings');
1013+ }
1014+ else if (Array.isArray(options)) {
1015+ command.push.apply(command, options);
1016+ }
1017+
1018+ return this._run(command, function (err, data) {
1019+ handler && handler(err, data);
1020+ }, {
1021+ format: format
1022+ });
1023+ };
1024+
1025+ /**
1026+ * Return repository changes.
1027+ *
1028+ * @param {string[]} [options]
1029+ * @param {Function} [then]
1030+ */
1031+ Git.prototype.diff = function (options, then) {
1032+ var command = ['diff'];
1033+
1034+ if (typeof options === 'string') {
1035+ command[0] += ' ' + options;
1036+ this._getLog('warn',
1037+ 'Git#diff: supplying options as a single string is now deprecated, switch to an array of strings');
1038+ }
1039+ else if (Array.isArray(options)) {
1040+ command.push.apply(command, options);
1041+ }
1042+
1043+ if (typeof arguments[arguments.length - 1] === 'function') {
1044+ then = arguments[arguments.length - 1];
1045+ }
1046+
1047+ return this._run(command, function (err, data) {
1048+ then && then(err, data);
1049+ });
1050+ };
1051+
1052+ Git.prototype.diffSummary = function (options, then) {
1053+ var next = Git.trailingFunctionArgument(arguments);
1054+ var command = ['--stat=4096'];
1055+
1056+ if (options && options !== next) {
1057+ command.push.apply(command, [].concat(options));
1058+ }
1059+
1060+ return this.diff(command, Git._responseHandler(next, 'DiffSummary'));
1061+ };
1062+
1063+ /**
1064+ * Wraps `git rev-parse`. Primarily used to convert friendly commit references (ie branch names) to SHA1 hashes.
1065+ *
1066+ * Options should be an array of string options compatible with the `git rev-parse`
1067+ *
1068+ * @param {string|string[]} [options]
1069+ * @param {Function} [then]
1070+ *
1071+ * @see https://git-scm.com/docs/git-rev-parse
1072+ */
1073+ Git.prototype.revparse = function (options, then) {
1074+ var command = ['rev-parse'];
1075+
1076+ if (typeof options === 'string') {
1077+ command = command + ' ' + options;
1078+ this._getLog('warn',
1079+ 'Git#revparse: supplying options as a single string is now deprecated, switch to an array of strings');
1080+ }
1081+ else if (Array.isArray(options)) {
1082+ command.push.apply(command, options);
1083+ }
1084+
1085+ if (typeof arguments[arguments.length - 1] === 'function') {
1086+ then = arguments[arguments.length - 1];
1087+ }
1088+
1089+ return this._run(command, function (err, data) {
1090+ then && then(err, err ? null : String(data).trim());
1091+ });
1092+ };
1093+
1094+ /**
1095+ * Show various types of objects, for example the file at a certain commit
1096+ *
1097+ * @param {string[]} [options]
1098+ * @param {Function} [then]
1099+ */
1100+ Git.prototype.show = function (options, then) {
1101+ var args = [].slice.call(arguments, 0);
1102+ var handler = typeof args[args.length - 1] === "function" ? args.pop() : null;
1103+ var command = ['show'];
1104+ if (typeof options === 'string') {
1105+ command = command + ' ' + options;
1106+ this._getLog('warn',
1107+ 'Git#show: supplying options as a single string is now deprecated, switch to an array of strings');
1108+ }
1109+ else if (Array.isArray(options)) {
1110+ command.push.apply(command, options);
1111+ }
1112+
1113+ return this._run(command, function (err, data) {
1114+ handler && handler(err, !err && data);
1115+ });
1116+ };
1117+
1118+ /**
1119+ * @param {string} mode Required parameter "n" or "f"
1120+ * @param {string[]} options
1121+ * @param {Function} [then]
1122+ */
1123+ Git.prototype.clean = function (mode, options, then) {
1124+ var handler = Git.trailingFunctionArgument(arguments);
1125+
1126+ if (typeof mode !== 'string' || !/[nf]/.test(mode)) {
1127+ return this.exec(function () {
1128+ handler && handler(new TypeError('Git clean mode parameter ("n" or "f") is required'));
1129+ });
1130+ }
1131+
1132+ if (/[^dfinqxX]/.test(mode)) {
1133+ return this.exec(function () {
1134+ handler && handler(new TypeError('Git clean unknown option found in ' + JSON.stringify(mode)));
1135+ });
1136+ }
1137+
1138+ var command = ['clean', '-' + mode];
1139+ if (Array.isArray(options)) {
1140+ command = command.concat(options);
1141+ }
1142+
1143+ if (command.some(interactiveMode)) {
1144+ return this.exec(function () {
1145+ handler && handler(new TypeError('Git clean interactive mode is not supported'));
1146+ });
1147+ }
1148+
1149+ return this._run(command, function (err, data) {
1150+ handler && handler(err, !err && data);
1151+ });
1152+
1153+ function interactiveMode (option) {
1154+ if (/^-[^\-]/.test(option)) {
1155+ return option.indexOf('i') > 0;
1156+ }
1157+
1158+ return option === '--interactive';
1159+ }
1160+ };
1161+
1162+ /**
1163+ * Call a simple function at the next step in the chain.
1164+ * @param {Function} [then]
1165+ */
1166+ Git.prototype.exec = function (then) {
1167+ this._run([], function () {
1168+ typeof then === 'function' && then();
1169+ });
1170+ return this;
1171+ };
1172+
1173+ /**
1174+ * Deprecated means of adding a regular function call at the next step in the chain. Use the replacement
1175+ * Git#exec, the Git#then method will be removed in version 2.x
1176+ *
1177+ * @see exec
1178+ * @deprecated
1179+ */
1180+ Git.prototype.then = function (then) {
1181+ this._getLog(
1182+ 'error', `
1183+Git#then is deprecated after version 1.72 and will be removed in version 2.x
1184+To use promises switch to importing 'simple-git/promise'.`);
1185+
1186+ return this.exec(then);
1187+ };
1188+
1189+ /**
1190+ * Show commit logs from `HEAD` to the first commit.
1191+ * If provided between `options.from` and `options.to` tags or branch.
1192+ *
1193+ * Additionally you can provide options.file, which is the path to a file in your repository. Then only this file will be considered.
1194+ *
1195+ * To use a custom splitter in the log format, set `options.splitter` to be the string the log should be split on.
1196+ *
1197+ * Options can also be supplied as a standard options object for adding custom properties supported by the git log command.
1198+ * For any other set of options, supply options as an array of strings to be appended to the git log command.
1199+ *
1200+ * @param {Object|string[]} [options]
1201+ * @param {string} [options.from] The first commit to include
1202+ * @param {string} [options.to] The most recent commit to include
1203+ * @param {string} [options.file] A single file to include in the result
1204+ * @param {boolean} [options.multiLine] Optionally include multi-line commit messages
1205+ *
1206+ * @param {Function} [then]
1207+ */
1208+ Git.prototype.log = function (options, then) {
1209+ var handler = Git.trailingFunctionArgument(arguments);
1210+ var opt = (handler === then ? options : null) || {};
1211+
1212+ var splitter = opt.splitter || requireResponseHandler('ListLogSummary').SPLITTER;
1213+ var format = opt.format || {
1214+ hash: '%H',
1215+ date: '%ai',
1216+ message: '%s',
1217+ refs: '%D',
1218+ body: opt.multiLine ? '%B' : '%b',
1219+ author_name: '%aN',
1220+ author_email: '%ae'
1221+ };
1222+ var rangeOperator = (opt.symmetric !== false) ? '...' : '..';
1223+
1224+ var fields = Object.keys(format);
1225+ var formatstr = fields.map(function (k) {
1226+ return format[k];
1227+ }).join(splitter);
1228+ var suffix = [];
1229+ var command = ["log", "--pretty=format:"
1230+ + requireResponseHandler('ListLogSummary').START_BOUNDARY
1231+ + formatstr
1232+ + requireResponseHandler('ListLogSummary').COMMIT_BOUNDARY
1233+ ];
1234+
1235+ if (Array.isArray(opt)) {
1236+ command = command.concat(opt);
1237+ opt = {};
1238+ }
1239+ else if (typeof arguments[0] === "string" || typeof arguments[1] === "string") {
1240+ this._getLog('warn',
1241+ 'Git#log: supplying to or from as strings is now deprecated, switch to an options configuration object');
1242+ opt = {
1243+ from: arguments[0],
1244+ to: arguments[1]
1245+ };
1246+ }
1247+
1248+ if (opt.n || opt['max-count']) {
1249+ command.push("--max-count=" + (opt.n || opt['max-count']));
1250+ }
1251+
1252+ if (opt.from && opt.to) {
1253+ command.push(opt.from + rangeOperator + opt.to);
1254+ }
1255+
1256+ if (opt.file) {
1257+ suffix.push("--follow", options.file);
1258+ }
1259+
1260+ 'splitter n max-count file from to --pretty format symmetric multiLine'.split(' ').forEach(function (key) {
1261+ delete opt[key];
1262+ });
1263+
1264+ Git._appendOptions(command, opt);
1265+
1266+ return this._run(
1267+ command.concat(suffix),
1268+ Git._responseHandler(handler, 'ListLogSummary', [splitter, fields])
1269+ );
1270+ };
1271+
1272+ /**
1273+ * Clears the queue of pending commands and returns the wrapper instance for chaining.
1274+ *
1275+ * @returns {Git}
1276+ */
1277+ Git.prototype.clearQueue = function () {
1278+ this._runCache.length = 0;
1279+ return this;
1280+ };
1281+
1282+ /**
1283+ * Check if a pathname or pathnames are excluded by .gitignore
1284+ *
1285+ * @param {string|string[]} pathnames
1286+ * @param {Function} [then]
1287+ */
1288+ Git.prototype.checkIgnore = function (pathnames, then) {
1289+ var handler = Git.trailingFunctionArgument(arguments);
1290+ var command = ["check-ignore"];
1291+
1292+ if (handler !== pathnames) {
1293+ command = command.concat(pathnames);
1294+ }
1295+
1296+ return this._run(command, function (err, data) {
1297+ handler && handler(err, !err && this._parseCheckIgnore(data));
1298+ });
1299+ };
1300+
1301+ /**
1302+ * Validates that the current repo is a Git repo.
1303+ *
1304+ * @param {Function} [then]
1305+ */
1306+ Git.prototype.checkIsRepo = function (then) {
1307+ function onError (exitCode, stdErr, done, fail) {
1308+ if (exitCode === 128 && /(Not a git repository|Kein Git-Repository)/i.test(stdErr)) {
1309+ return done(false);
1310+ }
1311+
1312+ fail(stdErr);
1313+ }
1314+
1315+ function handler (err, isRepo) {
1316+ then && then(err, String(isRepo).trim() === 'true');
1317+ }
1318+
1319+ return this._run(['rev-parse', '--is-inside-work-tree'], handler, {onError: onError});
1320+ };
1321+
1322+ Git.prototype._rm = function (_files, options, then) {
1323+ var files = [].concat(_files);
1324+ var args = ['rm', options];
1325+ args.push.apply(args, files);
1326+
1327+ return this._run(args, function (err) {
1328+ then && then(err);
1329+ });
1330+ };
1331+
1332+ Git.prototype._parseCheckout = function (checkout) {
1333+ // TODO
1334+ };
1335+
1336+ /**
1337+ * Parser for the `check-ignore` command - returns each
1338+ * @param {string} [files]
1339+ * @returns {string[]}
1340+ */
1341+ Git.prototype._parseCheckIgnore = function (files) {
1342+ return files.split(/\n/g).filter(Boolean).map(function (file) {
1343+ return file.trim()
1344+ });
1345+ };
1346+
1347+ /**
1348+ * Schedules the supplied command to be run, the command should not include the name of the git binary and should
1349+ * be an array of strings passed as the arguments to the git binary.
1350+ *
1351+ * @param {string[]} command
1352+ * @param {Function} then
1353+ * @param {Object} [opt]
1354+ * @param {boolean} [opt.concatStdErr=false] Optionally concatenate stderr output into the stdout
1355+ * @param {boolean} [opt.format="utf-8"] The format to use when reading the content of stdout
1356+ * @param {Function} [opt.onError] Optional error handler for this command - can be used to allow non-clean exits
1357+ * without killing the remaining stack of commands
1358+ * @param {number} [opt.onError.exitCode]
1359+ * @param {string} [opt.onError.stdErr]
1360+ *
1361+ * @returns {Git}
1362+ */
1363+ Git.prototype._run = function (command, then, opt) {
1364+ if (typeof command === "string") {
1365+ command = command.split(" ");
1366+ }
1367+ this._runCache.push([command, then, opt || {}]);
1368+ this._schedule();
1369+
1370+ return this;
1371+ };
1372+
1373+ Git.prototype._schedule = function () {
1374+ if (!this._childProcess && this._runCache.length) {
1375+ var git = this;
1376+ var Buffer = git.Buffer;
1377+ var task = git._runCache.shift();
1378+
1379+ var command = task[0];
1380+ var then = task[1];
1381+ var options = task[2];
1382+
1383+ debug(command);
1384+
1385+ var result = deferred();
1386+
1387+ var attempted = false;
1388+ var attemptClose = function attemptClose (e) {
1389+
1390+ // closing when there is content, terminate immediately
1391+ if (attempted || stdErr.length || stdOut.length) {
1392+ result.resolve(e);
1393+ attempted = true;
1394+ }
1395+
1396+ // first attempt at closing but no content yet, wait briefly for the close/exit that may follow
1397+ if (!attempted) {
1398+ attempted = true;
1399+ setTimeout(attemptClose.bind(this, e), 50);
1400+ }
1401+
1402+ };
1403+
1404+ var stdOut = [];
1405+ var stdErr = [];
1406+ var spawned = git.ChildProcess.spawn(git._command, command.slice(0), {
1407+ cwd: git._baseDir,
1408+ env: git._env,
1409+ windowsHide: true
1410+ });
1411+
1412+ spawned.stdout.on('data', function (buffer) {
1413+ stdOut.push(buffer);
1414+ });
1415+
1416+ spawned.stderr.on('data', function (buffer) {
1417+ stdErr.push(buffer);
1418+ });
1419+
1420+ spawned.on('error', function (err) {
1421+ stdErr.push(Buffer.from(err.stack, 'ascii'));
1422+ });
1423+
1424+ spawned.on('close', attemptClose);
1425+ spawned.on('exit', attemptClose);
1426+
1427+ result.promise.then(function (exitCode) {
1428+ function done (output) {
1429+ then.call(git, null, output);
1430+ }
1431+
1432+ function fail (error) {
1433+ Git.fail(git, error, then);
1434+ }
1435+
1436+ delete git._childProcess;
1437+
1438+ if (exitCode && stdErr.length && options.onError) {
1439+ options.onError(exitCode, Buffer.concat(stdErr).toString('utf-8'), done, fail);
1440+ }
1441+ else if (exitCode && stdErr.length) {
1442+ fail(Buffer.concat(stdErr).toString('utf-8'));
1443+ }
1444+ else {
1445+ if (options.concatStdErr) {
1446+ [].push.apply(stdOut, stdErr);
1447+ }
1448+
1449+ var stdOutput = Buffer.concat(stdOut);
1450+ if (options.format !== 'buffer') {
1451+ stdOutput = stdOutput.toString(options.format || 'utf-8');
1452+ }
1453+
1454+ done(stdOutput);
1455+ }
1456+
1457+ process.nextTick(git._schedule.bind(git));
1458+ });
1459+
1460+ git._childProcess = spawned;
1461+
1462+ if (git._outputHandler) {
1463+ git._outputHandler(command[0], git._childProcess.stdout, git._childProcess.stderr);
1464+ }
1465+ }
1466+ };
1467+
1468+ /**
1469+ * Handles an exception in the processing of a command.
1470+ */
1471+ Git.fail = function (git, error, handler) {
1472+ git._getLog('error', error);
1473+ git._runCache.length = 0;
1474+ if (typeof handler === 'function') {
1475+ handler.call(git, error, null);
1476+ }
1477+ };
1478+
1479+ /**
1480+ * Given any number of arguments, returns the last argument if it is a function, otherwise returns null.
1481+ * @returns {Function|null}
1482+ */
1483+ Git.trailingFunctionArgument = function (args) {
1484+ var trailing = args[args.length - 1];
1485+ return (typeof trailing === "function") ? trailing : null;
1486+ };
1487+
1488+ /**
1489+ * Given any number of arguments, returns the trailing options argument, ignoring a trailing function argument
1490+ * if there is one. When not found, the return value is null.
1491+ * @returns {Object|null}
1492+ */
1493+ Git.trailingOptionsArgument = function (args) {
1494+ var options = args[(args.length - (Git.trailingFunctionArgument(args) ? 2 : 1))];
1495+ return Object.prototype.toString.call(options) === '[object Object]' ? options : null;
1496+ };
1497+
1498+ /**
1499+ * Given any number of arguments, returns the trailing options array argument, ignoring a trailing function argument
1500+ * if there is one. When not found, the return value is an empty array.
1501+ * @returns {Array}
1502+ */
1503+ Git.trailingArrayArgument = function (args) {
1504+ var options = args[(args.length - (Git.trailingFunctionArgument(args) ? 2 : 1))];
1505+ return Object.prototype.toString.call(options) === '[object Array]' ? options : [];
1506+ };
1507+
1508+ /**
1509+ * Mutates the supplied command array by merging in properties in the options object. When the
1510+ * value of the item in the options object is a string it will be concatenated to the key as
1511+ * a single `name=value` item, otherwise just the name will be used.
1512+ *
1513+ * @param {string[]} command
1514+ * @param {Object} options
1515+ * @private
1516+ */
1517+ Git._appendOptions = function (command, options) {
1518+ if (options === null) {
1519+ return;
1520+ }
1521+
1522+ Object.keys(options).forEach(function (key) {
1523+ var value = options[key];
1524+ if (typeof value === 'string') {
1525+ command.push(key + '=' + value);
1526+ }
1527+ else {
1528+ command.push(key);
1529+ }
1530+ });
1531+ };
1532+
1533+ /**
1534+ * Given the type of response and the callback to receive the parsed response,
1535+ * uses the correct parser and calls back the callback.
1536+ *
1537+ * @param {Function} callback
1538+ * @param {string} [type]
1539+ * @param {Object[]} [args]
1540+ *
1541+ * @private
1542+ */
1543+ Git._responseHandler = function (callback, type, args) {
1544+ return function (error, data) {
1545+ if (typeof callback !== 'function') {
1546+ return;
1547+ }
1548+
1549+ if (error) {
1550+ return callback(error, null);
1551+ }
1552+
1553+ if (!type) {
1554+ return callback(null, data);
1555+ }
1556+
1557+ var handler = requireResponseHandler(type);
1558+ var result = handler.parse.apply(handler, [data].concat(args === undefined ? [] : args));
1559+
1560+ callback(null, result);
1561+ };
1562+
1563+ };
1564+
1565+ /**
1566+ * Marks the git instance as having had a fatal exception by clearing the pending queue of tasks and
1567+ * logging to the console.
1568+ *
1569+ * @param git
1570+ * @param error
1571+ * @param callback
1572+ */
1573+ Git.exception = function (git, error, callback) {
1574+ git._runCache.length = 0;
1575+ if (typeof callback === 'function') {
1576+ callback(error instanceof Error ? error : new Error(error));
1577+ }
1578+
1579+ git._getLog('error', error);
1580+ };
1581+
1582+ module.exports = Git;
1583+
1584+ /**
1585+ * Requires and returns a response handler based on its named type
1586+ * @param {string} type
1587+ */
1588+ function requireResponseHandler (type) {
1589+ return responses[type];
1590+ }
1591+
1592+}());
node_modules/simple-git/src/index.js+14−0
@@ -0,0 +1,14 @@
1+
2+var Git = require('./git');
3+
4+module.exports = function (baseDir) {
5+
6+ var dependencies = require('./util/dependencies');
7+
8+ if (baseDir && !dependencies.exists(baseDir, dependencies.exists.FOLDER)) {
9+ throw new Error("Cannot use simple-git on a directory that does not exist.");
10+ }
11+
12+ return new Git(baseDir || process.cwd(), dependencies.childProcess(), dependencies.buffer());
13+};
14+
node_modules/simple-git/src/responses/BranchDeleteSummary.js+26−0
@@ -0,0 +1,26 @@
1+
2+module.exports = BranchDeletion;
3+
4+function BranchDeletion (branch, hash) {
5+ this.branch = branch;
6+ this.hash = hash;
7+ this.success = hash !== null;
8+}
9+
10+BranchDeletion.deleteSuccessRegex = /(\S+)\s+\(\S+\s([^\)]+)\)/;
11+BranchDeletion.deleteErrorRegex = /^error[^']+'([^']+)'/;
12+
13+BranchDeletion.parse = function (data, asArray) {
14+ var result;
15+ var branchDeletions = data.trim().split('\n').map(function (line) {
16+ if (result = BranchDeletion.deleteSuccessRegex.exec(line)) {
17+ return new BranchDeletion(result[1], result[2]);
18+ }
19+ else if (result = BranchDeletion.deleteErrorRegex.exec(line)) {
20+ return new BranchDeletion(result[1], null);
21+ }
22+ })
23+ .filter(Boolean);
24+
25+ return asArray ? branchDeletions : branchDeletions.pop();
26+};
node_modules/simple-git/src/responses/BranchSummary.js+52−0
@@ -0,0 +1,52 @@
1+
2+module.exports = BranchSummary;
3+
4+function BranchSummary () {
5+ this.detached = false;
6+ this.current = '';
7+ this.all = [];
8+ this.branches = {};
9+}
10+
11+BranchSummary.prototype.push = function (current, detached, name, commit, label) {
12+ if (current) {
13+ this.detached = detached;
14+ this.current = name;
15+ }
16+ this.all.push(name);
17+ this.branches[name] = {
18+ current: current,
19+ name: name,
20+ commit: commit,
21+ label: label
22+ };
23+};
24+
25+BranchSummary.detachedRegex = /^(\*?\s+)\((?:HEAD )?detached (?:from|at) (\S+)\)\s+([a-z0-9]+)\s(.*)$/;
26+BranchSummary.branchRegex = /^(\*?\s+)(\S+)\s+([a-z0-9]+)\s(.*)$/;
27+
28+BranchSummary.parse = function (commit) {
29+ var branchSummary = new BranchSummary();
30+
31+ commit.split('\n')
32+ .forEach(function (line) {
33+ var detached = true;
34+ var branch = BranchSummary.detachedRegex.exec(line);
35+ if (!branch) {
36+ detached = false;
37+ branch = BranchSummary.branchRegex.exec(line);
38+ }
39+
40+ if (branch) {
41+ branchSummary.push(
42+ branch[1].charAt(0) === '*',
43+ detached,
44+ branch[2],
45+ branch[3],
46+ branch[4]
47+ );
48+ }
49+ });
50+
51+ return branchSummary;
52+};
node_modules/simple-git/src/responses/CommitSummary.js+60−0
@@ -0,0 +1,60 @@
1+
2+module.exports = CommitSummary;
3+
4+function CommitSummary () {
5+ this.branch = '';
6+ this.commit = '';
7+ this.summary = {
8+ changes: 0,
9+ insertions: 0,
10+ deletions: 0
11+ };
12+ this.author = null;
13+}
14+
15+var COMMIT_BRANCH_MESSAGE_REGEX = /\[([^\s]+) ([^\]]+)/;
16+var COMMIT_AUTHOR_MESSAGE_REGEX = /\s*Author:\s(.+)/i;
17+
18+function setBranchFromCommit (commitSummary, commitData) {
19+ if (commitData) {
20+ commitSummary.branch = commitData[1];
21+ commitSummary.commit = commitData[2];
22+ }
23+}
24+
25+function setSummaryFromCommit (commitSummary, commitData) {
26+ if (commitSummary.branch && commitData) {
27+ commitSummary.summary.changes = commitData[1] || 0;
28+ commitSummary.summary.insertions = commitData[2] || 0;
29+ commitSummary.summary.deletions = commitData[3] || 0;
30+ }
31+}
32+
33+function setAuthorFromCommit (commitSummary, commitData) {
34+ var parts = commitData[1].split('<');
35+ var email = parts.pop();
36+
37+ if (email.indexOf('@') <= 0) {
38+ return;
39+ }
40+
41+ commitSummary.author = {
42+ email: email.substr(0, email.length - 1),
43+ name: parts.join('<').trim()
44+ };
45+}
46+
47+CommitSummary.parse = function (commit) {
48+ var lines = commit.trim().split('\n');
49+ var commitSummary = new CommitSummary();
50+
51+ setBranchFromCommit(commitSummary, COMMIT_BRANCH_MESSAGE_REGEX.exec(lines.shift()));
52+
53+ if (COMMIT_AUTHOR_MESSAGE_REGEX.test(lines[0])) {
54+ setAuthorFromCommit(commitSummary, COMMIT_AUTHOR_MESSAGE_REGEX.exec(lines.shift()));
55+ }
56+
57+ setSummaryFromCommit(commitSummary, /(\d+)[^,]*(?:,\s*(\d+)[^,]*)?(?:,\s*(\d+))?/g.exec(lines.shift()));
58+
59+ return commitSummary;
60+};
node_modules/simple-git/src/responses/DiffSummary.js+92−0
@@ -0,0 +1,92 @@
1+
2+module.exports = DiffSummary;
3+
4+/**
5+ * The DiffSummary is returned as a response to getting `git().status()`
6+ *
7+ * @constructor
8+ */
9+function DiffSummary () {
10+ this.files = [];
11+ this.insertions = 0;
12+ this.deletions = 0;
13+ this.changed = 0;
14+}
15+
16+/**
17+ * Number of lines added
18+ * @type {number}
19+ */
20+DiffSummary.prototype.insertions = 0;
21+
22+/**
23+ * Number of lines deleted
24+ * @type {number}
25+ */
26+DiffSummary.prototype.deletions = 0;
27+
28+/**
29+ * Number of files changed
30+ * @type {number}
31+ */
32+DiffSummary.prototype.changed = 0;
33+
34+DiffSummary.parse = function (text) {
35+ var line, handler;
36+
37+ var lines = text.trim().split('\n');
38+ var status = new DiffSummary();
39+
40+ var summary = lines.pop();
41+ if (summary) {
42+ summary.trim().split(', ').forEach(function (text) {
43+ var summary = /(\d+)\s([a-z]+)/.exec(text);
44+ if (!summary) {
45+ return;
46+ }
47+
48+ if (/files?/.test(summary[2])) {
49+ status.changed = parseInt(summary[1], 10);
50+ }
51+ else {
52+ status[summary[2].replace(/s$/, '') + 's'] = parseInt(summary[1], 10);
53+ }
54+ });
55+ }
56+
57+ while (line = lines.shift()) {
58+ textFileChange(line, status.files) || binaryFileChange(line, status.files);
59+ }
60+
61+ return status;
62+};
63+
64+function textFileChange (line, files) {
65+ line = line.trim().match(/^(.+)\s+\|\s+(\d+)(\s+[+\-]+)?$/);
66+
67+ if (line) {
68+ var alterations = (line[3] || '').trim();
69+ files.push({
70+ file: line[1].trim(),
71+ changes: parseInt(line[2], 10),
72+ insertions: alterations.replace(/-/g, '').length,
73+ deletions: alterations.replace(/\+/g, '').length,
74+ binary: false
75+ });
76+
77+ return true;
78+ }
79+}
80+
81+function binaryFileChange (line, files) {
82+ line = line.match(/^(.+) \|\s+Bin ([0-9.]+) -> ([0-9.]+) ([a-z]+)$/);
83+ if (line) {
84+ files.push({
85+ file: line[1].trim(),
86+ before: +line[2],
87+ after: +line[3],
88+ binary: true
89+ });
90+ return true;
91+ }
92+}
node_modules/simple-git/src/responses/FetchSummary.js+55−0
@@ -0,0 +1,55 @@
1+'use strict';
2+
3+function FetchSummary (raw) {
4+ this.raw = raw;
5+
6+ this.remote = null;
7+ this.branches = [];
8+ this.tags = [];
9+}
10+
11+FetchSummary.parsers = [
12+ [
13+ /From (.+)$/, function (fetchSummary, matches) {
14+ fetchSummary.remote = matches[0];
15+ }
16+ ],
17+ [
18+ /\* \[new branch\]\s+(\S+)\s*\-> (.+)$/, function (fetchSummary, matches) {
19+ fetchSummary.branches.push({
20+ name: matches[0],
21+ tracking: matches[1]
22+ });
23+ }
24+ ],
25+ [
26+ /\* \[new tag\]\s+(\S+)\s*\-> (.+)$/, function (fetchSummary, matches) {
27+ fetchSummary.tags.push({
28+ name: matches[0],
29+ tracking: matches[1]
30+ });
31+ }
32+ ]
33+];
34+
35+FetchSummary.parse = function (data) {
36+ var fetchSummary = new FetchSummary(data);
37+
38+ String(data)
39+ .trim()
40+ .split('\n')
41+ .forEach(function (line) {
42+ var original = line.trim();
43+ FetchSummary.parsers.some(function (parser) {
44+ var parsed = parser[0].exec(original);
45+ if (parsed) {
46+ parser[1](fetchSummary, parsed.slice(1));
47+ return true;
48+ }
49+ });
50+ });
51+
52+ return fetchSummary;
53+};
54+
55+module.exports = FetchSummary;
node_modules/simple-git/src/responses/FileStatusSummary.js+22−0
@@ -0,0 +1,22 @@
1+'use strict';
2+
3+function FileStatusSummary (path, index, working_dir) {
4+ this.path = path;
5+ this.index = index;
6+ this.working_dir = working_dir;
7+
8+ if ('R' === index + working_dir) {
9+ var detail = FileStatusSummary.fromPathRegex.exec(path) || [null, path, path];
10+ this.from = detail[1];
11+ this.path = detail[2];
12+ }
13+}
14+
15+FileStatusSummary.fromPathRegex = /^(.+) -> (.+)$/;
16+
17+FileStatusSummary.prototype = {
18+ path: '',
19+ from: ''
20+};
21+
22+module.exports = FileStatusSummary;
node_modules/simple-git/src/responses/ListLogSummary.js+72−0
@@ -0,0 +1,72 @@
1+
2+module.exports = ListLogSummary;
3+
4+var DiffSummary = require('./DiffSummary');
5+
6+/**
7+ * The ListLogSummary is returned as a response to getting `git().log()` or `git().stashList()`
8+ *
9+ * @constructor
10+ */
11+function ListLogSummary (all) {
12+ this.all = all;
13+ this.latest = all.length && all[0] || null;
14+ this.total = all.length;
15+}
16+
17+/**
18+ * Detail for each of the log lines
19+ * @type {ListLogLine[]}
20+ */
21+ListLogSummary.prototype.all = null;
22+
23+/**
24+ * Most recent entry in the log
25+ * @type {ListLogLine}
26+ */
27+ListLogSummary.prototype.latest = null;
28+
29+/**
30+ * Number of items in the log
31+ * @type {number}
32+ */
33+ListLogSummary.prototype.total = 0;
34+
35+function ListLogLine (line, fields) {
36+ for (var k = 0; k < fields.length; k++) {
37+ this[fields[k]] = line[k] || '';
38+ }
39+}
40+
41+/**
42+ * When the log was generated with a summary, the `diff` property contains as much detail
43+ * as was provided in the log (whether generated with `--stat` or `--shortstat`.
44+ * @type {DiffSummary}
45+ */
46+ListLogLine.prototype.diff = null;
47+
48+ListLogSummary.START_BOUNDARY = 'òòòòòò ';
49+
50+ListLogSummary.COMMIT_BOUNDARY = ' òò';
51+
52+ListLogSummary.SPLITTER = ' ò ';
53+
54+ListLogSummary.parse = function (text, splitter, fields) {
55+ fields = fields || ['hash', 'date', 'message', 'refs', 'author_name', 'author_email'];
56+ return new ListLogSummary(
57+ text
58+ .trim()
59+ .split(ListLogSummary.START_BOUNDARY)
60+ .filter(function(item) { return !!item.trim(); })
61+ .map(function (item) {
62+ var lineDetail = item.trim().split(ListLogSummary.COMMIT_BOUNDARY);
63+ var listLogLine = new ListLogLine(lineDetail[0].trim().split(splitter), fields);
64+
65+ if (lineDetail.length > 1 && !!lineDetail[1].trim()) {
66+ listLogLine.diff = DiffSummary.parse(lineDetail[1]);
67+ }
68+
69+ return listLogLine;
70+ })
71+ );
72+};
node_modules/simple-git/src/responses/MergeSummary.js+103−0
@@ -0,0 +1,103 @@
1+module.exports = MergeSummary;
2+module.exports.MergeConflict = MergeConflict;
3+
4+var PullSummary = require('./PullSummary');
5+
6+function MergeConflict (reason, file, meta) {
7+ this.reason = reason;
8+ this.file = file;
9+ if (meta) {
10+ this.meta = meta;
11+ }
12+}
13+
14+MergeConflict.prototype.meta = null;
15+
16+MergeConflict.prototype.toString = function () {
17+ return this.file + ':' + this.reason;
18+};
19+
20+function MergeSummary () {
21+ PullSummary.call(this);
22+
23+ this.conflicts = [];
24+ this.merges = [];
25+}
26+
27+MergeSummary.prototype = Object.create(PullSummary.prototype);
28+
29+MergeSummary.prototype.result = 'success';
30+
31+MergeSummary.prototype.toString = function () {
32+ if (this.conflicts.length) {
33+ return 'CONFLICTS: ' + this.conflicts.join(', ');
34+ }
35+ return 'OK';
36+};
37+
38+Object.defineProperty(MergeSummary.prototype, 'failed', {
39+ get: function () {
40+ return this.conflicts.length > 0;
41+ }
42+});
43+
44+MergeSummary.parsers = [
45+ {
46+ test: /^Auto-merging\s+(.+)$/,
47+ handle: function (result, mergeSummary) {
48+ mergeSummary.merges.push(result[1]);
49+ }
50+ },
51+ {
52+ // Parser for standard merge conflicts
53+ test: /^CONFLICT\s+\((.+)\): Merge conflict in (.+)$/,
54+ handle: function (result, mergeSummary) {
55+ mergeSummary.conflicts.push(new MergeConflict(result[1], result[2]));
56+ }
57+ },
58+ {
59+ // Parser for modify/delete merge conflicts (modified by us/them, deleted by them/us)
60+ test: /^CONFLICT\s+\((.+\/delete)\): (.+) deleted in (.+) and/,
61+ handle: function (result, mergeSummary) {
62+ mergeSummary.conflicts.push(
63+ new MergeConflict(result[1], result[2], {deleteRef: result[3]})
64+ );
65+ }
66+ },
67+ {
68+ // Catch-all parser for unknown/unparsed conflicts
69+ test: /^CONFLICT\s+\((.+)\):/,
70+ handle: function (result, mergeSummary) {
71+ mergeSummary.conflicts.push(new MergeConflict(result[1], null));
72+ }
73+ },
74+ {
75+ test: /^Automatic merge failed;\s+(.+)$/,
76+ handle: function (result, mergeSummary) {
77+ mergeSummary.reason = mergeSummary.result = result[1];
78+ }
79+ }
80+];
81+
82+MergeSummary.parse = function (output) {
83+ let mergeSummary = new MergeSummary();
84+
85+ output.trim().split('\n').forEach(function (line) {
86+ for (var i = 0, iMax = MergeSummary.parsers.length; i < iMax; i++) {
87+ let parser = MergeSummary.parsers[i];
88+
89+ var result = parser.test.exec(line);
90+ if (result) {
91+ parser.handle(result, mergeSummary);
92+ break;
93+ }
94+ }
95+ });
96+
97+ let pullSummary = PullSummary.parse(output);
98+ if (pullSummary.summary.changes) {
99+ Object.assign(mergeSummary, pullSummary);
100+ }
101+
102+ return mergeSummary;
103+};
node_modules/simple-git/src/responses/MoveSummary.js+32−0
@@ -0,0 +1,32 @@
1+
2+module.exports = MoveSummary;
3+
4+/**
5+ * The MoveSummary is returned as a response to getting `git().status()`
6+ *
7+ * @constructor
8+ */
9+function MoveSummary () {
10+ this.moves = [];
11+ this.sources = {};
12+}
13+
14+MoveSummary.SUMMARY_REGEX = /^Renaming (.+) to (.+)$/;
15+
16+MoveSummary.parse = function (text) {
17+ var lines = text.split('\n');
18+ var summary = new MoveSummary();
19+
20+ for (var i = 0, iMax = lines.length, line; i < iMax; i++) {
21+ line = MoveSummary.SUMMARY_REGEX.exec(lines[i].trim());
22+
23+ if (line) {
24+ summary.moves.push({
25+ from: line[1],
26+ to: line[2]
27+ });
28+ }
29+ }
30+
31+ return summary;
32+};
node_modules/simple-git/src/responses/PullSummary.js+137−0
@@ -0,0 +1,137 @@
1+
2+module.exports = PullSummary;
3+
4+/**
5+ * The PullSummary is returned as a response to getting `git().pull()`
6+ *
7+ * @constructor
8+ */
9+function PullSummary () {
10+ this.files = [];
11+ this.insertions = {};
12+ this.deletions = {};
13+
14+ this.summary = {
15+ changes: 0,
16+ insertions: 0,
17+ deletions: 0
18+ };
19+
20+ this.created = [];
21+ this.deleted = [];
22+}
23+
24+/**
25+ * Array of files that were created
26+ * @type {string[]}
27+ */
28+PullSummary.prototype.created = null;
29+
30+/**
31+ * Array of files that were deleted
32+ * @type {string[]}
33+ */
34+PullSummary.prototype.deleted = null;
35+
36+/**
37+ * The array of file paths/names that have been modified in any part of the pulled content
38+ * @type {string[]}
39+ */
40+PullSummary.prototype.files = null;
41+
42+/**
43+ * A map of file path to number to show the number of insertions per file.
44+ * @type {Object}
45+ */
46+PullSummary.prototype.insertions = null;
47+
48+/**
49+ * A map of file path to number to show the number of deletions per file.
50+ * @type {Object}
51+ */
52+PullSummary.prototype.deletions = null;
53+
54+/**
55+ * Overall summary of changes/insertions/deletions and the number associated with each
56+ * across all content that was pulled.
57+ * @type {Object}
58+ */
59+PullSummary.prototype.summary = null;
60+
61+PullSummary.FILE_UPDATE_REGEX = /^\s*(.+?)\s+\|\s+\d+\s*(\+*)(-*)/;
62+PullSummary.SUMMARY_REGEX = /(\d+)\D+((\d+)\D+\(\+\))?(\D+(\d+)\D+\(-\))?/;
63+PullSummary.ACTION_REGEX = /(create|delete) mode \d+ (.+)/;
64+
65+PullSummary.parse = function (text) {
66+ var pullSummary = new PullSummary;
67+ var lines = text.split('\n');
68+
69+ while (lines.length) {
70+ var line = lines.shift().trim();
71+ if (!line) {
72+ continue;
73+ }
74+
75+ update(pullSummary, line) || summary(pullSummary, line) || action(pullSummary, line);
76+ }
77+
78+ return pullSummary;
79+};
80+
81+function update (pullSummary, line) {
82+
83+ var update = PullSummary.FILE_UPDATE_REGEX.exec(line);
84+ if (!update) {
85+ return false;
86+ }
87+
88+ pullSummary.files.push(update[1]);
89+
90+ var insertions = update[2].length;
91+ if (insertions) {
92+ pullSummary.insertions[update[1]] = insertions;
93+ }
94+
95+ var deletions = update[3].length;
96+ if (deletions) {
97+ pullSummary.deletions[update[1]] = deletions;
98+ }
99+
100+ return true;
101+}
102+
103+function summary (pullSummary, line) {
104+ if (!pullSummary.files.length) {
105+ return false;
106+ }
107+
108+ var update = PullSummary.SUMMARY_REGEX.exec(line);
109+ if (!update || (update[3] === undefined && update[5] === undefined)) {
110+ return false;
111+ }
112+
113+ pullSummary.summary.changes = +update[1] || 0;
114+ pullSummary.summary.insertions = +update[3] || 0;
115+ pullSummary.summary.deletions = +update[5] || 0;
116+
117+ return true;
118+}
119+
120+function action (pullSummary, line) {
121+
122+ var match = PullSummary.ACTION_REGEX.exec(line);
123+ if (!match) {
124+ return false;
125+ }
126+
127+ var file = match[2];
128+
129+ if (pullSummary.files.indexOf(file) < 0) {
130+ pullSummary.files.push(file);
131+ }
132+
133+ var container = (match[1] === 'create') ? pullSummary.created : pullSummary.deleted;
134+ container.push(file);
135+
136+ return true;
137+}
node_modules/simple-git/src/responses/StatusSummary.js+188−0
@@ -0,0 +1,188 @@
1+
2+
3+
4+var FileStatusSummary = require('./FileStatusSummary');
5+
6+module.exports = StatusSummary;
7+
8+/**
9+ * The StatusSummary is returned as a response to getting `git().status()`
10+ *
11+ * @constructor
12+ */
13+function StatusSummary () {
14+ this.not_added = [];
15+ this.conflicted = [];
16+ this.created = [];
17+ this.deleted = [];
18+ this.modified = [];
19+ this.renamed = [];
20+ this.files = [];
21+ this.staged = [];
22+}
23+
24+
25+/**
26+ * Number of commits ahead of the tracked branch
27+ * @type {number}
28+ */
29+StatusSummary.prototype.ahead = 0;
30+
31+/**
32+ * Number of commits behind the tracked branch
33+ * @type {number}
34+ */
35+StatusSummary.prototype.behind = 0;
36+
37+/**
38+ * Name of the current branch
39+ * @type {null}
40+ */
41+StatusSummary.prototype.current = null;
42+
43+/**
44+ * Name of the branch being tracked
45+ * @type {string}
46+ */
47+StatusSummary.prototype.tracking = null;
48+
49+/**
50+ * All files represented as an array of objects containing the `path` and status in `index` and
51+ * in the `working_dir`.
52+ *
53+ * @type {Array}
54+ */
55+StatusSummary.prototype.files = null;
56+
57+/**
58+ * Gets whether this StatusSummary represents a clean working branch.
59+ *
60+ * @return {boolean}
61+ */
62+StatusSummary.prototype.isClean = function () {
63+ return 0 === Object.keys(this).filter(function (name) {
64+ return Array.isArray(this[name]) && this[name].length;
65+ }, this).length;
66+};
67+
68+StatusSummary.parsers = {
69+ '##': function (line, status) {
70+ var aheadReg = /ahead (\d+)/;
71+ var behindReg = /behind (\d+)/;
72+ var currentReg = /^(.+?(?=(?:\.{3}|\s|$)))/;
73+ var trackingReg = /\.{3}(\S*)/;
74+ var regexResult;
75+
76+ regexResult = aheadReg.exec(line);
77+ status.ahead = regexResult && +regexResult[1] || 0;
78+
79+ regexResult = behindReg.exec(line);
80+ status.behind = regexResult && +regexResult[1] || 0;
81+
82+ regexResult = currentReg.exec(line);
83+ status.current = regexResult && regexResult[1];
84+
85+ regexResult = trackingReg.exec(line);
86+ status.tracking = regexResult && regexResult[1];
87+ },
88+
89+ '??': function (line, status) {
90+ status.not_added.push(line);
91+ },
92+
93+ A: function (line, status) {
94+ status.created.push(line);
95+ },
96+
97+ AM: function (line, status) {
98+ status.created.push(line);
99+ },
100+
101+ D: function (line, status) {
102+ status.deleted.push(line);
103+ },
104+
105+ M: function (line, status, indexState) {
106+ status.modified.push(line);
107+
108+ if (indexState === 'M') {
109+ status.staged.push(line);
110+ }
111+ },
112+
113+ R: function (line, status) {
114+ var detail = /^(.+) -> (.+)$/.exec(line) || [null, line, line];
115+
116+ status.renamed.push({
117+ from: detail[1],
118+ to: detail[2]
119+ });
120+ },
121+
122+ UU: function (line, status) {
123+ status.conflicted.push(line);
124+ }
125+};
126+
127+StatusSummary.parsers.MM = StatusSummary.parsers.M;
128+
129+/* Map all unmerged status code combinations to UU to mark as conflicted */
130+StatusSummary.parsers.AA = StatusSummary.parsers.UU;
131+StatusSummary.parsers.UD = StatusSummary.parsers.UU;
132+StatusSummary.parsers.DU = StatusSummary.parsers.UU;
133+StatusSummary.parsers.DD = StatusSummary.parsers.UU;
134+StatusSummary.parsers.AU = StatusSummary.parsers.UU;
135+StatusSummary.parsers.UA = StatusSummary.parsers.UU;
136+
137+StatusSummary.parse = function (text) {
138+ var file;
139+ var lines = text.trim().split('\n');
140+ var status = new StatusSummary();
141+
142+ for (var i = 0, l = lines.length; i < l; i++) {
143+ file = splitLine(lines[i]);
144+
145+ if (!file) {
146+ continue;
147+ }
148+
149+ if (file.handler) {
150+ file.handler(file.path, status, file.index, file.workingDir);
151+ }
152+
153+ if (file.code !== '##') {
154+ status.files.push(new FileStatusSummary(file.path, file.index, file.workingDir));
155+ }
156+ }
157+
158+ return status;
159+};
160+
161+
162+function splitLine (lineStr) {
163+ var line = lineStr.trim().match(/(..?)(\s+)(.*)/);
164+ if (!line || !line[1].trim()) {
165+ line = lineStr.trim().match(/(..?)\s+(.*)/);
166+ }
167+
168+ if (!line) {
169+ return;
170+ }
171+
172+ var code = line[1];
173+ if (line[2].length > 1) {
174+ code += ' ';
175+ }
176+ if (code.length === 1 && line[2].length === 1) {
177+ code = ' ' + code;
178+ }
179+
180+ return {
181+ raw: code,
182+ code: code.trim(),
183+ index: code.charAt(0),
184+ workingDir: code.charAt(1),
185+ handler: StatusSummary.parsers[code.trim()],
186+ path: line[3]
187+ };
188+}
node_modules/simple-git/src/responses/TagList.js+50−0
@@ -0,0 +1,50 @@
1+
2+module.exports = TagList;
3+
4+function TagList (tagList, latest) {
5+ this.latest = latest;
6+ this.all = tagList
7+}
8+
9+TagList.parse = function (data, customSort) {
10+ var number = function (input) {
11+ if (typeof input === 'string') {
12+ return parseInt(input.replace(/^\D+/g, ''), 10) || 0;
13+ }
14+
15+ return 0;
16+ };
17+
18+ var tags = data
19+ .trim()
20+ .split('\n')
21+ .map(function (item) { return item.trim(); })
22+ .filter(Boolean);
23+
24+ if (!customSort) {
25+ tags.sort(function (tagA, tagB) {
26+ var partsA = tagA.split('.');
27+ var partsB = tagB.split('.');
28+
29+ if (partsA.length === 1 || partsB.length === 1) {
30+ return tagA - tagB > 0 ? 1 : -1;
31+ }
32+
33+ for (var i = 0, l = Math.max(partsA.length, partsB.length); i < l; i++) {
34+ var a = number(partsA[i]);
35+ var b = number(partsB[i]);
36+
37+ var diff = a - b;
38+ if (diff) {
39+ return diff > 0 ? 1 : -1;
40+ }
41+ }
42+
43+ return 0;
44+ });
45+ }
46+
47+ var latest = customSort ? tags[0] : tags.filter(function (tag) { return tag.indexOf('.') >= 0; }).pop();
48+
49+ return new TagList(tags, latest);
50+};
node_modules/simple-git/src/responses/index.js+15−0
@@ -0,0 +1,15 @@
1+
2+module.exports = {
3+ BranchDeleteSummary: require('./BranchDeleteSummary'),
4+ BranchSummary: require('./BranchSummary'),
5+ CommitSummary: require('./CommitSummary'),
6+ DiffSummary: require('./DiffSummary'),
7+ FetchSummary: require('./FetchSummary'),
8+ FileStatusSummary: require('./FileStatusSummary'),
9+ ListLogSummary: require('./ListLogSummary'),
10+ MergeSummary: require('./MergeSummary'),
11+ MoveSummary: require('./MoveSummary'),
12+ PullSummary: require('./PullSummary'),
13+ StatusSummary: require('./StatusSummary'),
14+ TagList: require('./TagList'),
15+};
node_modules/simple-git/src/util/deferred.js+10−0
@@ -0,0 +1,10 @@
1+
2+module.exports = function deferred () {
3+ var d = {};
4+ d.promise = new Promise(function (resolve, reject) {
5+ d.resolve = resolve;
6+ d.reject = reject
7+ });
8+
9+ return d;
10+};
node_modules/simple-git/src/util/dependencies.js+12−0
@@ -0,0 +1,12 @@
1+/**
2+ * Exports the utilities `simple-git` depends upon to allow for mocking during a test
3+ */
4+module.exports = {
5+
6+ buffer: function () { return require('buffer').Buffer; },
7+
8+ childProcess: function () { return require('child_process'); },
9+
10+ exists: require('./exists')
11+
12+};
node_modules/simple-git/src/util/exists.js+33−0
@@ -0,0 +1,33 @@
1+
2+var fs = require('fs');
3+
4+function exists (path, isFile, isDirectory) {
5+ try {
6+ var matches = false;
7+ var stat = fs.statSync(path);
8+
9+ matches = matches || isFile && stat.isFile();
10+ matches = matches || isDirectory && stat.isDirectory();
11+
12+ return matches;
13+ }
14+ catch (e) {
15+ if (e.code === 'ENOENT') {
16+ return false;
17+ }
18+
19+ throw e;
20+ }
21+}
22+
23+module.exports = function (path, type) {
24+ if (!type) {
25+ return exists(path, true, true);
26+ }
27+
28+ return exists(path, type & 1, type & 2);
29+};
30+
31+module.exports.FILE = 1;
32+
33+module.exports.FOLDER = 2;