@@ -37,24 +37,31 @@ impl Generator {
3737
3838 self . fcps ( String :: from ( "T-libs-api" ) ) ?;
3939
40- IssueQuery :: new ( "Nominated" )
40+ GithubQuery :: new ( "Nominated" )
4141 . labels ( & [ "T-libs-api" , "I-nominated" ] )
4242 . repo ( "rust-lang/libs-team" )
4343 . repo ( "rust-lang/rust" )
4444 . repo ( "rust-lang/rfcs" )
4545 . write ( & mut self ) ?;
4646
47- IssueQuery :: new ( "Waiting on team" )
47+ GithubQuery :: new ( "Waiting on team" )
4848 . labels ( & [ "T-libs-api" , "S-waiting-on-team" ] )
4949 . repo ( "rust-lang/rust" )
5050 . repo ( "rust-lang/rfcs" )
5151 . write ( & mut self ) ?;
5252
53- IssueQuery :: new ( "Needs decision" )
53+ GithubQuery :: new ( "Needs decision" )
5454 . labels ( & [ "T-libs-api" , "I-needs-decision" ] )
5555 . repo ( "rust-lang/rust" )
5656 . write ( & mut self ) ?;
5757
58+ GithubQuery :: new ( "Stalled Tracking Issues" )
59+ . labels ( & [ "T-libs-api" , "C-tracking-issue" ] )
60+ . repo ( "rust-lang/rust" )
61+ . sort ( Sort :: LeastRecentlyUpdated )
62+ . take ( 5 )
63+ . write ( & mut self ) ?;
64+
5865 writeln ! ( & mut self . agenda,
5966 "## Actions
6067
@@ -91,28 +98,28 @@ impl Generator {
9198
9299 self . fcps ( String :: from ( "T-libs" ) ) ?;
93100
94- IssueQuery :: new ( "Critical" )
101+ GithubQuery :: new ( "Critical" )
95102 . labels ( & [ "T-libs" , "P-critical" ] )
96103 . labels ( & [ "T-libs-api" , "P-critical" ] )
97104 . repo ( "rust-lang/rust" )
98105 . repo ( "rust-lang/rfcs" )
99106 . write ( & mut self ) ?;
100107
101- IssueQuery :: new ( "Prioritization Requested" )
108+ GithubQuery :: new ( "Prioritization Requested" )
102109 . labels ( & [ "T-libs" , "I-prioritize" ] )
103110 . labels ( & [ "T-libs-api" , "I-prioritize" ] )
104111 . repo ( "rust-lang/rust" )
105112 . repo ( "rust-lang/rfcs" )
106113 . write ( & mut self ) ?;
107114
108- IssueQuery :: new ( "Nominated" )
115+ GithubQuery :: new ( "Nominated" )
109116 . labels ( & [ "T-libs" , "I-nominated" ] )
110117 . repo ( "rust-lang/rust" )
111118 . repo ( "rust-lang/rfcs" )
112119 . repo ( "rust-lang/libs-team" )
113120 . write ( & mut self ) ?;
114121
115- IssueQuery :: new ( "Backports" )
122+ GithubQuery :: new ( "Backports" )
116123 . labels ( & [ "T-libs" , "stable-nominated" ] )
117124 . labels ( & [ "T-libs-api" , "stable-nominated" ] )
118125 . labels ( & [ "T-libs" , "stable-accepted" ] )
@@ -121,11 +128,12 @@ impl Generator {
121128 . labels ( & [ "T-libs-api" , "beta-nominated" ] )
122129 . labels ( & [ "T-libs" , "beta-accepted" ] )
123130 . labels ( & [ "T-libs-api" , "beta-accepted" ] )
131+ . state ( State :: Any )
124132 . repo ( "rust-lang/rust" )
125133 . repo ( "rust-lang/rfcs" )
126134 . write ( & mut self ) ?;
127135
128- IssueQuery :: new ( "Regressions" )
136+ GithubQuery :: new ( "Regressions" )
129137 . labels ( & [ "T-libs" , "regression-untriaged" ] )
130138 . labels ( & [ "T-libs-api" , "regression-untriaged" ] )
131139 . labels ( & [ "T-libs" , "regression-from-stable-to-stable" ] )
@@ -150,24 +158,24 @@ impl Generator {
150158 }
151159
152160 pub fn error_handling_pg_agenda ( mut self ) -> Result < String > {
153- IssueQuery :: new ( "Nominated" )
161+ GithubQuery :: new ( "Nominated" )
154162 . labels ( & [ "PG-error-handling" , "I-nominated" ] )
155163 . repo ( "rust-lang/rust" )
156164 . repo ( "rust-lang/project-error-handling" )
157165 . write ( & mut self ) ?;
158166
159- IssueQuery :: new ( "PG Error Handling" )
167+ GithubQuery :: new ( "PG Error Handling" )
160168 . labels ( & [ "PG-error-handling" ] )
161169 . repo ( "rust-lang/rust" )
162170 . repo ( "rust-lang/project-error-handling" )
163171 . write ( & mut self ) ?;
164172
165- IssueQuery :: new ( "Area Error Handling" )
173+ GithubQuery :: new ( "Area Error Handling" )
166174 . labels ( & [ "A-error-handling" ] )
167175 . repo ( "rust-lang/rust" )
168176 . write ( & mut self ) ?;
169177
170- IssueQuery :: new ( "PG Error Handling" )
178+ GithubQuery :: new ( "PG Error Handling" )
171179 . repo ( "rust-lang/project-error-handling" )
172180 . write ( & mut self ) ?;
173181
@@ -348,18 +356,83 @@ impl Generator {
348356 }
349357}
350358
351- struct IssueQuery {
359+ #[ derive( Clone , Copy ) ]
360+ #[ allow( dead_code) ]
361+ enum Sort {
362+ Newest ,
363+ Oldest ,
364+ MostCommented ,
365+ LeastCommented ,
366+ MostRecentlyUpdated ,
367+ LeastRecentlyUpdated ,
368+ }
369+
370+ impl Sort {
371+ fn api_str ( & self ) -> & ' static str {
372+ match self {
373+ Sort :: Newest => "&sort=created&direction=desc" ,
374+ Sort :: Oldest => "&sort=created&direction=asc" ,
375+ Sort :: MostCommented => "&sort=comments&direction=asc" ,
376+ Sort :: LeastCommented => "&sort=comments&direction=desc" ,
377+ Sort :: MostRecentlyUpdated => "&sort=updated&direction=desc" ,
378+ Sort :: LeastRecentlyUpdated => "&sort=updated&direction=asc" ,
379+ }
380+ }
381+
382+ fn web_ui_str ( & self ) -> & ' static str {
383+ match self {
384+ Sort :: Newest => "+sort:created-desc" ,
385+ Sort :: Oldest => "+sort:created-asc" ,
386+ Sort :: MostCommented => "+sort:comments-desc" ,
387+ Sort :: LeastCommented => "+sort:comments-asc" ,
388+ Sort :: MostRecentlyUpdated => "+sort:updated-desc" ,
389+ Sort :: LeastRecentlyUpdated => "+sort:updated-asc" ,
390+ }
391+ }
392+ }
393+
394+ struct GithubQuery {
352395 name : & ' static str ,
353396 labels : Vec < & ' static [ & ' static str ] > ,
354397 repos : Vec < & ' static str > ,
398+ sort : Option < Sort > ,
399+ count : Option < usize > ,
400+ state : State ,
401+ }
402+
403+ enum State {
404+ Open ,
405+ Closed ,
406+ Any ,
355407}
356408
357- impl IssueQuery {
409+ impl State {
410+ fn api_str ( & self ) -> & ' static str {
411+ match self {
412+ State :: Open => "&state=open" ,
413+ State :: Closed => "&state=closed" ,
414+ State :: Any => "&state=all" ,
415+ }
416+ }
417+
418+ fn web_ui_str ( & self ) -> & ' static str {
419+ match self {
420+ State :: Open => "+is:open" ,
421+ State :: Closed => "+is:closed" ,
422+ State :: Any => "" ,
423+ }
424+ }
425+ }
426+
427+ impl GithubQuery {
358428 fn new ( name : & ' static str ) -> Self {
359429 Self {
360430 name,
361431 labels : vec ! [ ] ,
362432 repos : vec ! [ ] ,
433+ sort : None ,
434+ count : None ,
435+ state : State :: Open ,
363436 }
364437 }
365438
@@ -373,6 +446,21 @@ impl IssueQuery {
373446 self
374447 }
375448
449+ fn sort ( & mut self , sort : Sort ) -> & mut Self {
450+ self . sort = Some ( sort) ;
451+ self
452+ }
453+
454+ fn take ( & mut self , count : usize ) -> & mut Self {
455+ self . count = Some ( count) ;
456+ self
457+ }
458+
459+ fn state ( & mut self , state : State ) -> & mut Self {
460+ self . state = state;
461+ self
462+ }
463+
376464 fn write ( & mut self , generator : & mut Generator ) -> Result < ( ) > {
377465 writeln ! ( generator. agenda, "### {}" , self . name) ?;
378466 writeln ! ( generator. agenda, ) ?;
@@ -382,8 +470,21 @@ impl IssueQuery {
382470 for repo in & self . repos {
383471 for labels in & self . labels {
384472 let cs_labels = labels. join ( "," ) ;
385- let endpoint = format ! ( "repos/{}/issues?labels={}" , repo, cs_labels) ;
386- let issues = generator. dedup ( github_api ( & endpoint) ?) ;
473+ let mut endpoint = format ! ( "repos/{}/issues?labels={}" , repo, cs_labels) ;
474+
475+ endpoint += self . state . api_str ( ) ;
476+
477+ if let Some ( sort) = self . sort {
478+ endpoint += sort. api_str ( ) ;
479+ }
480+
481+ let mut issues = github_api ( & endpoint) ?;
482+
483+ if let Some ( count) = self . count {
484+ issues. truncate ( count) ;
485+ }
486+
487+ let issues = generator. dedup ( issues) ;
387488
388489 if issues. is_empty ( ) {
389490 continue ;
@@ -393,13 +494,23 @@ impl IssueQuery {
393494 . iter ( )
394495 . map ( |label| format ! ( "label:{}" , label) )
395496 . join ( "+" ) ;
497+
498+ let mut url = format ! ( "https://github.com/{}/issues?q={}" , repo, url_labels) ;
499+
500+ url += self . state . web_ui_str ( ) ;
501+
502+ if let Some ( sort) = self . sort {
503+ url += sort. web_ui_str ( ) ;
504+ }
505+
506+
396507 writeln ! (
397508 generator. agenda,
398- "- [{} `{repo}` `{labels}` items](https://github.com/{repo}/issues?q=is:open+{url_labels })" ,
509+ "- [{} `{repo}` `{labels}` items]({url })" ,
399510 issues. len( ) ,
400511 repo = repo,
401512 labels = labels. join( "` `" ) ,
402- url_labels = url_labels ,
513+ url = url ,
403514 ) ?;
404515 generator. write_issues ( & issues) ?;
405516
@@ -450,8 +561,9 @@ fn escape(v: &str) -> String {
450561}
451562
452563fn github_api < T : DeserializeOwned > ( endpoint : & str ) -> Result < T > {
564+ let url = format ! ( "https://api.github.com/{}" , endpoint) ;
453565 let mut client = reqwest:: blocking:: Client :: new ( )
454- . get ( & format ! ( "https://api.github.com/{}" , endpoint ) )
566+ . get ( & url )
455567 . header ( USER_AGENT , "rust-lang libs agenda maker" ) ;
456568 if let Ok ( token) = std:: env:: var ( "GITHUB_TOKEN" ) {
457569 client = client. header ( AUTHORIZATION , format ! ( "token {}" , token) ) ;
0 commit comments