commit.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. 'use strict';
  2. var through = require('through2');
  3. var log = require('fancy-log');
  4. var exec = require('child_process').exec;
  5. var escape = require('any-shell-escape');
  6. var path = require('path');
  7. // want to get the current git hash instead?
  8. // git.revParse({args:'--short HEAD'})
  9. module.exports = function(message, opt) {
  10. if (!opt) opt = {};
  11. if (!message) {
  12. if (opt.args.indexOf('--amend') === -1 && opt.disableMessageRequirement !== true) {
  13. throw new Error('gulp-git: Commit message is required git.commit("commit message") or --amend arg must be given');
  14. }
  15. }
  16. if (!opt.cwd) opt.cwd = process.cwd();
  17. if (!opt.maxBuffer) opt.maxBuffer = 200 * 1024; // Default buffer value for child_process.exec
  18. if (!opt.args) opt.args = ' ';
  19. var files = [];
  20. var paths = [];
  21. var write = function(file, enc, cb) {
  22. files.push(file);
  23. paths.push(path.relative(opt.cwd, file.path).replace('\\', '/') || '.');
  24. cb();
  25. };
  26. var messageEntry = function(entry) {
  27. return '-m "' + entry + '" ';
  28. };
  29. var flush = function(cb) {
  30. var writeStdin = false;
  31. var cmd = 'git commit ';
  32. // Allow delayed execution to determine the message
  33. if (typeof message === 'function') {
  34. message = message();
  35. }
  36. if (message && opt.args.indexOf('--amend') === -1) {
  37. // Check if the message is multiline
  38. if (message && message instanceof Array) {
  39. if (opt.multiline) {
  40. writeStdin = true;
  41. message = message.join('\n');
  42. } else {
  43. var messageExpanded = '';
  44. // repeat -m as needed
  45. for (var i = 0; i < message.length; i++) {
  46. messageExpanded += messageEntry(message[i]);
  47. }
  48. cmd += messageExpanded + opt.args;
  49. }
  50. if (!opt.disableAppendPaths) {
  51. cmd += ' ' + escape(paths);
  52. }
  53. } else {
  54. if (~message.indexOf('\n')) {
  55. writeStdin = true;
  56. } else {
  57. cmd += '-m "' + message + '" ' + opt.args;
  58. }
  59. if (!opt.disableAppendPaths) {
  60. cmd += ' ' + escape(paths);
  61. }
  62. }
  63. } else if (opt.disableMessageRequirement === true) {
  64. cmd += opt.args;
  65. } else {
  66. // When amending, just add the file automatically and do not include the message not the file.
  67. // Also, add all the files and avoid lauching the editor (even if --no-editor was added)
  68. cmd += '-a ' + opt.args + (opt.args.indexOf('--no-edit') === -1 ? ' --no-edit' : '');
  69. }
  70. var self = this;
  71. // If `message` was an array and `opt.multiline` was true
  72. // or was a string containing newlines, we append '-F -'
  73. if (writeStdin) {
  74. cmd += ' -F -';
  75. }
  76. if (!opt.disableAppendPaths) {
  77. cmd += ' .';
  78. }
  79. var execChildProcess = exec(cmd, opt, function(err, stdout, stderr) {
  80. if (err && (String(stdout).indexOf('no changes added to commit') === 0)) return cb(err);
  81. if (!opt.quiet) log(stdout, stderr);
  82. files.forEach(self.push.bind(self));
  83. self.emit('end');
  84. return cb();
  85. });
  86. if (writeStdin) {
  87. execChildProcess.stdin.write(message);
  88. execChildProcess.stdin.end();
  89. }
  90. // If the user wants, we'll emit data events during exec
  91. // they can listen to them with .on('data',function(data){ });
  92. // in their task
  93. if (opt.emitData) {
  94. execChildProcess.stdout.on('data', function(data) {
  95. self.emit('data', data);
  96. });
  97. execChildProcess.stderr.on('data', function(data) {
  98. self.emit('data', data);
  99. });
  100. }
  101. };
  102. return through.obj(write, flush);
  103. };