1 | 'use strict'
|
2 |
|
3 | const addStream = require('add-stream')
|
4 | const gitRawCommits = require('git-raw-commits')
|
5 | const conventionalCommitsParser = require('conventional-commits-parser')
|
6 | const conventionalChangelogWriter = require('conventional-changelog-writer')
|
7 | const _ = require('lodash')
|
8 | const stream = require('stream')
|
9 | const through = require('through2')
|
10 | const shell = require('shelljs')
|
11 |
|
12 | const mergeConfig = require('./lib/merge-config')
|
13 | function conventionalChangelog (options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts) {
|
14 | writerOpts = writerOpts || {}
|
15 |
|
16 | const readable = new stream.Readable({
|
17 | objectMode: writerOpts.includeDetails
|
18 | })
|
19 | readable._read = function () { }
|
20 |
|
21 | let commitsErrorThrown = false
|
22 |
|
23 | let commitsStream = new stream.Readable({
|
24 | objectMode: true
|
25 | })
|
26 | commitsStream._read = function () { }
|
27 |
|
28 | function commitsRange (from, to) {
|
29 | return gitRawCommits(_.merge({}, gitRawCommitsOpts, {
|
30 | from: from,
|
31 | to: to
|
32 | }))
|
33 | .on('error', function (err) {
|
34 | if (!commitsErrorThrown) {
|
35 | setImmediate(commitsStream.emit.bind(commitsStream), 'error', err)
|
36 | commitsErrorThrown = true
|
37 | }
|
38 | })
|
39 | }
|
40 |
|
41 | mergeConfig(options, context, gitRawCommitsOpts, parserOpts, writerOpts, gitRawExecOpts)
|
42 | .then(function (data) {
|
43 | options = data.options
|
44 | context = data.context
|
45 | gitRawCommitsOpts = data.gitRawCommitsOpts
|
46 | parserOpts = data.parserOpts
|
47 | writerOpts = data.writerOpts
|
48 | gitRawExecOpts = data.gitRawExecOpts
|
49 |
|
50 | if (shell.exec('git rev-parse --verify HEAD', { silent: true }).code === 0) {
|
51 | let reverseTags = context.gitSemverTags.slice(0).reverse()
|
52 | reverseTags.push('HEAD')
|
53 |
|
54 | if (gitRawCommitsOpts.from) {
|
55 | if (reverseTags.indexOf(gitRawCommitsOpts.from) !== -1) {
|
56 | reverseTags = reverseTags.slice(reverseTags.indexOf(gitRawCommitsOpts.from))
|
57 | } else {
|
58 | reverseTags = [gitRawCommitsOpts.from, 'HEAD']
|
59 | }
|
60 | }
|
61 |
|
62 | let streams = reverseTags.map((to, i) => {
|
63 | const from = i > 0
|
64 | ? reverseTags[i - 1]
|
65 | : ''
|
66 | return commitsRange(from, to)
|
67 | })
|
68 |
|
69 | if (gitRawCommitsOpts.from) {
|
70 | streams = streams.splice(1)
|
71 | }
|
72 |
|
73 | if (gitRawCommitsOpts.reverse) {
|
74 | streams.reverse()
|
75 | }
|
76 |
|
77 | streams.reduce((prev, next) => next.pipe(addStream(prev)))
|
78 | .on('data', function (data) {
|
79 | setImmediate(commitsStream.emit.bind(commitsStream), 'data', data)
|
80 | })
|
81 | .on('end', function () {
|
82 | setImmediate(commitsStream.emit.bind(commitsStream), 'end')
|
83 | })
|
84 | } else {
|
85 | commitsStream = gitRawCommits(gitRawCommitsOpts, gitRawExecOpts)
|
86 | }
|
87 |
|
88 | commitsStream
|
89 | .on('error', function (err) {
|
90 | err.message = 'Error in git-raw-commits: ' + err.message
|
91 | setImmediate(readable.emit.bind(readable), 'error', err)
|
92 | })
|
93 | .pipe(conventionalCommitsParser(parserOpts))
|
94 | .on('error', function (err) {
|
95 | err.message = 'Error in conventional-commits-parser: ' + err.message
|
96 | setImmediate(readable.emit.bind(readable), 'error', err)
|
97 | })
|
98 |
|
99 |
|
100 | .pipe(through.obj(function (chunk, enc, cb) {
|
101 | try {
|
102 | options.transform.call(this, chunk, cb)
|
103 | } catch (err) {
|
104 | cb(err)
|
105 | }
|
106 | }))
|
107 | .on('error', function (err) {
|
108 | err.message = 'Error in options.transform: ' + err.message
|
109 | setImmediate(readable.emit.bind(readable), 'error', err)
|
110 | })
|
111 | .pipe(conventionalChangelogWriter(context, writerOpts))
|
112 | .on('error', function (err) {
|
113 | err.message = 'Error in conventional-changelog-writer: ' + err.message
|
114 | setImmediate(readable.emit.bind(readable), 'error', err)
|
115 | })
|
116 | .pipe(through({
|
117 | objectMode: writerOpts.includeDetails
|
118 | }, function (chunk, enc, cb) {
|
119 | try {
|
120 | readable.push(chunk)
|
121 | } catch (err) {
|
122 | setImmediate(function () {
|
123 | throw err
|
124 | })
|
125 | }
|
126 |
|
127 | cb()
|
128 | }, function (cb) {
|
129 | readable.push(null)
|
130 |
|
131 | cb()
|
132 | }))
|
133 | })
|
134 | .catch(function (err) {
|
135 | setImmediate(readable.emit.bind(readable), 'error', err)
|
136 | })
|
137 |
|
138 | return readable
|
139 | }
|
140 |
|
141 | module.exports = conventionalChangelog
|