index.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. 'use strict'
  2. const dargs = require('dargs')
  3. const execFile = require('child_process').execFile
  4. const split = require('split2')
  5. const stream = require('stream')
  6. const template = require('lodash/template')
  7. const through = require('through2')
  8. const DELIMITER = '------------------------ >8 ------------------------'
  9. function normalizeExecOpts (execOpts) {
  10. execOpts = execOpts || {}
  11. execOpts.cwd = execOpts.cwd || process.cwd()
  12. return execOpts
  13. }
  14. function normalizeGitOpts (gitOpts) {
  15. gitOpts = gitOpts || {}
  16. gitOpts.format = gitOpts.format || '%B'
  17. gitOpts.from = gitOpts.from || ''
  18. gitOpts.to = gitOpts.to || 'HEAD'
  19. return gitOpts
  20. }
  21. function getGitArgs (gitOpts) {
  22. const gitFormat = template('--format=<%= format %>%n' + DELIMITER)(gitOpts)
  23. const gitFromTo = [gitOpts.from, gitOpts.to].filter(Boolean).join('..')
  24. const gitArgs = ['log', gitFormat, gitFromTo]
  25. .concat(dargs(gitOpts, {
  26. excludes: ['debug', 'from', 'to', 'format', 'path']
  27. }))
  28. // allow commits to focus on a single directory
  29. // this is useful for monorepos.
  30. if (gitOpts.path) {
  31. gitArgs.push('--', gitOpts.path)
  32. }
  33. return gitArgs
  34. }
  35. function gitRawCommits (rawGitOpts, rawExecOpts) {
  36. const readable = new stream.Readable()
  37. readable._read = function () {}
  38. const gitOpts = normalizeGitOpts(rawGitOpts)
  39. const execOpts = normalizeExecOpts(rawExecOpts)
  40. const args = getGitArgs(gitOpts)
  41. if (gitOpts.debug) {
  42. gitOpts.debug('Your git-log command is:\ngit ' + args.join(' '))
  43. }
  44. let isError = false
  45. const child = execFile('git', args, {
  46. cwd: execOpts.cwd,
  47. maxBuffer: Infinity
  48. })
  49. child.stdout
  50. .pipe(split(DELIMITER + '\n'))
  51. .pipe(through(function (chunk, enc, cb) {
  52. readable.push(chunk)
  53. isError = false
  54. cb()
  55. }, function (cb) {
  56. setImmediate(function () {
  57. if (!isError) {
  58. readable.push(null)
  59. readable.emit('close')
  60. }
  61. cb()
  62. })
  63. }))
  64. child.stderr
  65. .pipe(through.obj(function (chunk) {
  66. isError = true
  67. readable.emit('error', new Error(chunk))
  68. readable.emit('close')
  69. }))
  70. return readable
  71. }
  72. module.exports = gitRawCommits