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