@@ -366,17 +366,36 @@ impl IssueRepository {
366
366
)
367
367
}
368
368
369
- async fn has_label ( & self , client : & GithubClient , label : & str ) -> bool {
369
+ async fn has_label ( & self , client : & GithubClient , label : & str ) -> anyhow :: Result < bool > {
370
370
#[ allow( clippy:: redundant_pattern_matching) ]
371
371
let url = format ! ( "{}/labels/{}" , self . url( ) , label) ;
372
- match client. send_req ( client. get ( & url) ) . await {
373
- Ok ( _) => true ,
374
- // XXX: Error handling if the request failed for reasons beyond 'label didn't exist'
375
- Err ( _) => false ,
372
+ match client. _send_req ( client. get ( & url) ) . await {
373
+ Ok ( ( _, _) ) => Ok ( true ) ,
374
+ Err ( e) => {
375
+ if e. downcast_ref :: < reqwest:: Error > ( ) . map_or ( false , |e| e. status ( ) == Some ( StatusCode :: NOT_FOUND ) ) {
376
+ Ok ( false )
377
+ } else {
378
+ Err ( e)
379
+ }
380
+ }
376
381
}
377
382
}
378
383
}
379
384
385
+ #[ derive( Debug ) ]
386
+ pub ( crate ) struct UnknownLabels {
387
+ labels : Vec < String > ,
388
+ }
389
+
390
+ // NOTE: This is used to post the Github comment; make sure it's valid markdown.
391
+ impl fmt:: Display for UnknownLabels {
392
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
393
+ write ! ( f, "Unknown labels: {}" , & self . labels. join( ", " ) )
394
+ }
395
+ }
396
+
397
+ impl std:: error:: Error for UnknownLabels { }
398
+
380
399
impl Issue {
381
400
pub fn to_zulip_github_reference ( & self ) -> ZulipGitHubReference {
382
401
ZulipGitHubReference {
@@ -519,18 +538,27 @@ impl Issue {
519
538
return Ok ( ( ) ) ;
520
539
}
521
540
522
- for label in & labels {
523
- if !self . repository ( ) . has_label ( client, & label) . await {
524
- anyhow:: bail!( "Label {} does not exist in {}" , label, self . global_id( ) ) ;
541
+ let mut unknown_labels = vec ! [ ] ;
542
+ let mut known_labels = vec ! [ ] ;
543
+ for label in labels {
544
+ if !self . repository ( ) . has_label ( client, & label) . await ? {
545
+ unknown_labels. push ( label) ;
546
+ } else {
547
+ known_labels. push ( label) ;
525
548
}
526
549
}
527
550
551
+ if !unknown_labels. is_empty ( ) {
552
+ return Err ( UnknownLabels { labels : unknown_labels } . into ( ) ) ;
553
+ }
554
+
528
555
#[ derive( serde:: Serialize ) ]
529
556
struct LabelsReq {
530
557
labels : Vec < String > ,
531
558
}
559
+
532
560
client
533
- . _send_req ( client. post ( & url) . json ( & LabelsReq { labels } ) )
561
+ . _send_req ( client. post ( & url) . json ( & LabelsReq { labels : known_labels } ) )
534
562
. await
535
563
. context ( "failed to add labels" ) ?;
536
564
@@ -1430,6 +1458,12 @@ pub trait IssuesQuery {
1430
1458
mod tests {
1431
1459
use super :: * ;
1432
1460
1461
+ #[ test]
1462
+ fn display_labels ( ) {
1463
+ let x = UnknownLabels { labels : vec ! [ "A-bootstrap" . into( ) , "xxx" . into( ) ] } ;
1464
+ assert_eq ! ( x. to_string( ) , "Unknown labels: A-bootstrap, xxx" ) ;
1465
+ }
1466
+
1433
1467
#[ test]
1434
1468
fn extract_one_file ( ) {
1435
1469
let input = r##"\
0 commit comments