@@ -4,6 +4,8 @@ use xshell::Shell;
44pub ( crate ) fn check_changelog ( shell : Shell , mut args : Arguments ) -> anyhow:: Result < ( ) > {
55 const CHANGELOG_PATH_RELATIVE : & str = "./CHANGELOG.md" ;
66
7+ let emit_github_messages = args. contains ( "--emit-github-messages" ) ;
8+
79 let from_branch = args
810 . free_from_str ( )
911 . ok ( )
@@ -60,7 +62,16 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
6062 }
6163
6264 for hunk in & hunks_in_a_released_section {
63- eprintln ! ( "{hunk}" ) ;
65+ eprintln ! ( "{}" , hunk. contents) ;
66+
67+ if emit_github_messages {
68+ let title = "" ;
69+ let message = "" ;
70+ println ! (
71+ "::error file={},line={},endLine={},title={title}::{message}" ,
72+ CHANGELOG_PATH_RELATIVE , hunk. change_start_line_num, hunk. change_end_line_num,
73+ )
74+ }
6475 }
6576 }
6677
@@ -76,6 +87,12 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
7687 }
7788}
7889
90+ struct Hunk < ' a > {
91+ change_start_line_num : u64 ,
92+ change_end_line_num : u64 ,
93+ contents : & ' a str ,
94+ }
95+
7996/// Given some `changelog_contents` (in Markdown) containing the full end state of the provided
8097/// `diff` (in [unified diff format]), return all hunks that are (1) below a `## Unreleased` section
8198/// _and_ (2) above all other second-level (i.e., `## …`) headings.
@@ -90,7 +107,7 @@ pub(crate) fn check_changelog(shell: Shell, mut args: Arguments) -> anyhow::Resu
90107/// `changelog_contents`. using hunk information to compare against `changelog_contents`.
91108///
92109/// Failing to uphold these assumptons is not unsafe, but will yield incorrect results.
93- fn hunks_in_a_released_section < ' a > ( changelog_contents : & str , diff : & ' a str ) -> Vec < & ' a str > {
110+ fn hunks_in_a_released_section < ' a > ( changelog_contents : & str , diff : & ' a str ) -> Vec < Hunk < ' a > > {
94111 let mut changelog_lines = changelog_contents. lines ( ) ;
95112
96113 let changelog_unreleased_line_num =
@@ -109,7 +126,7 @@ fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> V
109126 SplitPrefixInclusive :: new ( "\n @@" , & diff[ first_hunk_idx..] ) . map ( |s| & s[ '\n' . len_utf8 ( ) ..] )
110127 } ;
111128 let hunks_in_a_released_section = hunks
112- . filter ( |hunk| {
129+ . filter_map ( |hunk| {
113130 let ( hunk_header, hunk_contents) = hunk. split_once ( '\n' ) . unwrap ( ) ;
114131
115132 // Reference: This is of the format `@@ -86,6 +88,10 @@ …`.
@@ -128,15 +145,25 @@ fn hunks_in_a_released_section<'a>(changelog_contents: &str, diff: &'a str) -> V
128145 . parse :: < u64 > ( )
129146 . unwrap ( ) ;
130147
131- let lines_until_first_change = hunk_contents
148+ let mut change_lines = hunk_contents
132149 . lines ( )
133- . take_while ( |l| l. starts_with ( ' ' ) )
134- . count ( ) as u64 ;
135-
136- let first_hunk_change_start_offset =
137- post_change_hunk_start_offset + lines_until_first_change;
138-
139- first_hunk_change_start_offset >= changelog_first_release_section_line_num
150+ . enumerate ( )
151+ . filter ( |( _idx, l) | !l. starts_with ( ' ' ) )
152+ . map ( |( zero_based_idx, _l) | {
153+ post_change_hunk_start_offset + ( zero_based_idx as u64 ) + 1
154+ } ) ;
155+
156+ let change_start_line_num = change_lines. next ( ) . unwrap ( ) ;
157+
158+ if change_start_line_num >= changelog_first_release_section_line_num {
159+ Some ( Hunk {
160+ contents : hunk,
161+ change_start_line_num,
162+ change_end_line_num : change_lines. last ( ) . unwrap_or ( change_start_line_num) ,
163+ } )
164+ } else {
165+ None
166+ }
140167 } )
141168 . collect :: < Vec < _ > > ( ) ;
142169
0 commit comments