@@ -7,6 +7,7 @@ package models
7
7
import (
8
8
"errors"
9
9
"fmt"
10
+ "sort"
10
11
"strings"
11
12
"time"
12
13
@@ -103,11 +104,17 @@ func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) {
103
104
return
104
105
}
105
106
106
- func (issue * Issue ) loadAttributes (e Engine ) (err error ) {
107
- if err := issue .loadRepo (e ); err != nil {
108
- return err
107
+ func (issue * Issue ) loadLabels (e Engine ) (err error ) {
108
+ if issue .Labels == nil {
109
+ issue .Labels , err = getLabelsByIssueID (e , issue .ID )
110
+ if err != nil {
111
+ return fmt .Errorf ("getLabelsByIssueID [%d]: %v" , issue .ID , err )
112
+ }
109
113
}
114
+ return nil
115
+ }
110
116
117
+ func (issue * Issue ) loadPoster (e Engine ) (err error ) {
111
118
if issue .Poster == nil {
112
119
issue .Poster , err = getUserByID (e , issue .PosterID )
113
120
if err != nil {
@@ -120,12 +127,20 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
120
127
return
121
128
}
122
129
}
130
+ return
131
+ }
123
132
124
- if issue .Labels == nil {
125
- issue .Labels , err = getLabelsByIssueID (e , issue .ID )
126
- if err != nil {
127
- return fmt .Errorf ("getLabelsByIssueID [%d]: %v" , issue .ID , err )
128
- }
133
+ func (issue * Issue ) loadAttributes (e Engine ) (err error ) {
134
+ if err = issue .loadRepo (e ); err != nil {
135
+ return
136
+ }
137
+
138
+ if err = issue .loadPoster (e ); err != nil {
139
+ return
140
+ }
141
+
142
+ if err = issue .loadLabels (e ); err != nil {
143
+ return
129
144
}
130
145
131
146
if issue .Milestone == nil && issue .MilestoneID > 0 {
@@ -289,27 +304,27 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
289
304
}
290
305
}
291
306
292
- func (issue * Issue ) addLabel (e * xorm.Session , label * Label ) error {
293
- return newIssueLabel (e , issue , label )
307
+ func (issue * Issue ) addLabel (e * xorm.Session , label * Label , doer * User ) error {
308
+ return newIssueLabel (e , issue , label , doer )
294
309
}
295
310
296
311
// AddLabel adds a new label to the issue.
297
312
func (issue * Issue ) AddLabel (doer * User , label * Label ) error {
298
- if err := NewIssueLabel (issue , label ); err != nil {
313
+ if err := NewIssueLabel (issue , label , doer ); err != nil {
299
314
return err
300
315
}
301
316
302
317
issue .sendLabelUpdatedWebhook (doer )
303
318
return nil
304
319
}
305
320
306
- func (issue * Issue ) addLabels (e * xorm.Session , labels []* Label ) error {
307
- return newIssueLabels (e , issue , labels )
321
+ func (issue * Issue ) addLabels (e * xorm.Session , labels []* Label , doer * User ) error {
322
+ return newIssueLabels (e , issue , labels , doer )
308
323
}
309
324
310
325
// AddLabels adds a list of new labels to the issue.
311
326
func (issue * Issue ) AddLabels (doer * User , labels []* Label ) error {
312
- if err := NewIssueLabels (issue , labels ); err != nil {
327
+ if err := NewIssueLabels (issue , labels , doer ); err != nil {
313
328
return err
314
329
}
315
330
@@ -329,8 +344,8 @@ func (issue *Issue) getLabels(e Engine) (err error) {
329
344
return nil
330
345
}
331
346
332
- func (issue * Issue ) removeLabel (e * xorm.Session , label * Label ) error {
333
- return deleteIssueLabel (e , issue , label )
347
+ func (issue * Issue ) removeLabel (e * xorm.Session , doer * User , label * Label ) error {
348
+ return deleteIssueLabel (e , doer , issue , label )
334
349
}
335
350
336
351
// RemoveLabel removes a label from issue by given ID.
@@ -345,21 +360,21 @@ func (issue *Issue) RemoveLabel(doer *User, label *Label) error {
345
360
return ErrLabelNotExist {}
346
361
}
347
362
348
- if err := DeleteIssueLabel (issue , label ); err != nil {
363
+ if err := DeleteIssueLabel (issue , doer , label ); err != nil {
349
364
return err
350
365
}
351
366
352
367
issue .sendLabelUpdatedWebhook (doer )
353
368
return nil
354
369
}
355
370
356
- func (issue * Issue ) clearLabels (e * xorm.Session ) (err error ) {
371
+ func (issue * Issue ) clearLabels (e * xorm.Session , doer * User ) (err error ) {
357
372
if err = issue .getLabels (e ); err != nil {
358
373
return fmt .Errorf ("getLabels: %v" , err )
359
374
}
360
375
361
376
for i := range issue .Labels {
362
- if err = issue .removeLabel (e , issue .Labels [i ]); err != nil {
377
+ if err = issue .removeLabel (e , doer , issue .Labels [i ]); err != nil {
363
378
return fmt .Errorf ("removeLabel: %v" , err )
364
379
}
365
380
}
@@ -386,7 +401,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
386
401
return ErrLabelNotExist {}
387
402
}
388
403
389
- if err = issue .clearLabels (sess ); err != nil {
404
+ if err = issue .clearLabels (sess , doer ); err != nil {
390
405
return err
391
406
}
392
407
@@ -417,19 +432,75 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
417
432
return nil
418
433
}
419
434
435
+ type labelSorter []* Label
436
+
437
+ func (ts labelSorter ) Len () int {
438
+ return len ([]* Label (ts ))
439
+ }
440
+
441
+ func (ts labelSorter ) Less (i , j int ) bool {
442
+ return []* Label (ts )[i ].ID < []* Label (ts )[j ].ID
443
+ }
444
+
445
+ func (ts labelSorter ) Swap (i , j int ) {
446
+ []* Label (ts )[i ], []* Label (ts )[j ] = []* Label (ts )[j ], []* Label (ts )[i ]
447
+ }
448
+
420
449
// ReplaceLabels removes all current labels and add new labels to the issue.
421
450
// Triggers appropriate WebHooks, if any.
422
- func (issue * Issue ) ReplaceLabels (labels []* Label ) (err error ) {
451
+ func (issue * Issue ) ReplaceLabels (labels []* Label , doer * User ) (err error ) {
423
452
sess := x .NewSession ()
424
453
defer sessionRelease (sess )
425
454
if err = sess .Begin (); err != nil {
426
455
return err
427
456
}
428
457
429
- if err = issue .clearLabels (sess ); err != nil {
430
- return fmt .Errorf ("clearLabels: %v" , err )
431
- } else if err = issue .addLabels (sess , labels ); err != nil {
432
- return fmt .Errorf ("addLabels: %v" , err )
458
+ if err = issue .loadLabels (sess ); err != nil {
459
+ return err
460
+ }
461
+
462
+ sort .Sort (labelSorter (labels ))
463
+ sort .Sort (labelSorter (issue .Labels ))
464
+
465
+ var toAdd , toRemove []* Label
466
+ for _ , l := range labels {
467
+ var exist bool
468
+ for _ , oriLabel := range issue .Labels {
469
+ if oriLabel .ID == l .ID {
470
+ exist = true
471
+ break
472
+ }
473
+ }
474
+ if ! exist {
475
+ toAdd = append (toAdd , l )
476
+ }
477
+ }
478
+
479
+ for _ , oriLabel := range issue .Labels {
480
+ var exist bool
481
+ for _ , l := range labels {
482
+ if oriLabel .ID == l .ID {
483
+ exist = true
484
+ break
485
+ }
486
+ }
487
+ if ! exist {
488
+ toRemove = append (toRemove , oriLabel )
489
+ }
490
+ }
491
+
492
+ if len (toAdd ) > 0 {
493
+ if err = issue .addLabels (sess , toAdd , doer ); err != nil {
494
+ return fmt .Errorf ("addLabels: %v" , err )
495
+ }
496
+ }
497
+
498
+ if len (toRemove ) > 0 {
499
+ for _ , l := range toRemove {
500
+ if err = issue .removeLabel (sess , doer , l ); err != nil {
501
+ return fmt .Errorf ("removeLabel: %v" , err )
502
+ }
503
+ }
433
504
}
434
505
435
506
return sess .Commit ()
@@ -731,13 +802,17 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
731
802
return fmt .Errorf ("find all labels [label_ids: %v]: %v" , opts .LableIDs , err )
732
803
}
733
804
805
+ if err = opts .Issue .loadPoster (e ); err != nil {
806
+ return err
807
+ }
808
+
734
809
for _ , label := range labels {
735
810
// Silently drop invalid labels.
736
811
if label .RepoID != opts .Repo .ID {
737
812
continue
738
813
}
739
814
740
- if err = opts .Issue .addLabel (e , label ); err != nil {
815
+ if err = opts .Issue .addLabel (e , label , opts . Issue . Poster ); err != nil {
741
816
return fmt .Errorf ("addLabel [id: %d]: %v" , label .ID , err )
742
817
}
743
818
}
0 commit comments