1
1
import semver from 'semver'
2
+ import { fetchCommits } from './commits'
2
3
import { niceDate } from './utils'
3
4
4
5
const MERGE_COMMIT_PATTERN = / ^ M e r g e ( r e m o t e - t r a c k i n g ) ? b r a n c h ' .+ ' /
5
6
const COMMIT_MESSAGE_PATTERN = / \n + ( [ \S \s ] + ) /
6
7
7
- function commitReducer ( { map, version } , commit ) {
8
- const currentVersion = commit . tag || version
9
- const commits = map [ currentVersion ] || [ ]
8
+ async function createRelease ( tag , previousTag , diff , remote , options ) {
9
+ const commits = await fetchCommits ( diff , remote , options )
10
+ const merges = commits . filter ( commit => commit . merge ) . map ( commit => commit . merge )
11
+ const fixes = commits . filter ( commit => commit . fixes ) . map ( commit => ( { fixes : commit . fixes , commit } ) )
12
+ const emptyRelease = merges . length === 0 && fixes . length === 0
13
+ const { date, message } = commits [ 0 ] || { date : new Date ( ) . toISOString ( ) }
14
+ const breakingCount = commits . filter ( c => c . breaking ) . length
15
+ const filteredCommits = commits
16
+ . filter ( commit => filterCommit ( commit , options , merges ) )
17
+ . sort ( commitSorter ( options ) )
18
+ . slice ( 0 , getCommitLimit ( options , emptyRelease , breakingCount ) )
10
19
return {
11
- map : {
12
- ...map ,
13
- [ currentVersion ] : [ ...commits , commit ]
14
- } ,
15
- version : currentVersion
20
+ tag,
21
+ title : tag || 'Unreleased' ,
22
+ date,
23
+ isoDate : date . slice ( 0 , 10 ) ,
24
+ niceDate : niceDate ( date ) ,
25
+ commits : filteredCommits ,
26
+ merges,
27
+ fixes,
28
+ summary : getSummary ( message , options ) ,
29
+ major : Boolean ( ! options . tagPattern && tag && previousTag && semver . diff ( tag , previousTag ) === 'major' ) ,
30
+ href : getCompareLink ( previousTag , tag , remote , options )
16
31
}
17
32
}
18
33
19
- export function parseReleases ( commits , remote , latestVersion , options ) {
20
- const { map } = commits . reduce ( commitReducer , { map : { } , version : latestVersion } )
21
- return Object . keys ( map ) . map ( ( key , index , versions ) => {
22
- const commits = map [ key ]
23
- const previousVersion = versions [ index + 1 ] || null
24
- const versionCommit = commits . find ( commit => commit . tag ) || { }
25
- const merges = commits . filter ( commit => commit . merge ) . map ( commit => commit . merge )
26
- const fixes = commits . filter ( commit => commit . fixes ) . map ( commit => ( { fixes : commit . fixes , commit } ) )
27
- const tag = versionCommit . tag || latestVersion
28
- const date = versionCommit . date || new Date ( ) . toISOString ( )
29
- const filteredCommits = commits
30
- . filter ( commit => filterCommit ( commit , options , merges ) )
31
- . sort ( commitSorter ( options ) )
32
- const emptyRelease = merges . length === 0 && fixes . length === 0
33
- const { tagPattern, tagPrefix } = options
34
- return {
35
- tag,
36
- title : tag || 'Unreleased' ,
37
- date,
38
- isoDate : date . slice ( 0 , 10 ) ,
39
- niceDate : niceDate ( date ) ,
40
- commits : sliceCommits ( filteredCommits , options , emptyRelease ) ,
41
- merges,
42
- fixes,
43
- summary : getSummary ( versionCommit . message , options ) ,
44
- major : Boolean ( ! tagPattern && tag && previousVersion && semver . diff ( tag , previousVersion ) === 'major' ) ,
45
- href : previousVersion ? remote . getCompareLink ( `${ tagPrefix } ${ previousVersion } ` , tag ? `${ tagPrefix } ${ tag } ` : 'HEAD' ) : null
46
- }
47
- } ) . filter ( release => {
48
- return options . unreleased ? true : release . tag
34
+ export function parseReleases ( tags , remote , latestVersion , options ) {
35
+ const releases = tags . map ( ( tag , index , tags ) => {
36
+ const previousTag = tags [ index + 1 ]
37
+ const diff = previousTag ? `${ previousTag } ..${ tag } ` : tag
38
+ return createRelease ( tag , previousTag , diff , remote , options )
49
39
} )
50
- }
51
-
52
- export function sortReleases ( a , b ) {
53
- const tags = {
54
- a : inferSemver ( a . tag ) ,
55
- b : inferSemver ( b . tag )
56
- }
57
- if ( tags . a && tags . b ) {
58
- if ( semver . valid ( tags . a ) && semver . valid ( tags . b ) ) {
59
- return semver . rcompare ( tags . a , tags . b )
60
- }
61
- if ( tags . a === tags . b ) {
62
- return 0
63
- }
64
- return tags . a < tags . b ? 1 : - 1
65
- }
66
- if ( tags . a ) return 1
67
- if ( tags . b ) return - 1
68
- return 0
69
- }
70
-
71
- function inferSemver ( tag ) {
72
- if ( / ^ v ? \d + $ / . test ( tag ) ) {
73
- // v1 becomes v1.0.0
74
- return `${ tag } .0.0`
40
+ if ( latestVersion || options . unreleased ) {
41
+ const tag = latestVersion || null
42
+ const previousTag = tags [ 0 ]
43
+ const diff = `${ previousTag } ..`
44
+ releases . unshift ( createRelease ( tag , previousTag , diff , remote , options ) )
75
45
}
76
- if ( / ^ v ? \d + \. \d + $ / . test ( tag ) ) {
77
- // v1.0 becomes v1.0.0
78
- return `${ tag } .0`
79
- }
80
- return tag
46
+ return Promise . all ( releases )
81
47
}
82
48
83
- function sliceCommits ( commits , { commitLimit, backfillLimit } , emptyRelease ) {
49
+ function getCommitLimit ( { commitLimit, backfillLimit } , emptyRelease , breakingCount ) {
84
50
if ( commitLimit === false ) {
85
- return commits
51
+ return undefined // Return all commits
86
52
}
87
53
const limit = emptyRelease ? backfillLimit : commitLimit
88
- const minLimit = commits . filter ( c => c . breaking ) . length
89
- return commits . slice ( 0 , Math . max ( minLimit , limit ) )
54
+ return Math . max ( breakingCount , limit )
90
55
}
91
56
92
57
function filterCommit ( commit , { ignoreCommitPattern } , merges ) {
@@ -97,9 +62,8 @@ function filterCommit (commit, { ignoreCommitPattern }, merges) {
97
62
if ( commit . breaking ) {
98
63
return true
99
64
}
100
- if ( ignoreCommitPattern ) {
101
- // Filter out commits that match ignoreCommitPattern
102
- return new RegExp ( ignoreCommitPattern ) . test ( commit . subject ) === false
65
+ if ( ignoreCommitPattern && new RegExp ( ignoreCommitPattern ) . test ( commit . subject ) ) {
66
+ return false
103
67
}
104
68
if ( semver . valid ( commit . subject ) ) {
105
69
// Filter out version commits
@@ -135,3 +99,12 @@ function commitSorter ({ sortCommits }) {
135
99
return ( b . insertions + b . deletions ) - ( a . insertions + a . deletions )
136
100
}
137
101
}
102
+
103
+ function getCompareLink ( previousTag , tag , remote , { tagPrefix = '' } ) {
104
+ if ( ! previousTag ) {
105
+ return null
106
+ }
107
+ const from = `${ tagPrefix } ${ previousTag } `
108
+ const to = tag ? `${ tagPrefix } ${ tag } ` : 'HEAD'
109
+ return remote . getCompareLink ( from , to )
110
+ }
0 commit comments