@@ -14,7 +14,7 @@ use crate::{
1414 gh:: {
1515 issue_id:: Repository ,
1616 issues:: {
17- count_issues_matching_search, list_issue_titles_in_milestone, CountIssues ,
17+ count_issues_matching_search, fetch_issue , list_issue_titles_in_milestone, CountIssues ,
1818 ExistingGithubComment , ExistingGithubIssue , ExistingIssueState ,
1919 } ,
2020 } ,
@@ -131,38 +131,66 @@ struct TrackingIssueUpdate {
131131///
132132/// Returns a tuple (completed, total) with the number of completed items and the total number of items.
133133fn checkboxes ( issue : & ExistingGithubIssue ) -> anyhow:: Result < Progress > {
134- let mut checkboxes = None ;
135- let mut issues = None ;
134+ let mut completed = 0 ;
135+ let mut total = 0 ;
136136
137137 for line in issue. body . lines ( ) {
138138 // Does this match TRACKED_ISSUES?
139139 if let Some ( c) = re:: TRACKED_ISSUES_QUERY . captures ( line) {
140- let repo = Repository :: from_str ( & c[ 1 ] ) ?;
141- let query = & c[ 2 ] ;
142-
143- if issues. is_some ( ) {
144- anyhow:: bail!( "found multiple search queries for Tracked Issues" ) ;
145- }
140+ let repo = Repository :: from_str ( & c[ "repo" ] ) ?;
141+ let query = & c[ "query" ] ;
146142
147143 let CountIssues { open, closed } = count_issues_matching_search ( & repo, query) ?;
148- issues = Some ( ( closed, open + closed) ) ;
144+ completed += closed;
145+ total += open + closed;
146+ continue ;
149147 }
150148
151- let ( checked, total) = checkboxes. unwrap_or ( ( 0 , 0 ) ) ;
149+ if let Some ( c) = re:: SEE_ALSO_QUERY . captures ( line) {
150+ let issue_urls = c[ "issues" ] . split ( & [ ',' , ' ' ] ) . filter ( |s| !s. is_empty ( ) ) ;
151+
152+ for issue_url in issue_urls {
153+ let Some ( c) = re:: SEE_ALSO_ISSUE . captures ( issue_url) else {
154+ anyhow:: bail!( "invalid issue URL `{issue_url}`" )
155+ } ;
156+ let repository = Repository :: new ( & c[ "org" ] , & c[ "repo" ] ) ;
157+ let issue_number = c[ "issue" ] . parse :: < u64 > ( ) ?;
158+ let issue = fetch_issue ( & repository, issue_number) ?;
159+ match checkboxes ( & issue) ? {
160+ Progress :: Binary => {
161+ if issue. state == ExistingIssueState :: Closed {
162+ completed += 1 ;
163+ }
164+ total += 1 ;
165+ }
166+
167+ Progress :: Tracked {
168+ completed : c,
169+ total : t,
170+ } => {
171+ completed += c;
172+ total += t;
173+ }
174+
175+ Progress :: Error { message } => {
176+ anyhow:: bail!( "error parsing {repository}#{issue_number}: {message}" )
177+ }
178+ }
179+ }
180+ }
152181
153182 if re:: CHECKED_CHECKBOX . is_match ( line) {
154- checkboxes = Some ( ( checked + 1 , total + 1 ) ) ;
183+ total += 1 ;
184+ completed += 1 ;
155185 } else if re:: CHECKBOX . is_match ( line) {
156- checkboxes = Some ( ( checked , total + 1 ) ) ;
186+ total += 1 ;
157187 }
158188 }
159189
160- match ( checkboxes, issues) {
161- ( Some ( ( completed, total) ) , None ) | ( None , Some ( ( completed, total) ) ) => {
162- Ok ( Progress :: Tracked { completed, total } )
163- }
164- ( None , None ) => Ok ( Progress :: Binary ) ,
165- ( Some ( _) , Some ( _) ) => anyhow:: bail!( "found both Tracked Issues and checkboxes" ) ,
190+ if total == 0 && completed == 0 {
191+ Ok ( Progress :: Binary )
192+ } else {
193+ Ok ( Progress :: Tracked { completed, total } )
166194 }
167195}
168196
0 commit comments