@@ -179,6 +179,8 @@ pub(crate) struct Team {
179
179
lists : Vec < TeamList > ,
180
180
#[ serde( default ) ]
181
181
zulip_groups : Vec < RawZulipGroup > ,
182
+ #[ serde( default ) ]
183
+ zulip_streams : Vec < RawZulipStream > ,
182
184
discord_roles : Option < Vec < DiscordRole > > ,
183
185
}
184
186
@@ -364,6 +366,51 @@ impl Team {
364
366
Ok ( lists)
365
367
}
366
368
369
+ /// `on_exclude_not_included` is a function that is returned when an excluded member
370
+ /// wasn't included.
371
+ fn expand_zulip_membership (
372
+ & self ,
373
+ data : & Data ,
374
+ common : & RawZulipCommon ,
375
+ on_exclude_not_included : impl Fn ( & str ) -> Error ,
376
+ ) -> Result < Vec < ZulipMember > , Error > {
377
+ let mut members = if common. include_team_members {
378
+ self . members ( data) ?
379
+ } else {
380
+ HashSet :: new ( )
381
+ } ;
382
+ for person in & common. extra_people {
383
+ members. insert ( person. as_str ( ) ) ;
384
+ }
385
+ for team in & common. extra_teams {
386
+ let team = data
387
+ . team ( team)
388
+ . ok_or_else ( || format_err ! ( "team {} is missing" , team) ) ?;
389
+ members. extend ( team. members ( data) ?) ;
390
+ }
391
+ for excluded in & common. excluded_people {
392
+ if !members. remove ( excluded. as_str ( ) ) {
393
+ return Err ( on_exclude_not_included ( excluded) ) ;
394
+ }
395
+ }
396
+
397
+ let mut final_members = Vec :: new ( ) ;
398
+ for member in members. iter ( ) {
399
+ let member = data
400
+ . person ( member)
401
+ . ok_or_else ( || format_err ! ( "{} does not have a person configuration" , member) ) ?;
402
+ let member = match ( member. github . clone ( ) , member. zulip_id ) {
403
+ ( github, Some ( zulip_id) ) => ZulipMember :: MemberWithId { github, zulip_id } ,
404
+ ( github, _) => ZulipMember :: MemberWithoutId { github } ,
405
+ } ;
406
+ final_members. push ( member) ;
407
+ }
408
+ for & extra in & common. extra_zulip_ids {
409
+ final_members. push ( ZulipMember :: JustId ( extra) ) ;
410
+ }
411
+ Ok ( final_members)
412
+ }
413
+
367
414
pub ( crate ) fn raw_zulip_groups ( & self ) -> & [ RawZulipGroup ] {
368
415
& self . zulip_groups
369
416
}
@@ -373,48 +420,43 @@ impl Team {
373
420
let zulip_groups = & self . zulip_groups ;
374
421
375
422
for raw_group in zulip_groups {
376
- let mut group = ZulipGroup {
377
- name : raw_group. name . clone ( ) ,
378
- includes_team_members : raw_group. include_team_members ,
379
- members : Vec :: new ( ) ,
380
- } ;
423
+ groups. push ( ZulipGroup ( ZulipCommon {
424
+ name : raw_group. common . name . clone ( ) ,
425
+ includes_team_members : raw_group. common . include_team_members ,
426
+ members : self . expand_zulip_membership (
427
+ data,
428
+ & raw_group. common ,
429
+ |excluded| {
430
+ format_err ! ( "'{excluded}' was specifically excluded from the Zulip group '{}' but they were already not included" , raw_group. common. name)
431
+ } ,
432
+ ) ?,
433
+ } ) ) ;
434
+ }
435
+ Ok ( groups)
436
+ }
381
437
382
- let mut members = if raw_group. include_team_members {
383
- self . members ( data) ?
384
- } else {
385
- HashSet :: new ( )
386
- } ;
387
- for person in & raw_group. extra_people {
388
- members. insert ( person. as_str ( ) ) ;
389
- }
390
- for team in & raw_group. extra_teams {
391
- let team = data
392
- . team ( team)
393
- . ok_or_else ( || format_err ! ( "team {} is missing" , team) ) ?;
394
- members. extend ( team. members ( data) ?) ;
395
- }
396
- for excluded in & raw_group. excluded_people {
397
- if !members. remove ( excluded. as_str ( ) ) {
398
- bail ! ( "'{excluded}' was specifically excluded from the Zulip group '{}' but they were already not included" , raw_group. name) ;
399
- }
400
- }
438
+ pub ( crate ) fn raw_zulip_streams ( & self ) -> & [ RawZulipStream ] {
439
+ & self . zulip_streams
440
+ }
401
441
402
- for member in members. iter ( ) {
403
- let member = data. person ( member) . ok_or_else ( || {
404
- format_err ! ( "{} does not have a person configuration" , member)
405
- } ) ?;
406
- let member = match ( member. github . clone ( ) , member. zulip_id ) {
407
- ( github, Some ( zulip_id) ) => ZulipGroupMember :: MemberWithId { github, zulip_id } ,
408
- ( github, _) => ZulipGroupMember :: MemberWithoutId { github } ,
409
- } ;
410
- group. members . push ( member) ;
411
- }
412
- for & extra in & raw_group. extra_zulip_ids {
413
- group. members . push ( ZulipGroupMember :: JustId ( extra) ) ;
414
- }
415
- groups. push ( group) ;
442
+ pub ( crate ) fn zulip_streams ( & self , data : & Data ) -> Result < Vec < ZulipStream > , Error > {
443
+ let mut streams = Vec :: new ( ) ;
444
+ let zulip_streams = self . raw_zulip_streams ( ) ;
445
+
446
+ for raw_stream in zulip_streams {
447
+ streams. push ( ZulipStream ( ZulipCommon {
448
+ name : raw_stream. common . name . clone ( ) ,
449
+ includes_team_members : raw_stream. common . include_team_members ,
450
+ members : self . expand_zulip_membership (
451
+ data,
452
+ & raw_stream. common ,
453
+ |excluded| {
454
+ format_err ! ( "'{excluded}' was specifically excluded from the Zulip stream '{}' but they were already not included" , raw_stream. common. name)
455
+ } ,
456
+ ) ?,
457
+ } ) ) ;
416
458
}
417
- Ok ( groups )
459
+ Ok ( streams )
418
460
}
419
461
420
462
pub ( crate ) fn permissions ( & self ) -> & Permissions {
@@ -677,7 +719,7 @@ pub(crate) struct TeamList {
677
719
678
720
#[ derive( serde_derive:: Deserialize , Debug ) ]
679
721
#[ serde( rename_all = "kebab-case" , deny_unknown_fields) ]
680
- pub ( crate ) struct RawZulipGroup {
722
+ pub ( crate ) struct RawZulipCommon {
681
723
pub ( crate ) name : String ,
682
724
#[ serde( default = "default_true" ) ]
683
725
pub ( crate ) include_team_members : bool ,
@@ -691,6 +733,20 @@ pub(crate) struct RawZulipGroup {
691
733
pub ( crate ) excluded_people : Vec < String > ,
692
734
}
693
735
736
+ #[ derive( serde_derive:: Deserialize , Debug ) ]
737
+ #[ serde( rename_all = "kebab-case" , deny_unknown_fields) ]
738
+ pub ( crate ) struct RawZulipGroup {
739
+ #[ serde( flatten) ]
740
+ pub ( crate ) common : RawZulipCommon ,
741
+ }
742
+
743
+ #[ derive( serde_derive:: Deserialize , Debug ) ]
744
+ #[ serde( rename_all = "kebab-case" , deny_unknown_fields) ]
745
+ pub ( crate ) struct RawZulipStream {
746
+ #[ serde( flatten) ]
747
+ pub ( crate ) common : RawZulipCommon ,
748
+ }
749
+
694
750
#[ derive( Debug ) ]
695
751
pub ( crate ) struct List {
696
752
address : String ,
@@ -708,29 +764,49 @@ impl List {
708
764
}
709
765
710
766
#[ derive( Debug ) ]
711
- pub ( crate ) struct ZulipGroup {
767
+ pub ( crate ) struct ZulipCommon {
712
768
name : String ,
713
769
includes_team_members : bool ,
714
- members : Vec < ZulipGroupMember > ,
770
+ members : Vec < ZulipMember > ,
715
771
}
716
772
717
- impl ZulipGroup {
773
+ impl ZulipCommon {
718
774
pub ( crate ) fn name ( & self ) -> & str {
719
775
& self . name
720
776
}
721
777
722
- /// Whether the group includes the members of the team its associated
778
+ /// Whether the group/stream includes the members of the associated team?
723
779
pub ( crate ) fn includes_team_members ( & self ) -> bool {
724
780
self . includes_team_members
725
781
}
726
782
727
- pub ( crate ) fn members ( & self ) -> & [ ZulipGroupMember ] {
783
+ pub ( crate ) fn members ( & self ) -> & [ ZulipMember ] {
728
784
& self . members
729
785
}
730
786
}
731
787
788
+ #[ derive( Debug ) ]
789
+ pub ( crate ) struct ZulipGroup ( ZulipCommon ) ;
790
+
791
+ impl std:: ops:: Deref for ZulipGroup {
792
+ type Target = ZulipCommon ;
793
+ fn deref ( & self ) -> & Self :: Target {
794
+ & self . 0
795
+ }
796
+ }
797
+
798
+ #[ derive( Debug ) ]
799
+ pub ( crate ) struct ZulipStream ( ZulipCommon ) ;
800
+
801
+ impl std:: ops:: Deref for ZulipStream {
802
+ type Target = ZulipCommon ;
803
+ fn deref ( & self ) -> & Self :: Target {
804
+ & self . 0
805
+ }
806
+ }
807
+
732
808
#[ derive( Debug , Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
733
- pub ( crate ) enum ZulipGroupMember {
809
+ pub ( crate ) enum ZulipMember {
734
810
MemberWithId { github : String , zulip_id : u64 } ,
735
811
JustId ( u64 ) ,
736
812
MemberWithoutId { github : String } ,
0 commit comments