1+ const { execSync} = require ( 'child_process' ) ;
2+ let [ start , end ] = process . argv . slice ( 2 ) ;
3+ if ( ! start || ! end ) {
4+ console . error ( 'Must provide start and end tags' ) ;
5+ console . error ( ' eg: v1.0 HEAD' ) ;
6+ console . error ( ' eg: v1.0 v2.0' ) ;
7+ process . exit ( 1 ) ;
8+ }
9+ const separator = `===END===` ;
10+ const res = execSync ( `git log -E --format=%H%n%s%b===END=== ${ start } ..${ end } ` ) ;
11+ const sep = res . toString ( ) . split ( separator ) ;
12+ const output = sep
13+ . map ( ( item , i ) => {
14+ const [ hash , ...body ] = getParts ( item , i ) ;
15+ const bodyJoined = body . join ( '\n' ) ;
16+ return [ hash , bodyJoined ] ;
17+ } )
18+ . filter ( ( [ , body ] ) => / ^ [ \w ] + : [ ^ ] / . test ( body ) )
19+ . map ( ( [ hash , bodyJoined ] ) => {
20+ const [ section , body ] = bodyJoined . split ( / : / ) ;
21+ return [ hash , section , body ] ;
22+ } )
23+ . reduce ( ( acc , item ) => {
24+ const [ , section ] = item ;
25+ if ( ! acc [ section ] ) {
26+ acc [ section ] = [ item ] ;
27+ } else {
28+ acc [ section ] . push ( item ) ;
29+ }
30+ return acc ;
31+ } , { } ) ;
32+
33+ if ( process . argv . indexOf ( '--json' ) > - 1 ) {
34+ console . log ( JSON . stringify ( output , null , 2 ) ) ;
35+ } else {
36+ Object . keys ( output )
37+ . map ( x => [ x , output [ x ] ] )
38+ . forEach ( ( [ section , items ] ) => {
39+ const header = `**${ section } **` ;
40+ console . log ( header ) ;
41+ items . forEach ( ( [ hash , section , body ] ) => {
42+ console . log ( `- ${ body } ${ hash } ` )
43+ } ) ;
44+ console . log ( '' )
45+ } ) ;
46+ }
47+
48+
49+
50+ function getParts ( item , index ) {
51+ const segs = item . split ( '\n' ) ;
52+ if ( index === 0 ) return segs ;
53+ return segs . slice ( 1 ) ;
54+ }
0 commit comments