1
+ // Copyright 2024 © Sandro Figo
2
+
3
+ using System ;
4
+ using System . Collections . Generic ;
5
+ using System . Text ;
6
+ using System . Text . RegularExpressions ;
7
+ using Nuke . Common . IO ;
8
+ using Nuke . Common . Utilities ;
9
+ using Nuke . Common . Utilities . Collections ;
10
+
11
+ public class Changelog
12
+ {
13
+ public ChangelogTextSection Header ;
14
+ public List < ChangelogReleaseSection > Sections = new ( ) ;
15
+
16
+ public static Changelog FromFile ( AbsolutePath changelogFile )
17
+ {
18
+ string [ ] lines = changelogFile . ReadAllLines ( ) ;
19
+
20
+ return new Changelog
21
+ {
22
+ Header = GetHeader ( lines ) ,
23
+ Sections = GetSections ( lines )
24
+ } ;
25
+ }
26
+
27
+ static bool IsSectionStart ( string line )
28
+ {
29
+ return line . StartsWith ( "## " ) ;
30
+ }
31
+
32
+ static bool IsSubSectionStart ( string line )
33
+ {
34
+ return line . StartsWith ( "### " ) ;
35
+ }
36
+
37
+ static bool IsSubSectionEntry ( string line )
38
+ {
39
+ return line . StartsWith ( "-" ) ;
40
+ }
41
+
42
+ static bool IsVersionComparison ( string line )
43
+ {
44
+ return line . StartsWith ( "[" ) ;
45
+ }
46
+
47
+ static ChangelogTextSection GetHeader ( IEnumerable < string > lines )
48
+ {
49
+ var header = new ChangelogTextSection ( ) ;
50
+
51
+ foreach ( string l in lines )
52
+ {
53
+ if ( IsSectionStart ( l ) )
54
+ {
55
+ return header ;
56
+ }
57
+
58
+ header . Lines . Add ( l ) ;
59
+ }
60
+
61
+ return header ;
62
+ }
63
+
64
+
65
+ static List < ChangelogReleaseSection > GetSections ( IEnumerable < string > lines )
66
+ {
67
+ var sections = new List < ChangelogReleaseSection > ( ) ;
68
+
69
+ string currentSubSection = "" ;
70
+
71
+ foreach ( string l in lines )
72
+ {
73
+ if ( IsSectionStart ( l ) )
74
+ {
75
+ string currentSectionVersion = Regex . Match ( l , @"\[(?<version>.*)\]" ) . Groups [ "version" ] . Value . Trim ( ) ;
76
+ string currentSectionReleaseDate = Regex . Match ( l , @"(?<release_date>\d+-\d+-\d+)" ) . Groups [ "release_date" ] . Value . Trim ( ) ;
77
+
78
+ sections . Add ( new ChangelogReleaseSection
79
+ {
80
+ Version = currentSectionVersion ,
81
+ ReleaseDate = currentSectionReleaseDate
82
+ } ) ;
83
+
84
+ currentSubSection = "" ;
85
+ }
86
+ else if ( IsSubSectionStart ( l ) && sections . Count > 0 )
87
+ {
88
+ string subSectionName = l . Replace ( "###" , "" ) . Trim ( ) . ToLowerInvariant ( ) ;
89
+
90
+ currentSubSection = subSectionName ;
91
+ }
92
+ else if ( IsSubSectionEntry ( l ) && ! currentSubSection . IsNullOrWhiteSpace ( ) )
93
+ {
94
+ string entry = l . TrimStart ( "-" ) . Trim ( ) ;
95
+
96
+ if ( Enum . TryParse ( currentSubSection , true , out EntryType entryType ) )
97
+ {
98
+ sections [ ^ 1 ] . Entries [ entryType ] . Add ( entry ) ;
99
+ }
100
+ }
101
+ }
102
+
103
+ return sections ;
104
+ }
105
+
106
+ public override string ToString ( )
107
+ {
108
+ var stringBuilder = new StringBuilder ( ) ;
109
+
110
+ if ( Header != null )
111
+ stringBuilder . AppendLine ( Header . ToString ( ) ) ;
112
+
113
+ stringBuilder . AppendJoin ( System . Environment . NewLine , Sections ) ;
114
+
115
+ return stringBuilder . ToString ( ) ;
116
+ }
117
+ }
118
+
119
+ public class ChangelogReleaseSection
120
+ {
121
+ public string Version { get ; set ; }
122
+ public string ReleaseDate { get ; set ; }
123
+
124
+ public Dictionary < EntryType , List < string > > Entries { get ; set ; } = new ( )
125
+ {
126
+ { EntryType . Added , new List < string > ( ) } ,
127
+ { EntryType . Changed , new List < string > ( ) } ,
128
+ { EntryType . Deprecated , new List < string > ( ) } ,
129
+ { EntryType . Removed , new List < string > ( ) } ,
130
+ { EntryType . Fixed , new List < string > ( ) } ,
131
+ { EntryType . Security , new List < string > ( ) }
132
+ } ;
133
+
134
+ public override string ToString ( )
135
+ {
136
+ var lines = new List < string > ( ) ;
137
+
138
+ lines . Add ( $ "## [{ Version } ]{ ( ReleaseDate . IsNullOrWhiteSpace ( ) ? "" : $ " - { ReleaseDate } ") } ") ;
139
+ lines . Add ( "" ) ;
140
+
141
+ foreach ( var group in Entries )
142
+ {
143
+ if ( ! group . Value . IsEmpty ( ) )
144
+ {
145
+ lines . Add ( $ "### { group . Key } ") ;
146
+ lines . Add ( "" ) ;
147
+ foreach ( string s in group . Value )
148
+ lines . Add ( $ "- { s } ") ;
149
+ lines . Add ( "" ) ;
150
+ }
151
+ }
152
+
153
+ var stringBuilder = new StringBuilder ( ) ;
154
+
155
+ return stringBuilder . AppendJoin ( System . Environment . NewLine , lines ) . ToString ( ) ;
156
+ }
157
+ }
158
+
159
+ public class ChangelogTextSection
160
+ {
161
+ public List < string > Lines { get ; } = new ( ) ;
162
+
163
+ public override string ToString ( )
164
+ {
165
+ var stringBuilder = new StringBuilder ( ) ;
166
+
167
+ stringBuilder . AppendJoin ( System . Environment . NewLine , Lines ) ;
168
+
169
+ return stringBuilder . ToString ( ) ;
170
+ }
171
+ }
172
+
173
+ public enum EntryType
174
+ {
175
+ Added ,
176
+ Changed ,
177
+ Deprecated ,
178
+ Removed ,
179
+ Fixed ,
180
+ Security ,
181
+ }
0 commit comments