8
8
//! If the command was successful, there will be no feedback beyond the label change to reduce
9
9
//! notification noise.
10
10
11
+ use std:: collections:: BTreeSet ;
12
+
13
+ use crate :: github:: Label ;
11
14
use crate :: team_data:: TeamClient ;
12
15
use crate :: {
13
16
config:: RelabelConfig ,
@@ -24,8 +27,6 @@ pub(super) async fn handle_command(
24
27
event : & Event ,
25
28
input : RelabelCommand ,
26
29
) -> anyhow:: Result < ( ) > {
27
- let mut results = vec ! [ ] ;
28
- let mut to_add = vec ! [ ] ;
29
30
for delta in & input. 0 {
30
31
let name = delta. label ( ) . as_str ( ) ;
31
32
let err = match check_filter ( name, config, is_member ( & event. user ( ) , & ctx. team ) . await ) {
@@ -46,21 +47,10 @@ pub(super) async fn handle_command(
46
47
cmnt. post ( & ctx. github ) . await ?;
47
48
return Ok ( ( ) ) ;
48
49
}
49
- match delta {
50
- LabelDelta :: Add ( label) => {
51
- to_add. push ( github:: Label {
52
- name : label. to_string ( ) ,
53
- } ) ;
54
- }
55
- LabelDelta :: Remove ( label) => {
56
- results. push ( (
57
- label,
58
- event. issue ( ) . unwrap ( ) . remove_label ( & ctx. github , & label) ,
59
- ) ) ;
60
- }
61
- }
62
50
}
63
51
52
+ let ( to_add, to_remove) = compute_label_deltas ( & input. 0 ) ;
53
+
64
54
if let Err ( e) = event
65
55
. issue ( )
66
56
. unwrap ( )
@@ -84,8 +74,13 @@ pub(super) async fn handle_command(
84
74
return Err ( e) ;
85
75
}
86
76
87
- for ( label, res) in results {
88
- if let Err ( e) = res. await {
77
+ for label in to_remove {
78
+ if let Err ( e) = event
79
+ . issue ( )
80
+ . unwrap ( )
81
+ . remove_label ( & ctx. github , & label. name )
82
+ . await
83
+ {
89
84
tracing:: error!(
90
85
"failed to remove {:?} from issue {}: {:?}" ,
91
86
label,
@@ -182,10 +177,41 @@ fn match_pattern(pattern: &str, label: &str) -> anyhow::Result<MatchPatternResul
182
177
} )
183
178
}
184
179
180
+ fn compute_label_deltas ( deltas : & [ LabelDelta ] ) -> ( Vec < Label > , Vec < Label > ) {
181
+ let mut add = BTreeSet :: new ( ) ;
182
+ let mut remove = BTreeSet :: new ( ) ;
183
+
184
+ for delta in deltas {
185
+ match delta {
186
+ LabelDelta :: Add ( label) => {
187
+ let label = Label {
188
+ name : label. to_string ( ) ,
189
+ } ;
190
+ if !remove. remove ( & label) {
191
+ add. insert ( label) ;
192
+ }
193
+ }
194
+ LabelDelta :: Remove ( label) => {
195
+ let label = Label {
196
+ name : label. to_string ( ) ,
197
+ } ;
198
+ if !add. remove ( & label) {
199
+ remove. insert ( label) ;
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ ( add. into_iter ( ) . collect ( ) , remove. into_iter ( ) . collect ( ) )
206
+ }
207
+
185
208
#[ cfg( test) ]
186
209
mod tests {
210
+ use parser:: command:: relabel:: { Label , LabelDelta } ;
211
+
187
212
use super :: {
188
- CheckFilterResult , MatchPatternResult , TeamMembership , check_filter, match_pattern,
213
+ CheckFilterResult , MatchPatternResult , TeamMembership , check_filter, compute_label_deltas,
214
+ match_pattern,
189
215
} ;
190
216
use crate :: config:: RelabelConfig ;
191
217
@@ -252,4 +278,55 @@ mod tests {
252
278
}
253
279
Ok ( ( ) )
254
280
}
281
+
282
+ #[ test]
283
+ fn test_compute_label_deltas ( ) {
284
+ use crate :: github:: Label as GitHubLabel ;
285
+
286
+ let mut deltas = vec ! [
287
+ LabelDelta :: Add ( Label ( "I-nominated" . to_string( ) ) ) ,
288
+ LabelDelta :: Add ( Label ( "I-nominated" . to_string( ) ) ) ,
289
+ LabelDelta :: Add ( Label ( "I-lang-nominated" . to_string( ) ) ) ,
290
+ LabelDelta :: Add ( Label ( "I-libs-nominated" . to_string( ) ) ) ,
291
+ LabelDelta :: Remove ( Label ( "I-lang-nominated" . to_string( ) ) ) ,
292
+ ] ;
293
+
294
+ assert_eq ! (
295
+ compute_label_deltas( & deltas) ,
296
+ (
297
+ vec![
298
+ GitHubLabel {
299
+ name: "I-libs-nominated" . to_string( )
300
+ } ,
301
+ GitHubLabel {
302
+ name: "I-nominated" . to_string( )
303
+ } ,
304
+ ] ,
305
+ vec![ ] ,
306
+ ) ,
307
+ ) ;
308
+
309
+ deltas. push ( LabelDelta :: Remove ( Label ( "needs-triage" . to_string ( ) ) ) ) ;
310
+ deltas. push ( LabelDelta :: Add ( Label ( "I-lang-nominated" . to_string ( ) ) ) ) ;
311
+
312
+ assert_eq ! (
313
+ compute_label_deltas( & deltas) ,
314
+ (
315
+ vec![
316
+ GitHubLabel {
317
+ name: "I-lang-nominated" . to_string( )
318
+ } ,
319
+ GitHubLabel {
320
+ name: "I-libs-nominated" . to_string( )
321
+ } ,
322
+ GitHubLabel {
323
+ name: "I-nominated" . to_string( )
324
+ } ,
325
+ ] ,
326
+ vec![ GitHubLabel {
327
+ name: "needs-triage" . to_string( )
328
+ } ] ,
329
+ ) ,
330
+ ) ;
331
+ }
255
332
}
0 commit comments