@@ -58,8 +58,11 @@ func getAssigneesByIssue(e Engine, issue *Issue) (assignees []*User, err error)
5858
5959// IsUserAssignedToIssue returns true when the user is assigned to the issue
6060func IsUserAssignedToIssue (issue * Issue , user * User ) (isAssigned bool , err error ) {
61- isAssigned , err = x .Exist (& IssueAssignees {IssueID : issue .ID , AssigneeID : user .ID })
62- return
61+ return isUserAssignedToIssue (x , issue , user )
62+ }
63+
64+ func isUserAssignedToIssue (e Engine , issue * Issue , user * User ) (isAssigned bool , err error ) {
65+ return e .Get (& IssueAssignees {IssueID : issue .ID , AssigneeID : user .ID })
6366}
6467
6568// DeleteNotPassedAssignee deletes all assignees who aren't passed via the "assignees" array
@@ -78,7 +81,7 @@ func DeleteNotPassedAssignee(issue *Issue, doer *User, assignees []*User) (err e
7881
7982 if ! found {
8083 // This function also does comments and hooks, which is why we call it seperatly instead of directly removing the assignees here
81- if err := UpdateAssignee ( issue , doer , assignee .ID ); err != nil {
84+ if _ , _ , err := issue . ToggleAssignee ( doer , assignee .ID ); err != nil {
8285 return err
8386 }
8487 }
@@ -110,73 +113,56 @@ func clearAssigneeByUserID(sess *xorm.Session, userID int64) (err error) {
110113 return
111114}
112115
113- // AddAssigneeIfNotAssigned adds an assignee only if he isn't aleady assigned to the issue
114- func AddAssigneeIfNotAssigned (issue * Issue , doer * User , assigneeID int64 ) (err error ) {
115- // Check if the user is already assigned
116- isAssigned , err := IsUserAssignedToIssue (issue , & User {ID : assigneeID })
117- if err != nil {
118- return err
119- }
120-
121- if ! isAssigned {
122- return issue .ChangeAssignee (doer , assigneeID )
123- }
124- return nil
125- }
126-
127- // UpdateAssignee deletes or adds an assignee to an issue
128- func UpdateAssignee (issue * Issue , doer * User , assigneeID int64 ) (err error ) {
129- return issue .ChangeAssignee (doer , assigneeID )
130- }
131-
132- // ChangeAssignee changes the Assignee of this issue.
133- func (issue * Issue ) ChangeAssignee (doer * User , assigneeID int64 ) (err error ) {
116+ // ToggleAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
117+ func (issue * Issue ) ToggleAssignee (doer * User , assigneeID int64 ) (removed bool , comment * Comment , err error ) {
134118 sess := x .NewSession ()
135119 defer sess .Close ()
136120
137121 if err := sess .Begin (); err != nil {
138- return err
122+ return false , nil , err
139123 }
140124
141- if err := issue .changeAssignee (sess , doer , assigneeID , false ); err != nil {
142- return err
125+ removed , comment , err = issue .toggleAssignee (sess , doer , assigneeID , false )
126+ if err != nil {
127+ return false , nil , err
143128 }
144129
145130 if err := sess .Commit (); err != nil {
146- return err
131+ return false , nil , err
147132 }
148133
149134 go HookQueue .Add (issue .RepoID )
150- return nil
135+
136+ return removed , comment , nil
151137}
152138
153- func (issue * Issue ) changeAssignee (sess * xorm.Session , doer * User , assigneeID int64 , isCreate bool ) (err error ) {
154- // Update the assignee
155- removed , err := updateIssueAssignee (sess , issue , assigneeID )
139+ func (issue * Issue ) toggleAssignee (sess * xorm.Session , doer * User , assigneeID int64 , isCreate bool ) (removed bool , comment * Comment , err error ) {
140+ removed , err = toggleUserAssignee (sess , issue , assigneeID )
156141 if err != nil {
157- return fmt .Errorf ("UpdateIssueUserByAssignee: %v" , err )
142+ return false , nil , fmt .Errorf ("UpdateIssueUserByAssignee: %v" , err )
158143 }
159144
160145 // Repo infos
161146 if err = issue .loadRepo (sess ); err != nil {
162- return fmt .Errorf ("loadRepo: %v" , err )
147+ return false , nil , fmt .Errorf ("loadRepo: %v" , err )
163148 }
164149
165150 // Comment
166- if _ , err = createAssigneeComment (sess , doer , issue .Repo , issue , assigneeID , removed ); err != nil {
167- return fmt .Errorf ("createAssigneeComment: %v" , err )
151+ comment , err = createAssigneeComment (sess , doer , issue .Repo , issue , assigneeID , removed )
152+ if err != nil {
153+ return false , nil , fmt .Errorf ("createAssigneeComment: %v" , err )
168154 }
169155
170156 // if pull request is in the middle of creation - don't call webhook
171157 if isCreate {
172- return nil
158+ return removed , comment , err
173159 }
174160
175161 if issue .IsPull {
176162 mode , _ := accessLevelUnit (sess , doer , issue .Repo , UnitTypePullRequests )
177163
178164 if err = issue .loadPullRequest (sess ); err != nil {
179- return fmt .Errorf ("loadPullRequest: %v" , err )
165+ return false , nil , fmt .Errorf ("loadPullRequest: %v" , err )
180166 }
181167 issue .PullRequest .Issue = issue
182168 apiPullRequest := & api.PullRequestPayload {
@@ -190,9 +176,10 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
190176 } else {
191177 apiPullRequest .Action = api .HookIssueAssigned
192178 }
179+ // Assignee comment triggers a webhook
193180 if err := prepareWebhooks (sess , issue .Repo , HookEventPullRequest , apiPullRequest ); err != nil {
194181 log .Error ("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v" , issue .IsPull , removed , err )
195- return nil
182+ return false , nil , err
196183 }
197184 } else {
198185 mode , _ := accessLevelUnit (sess , doer , issue .Repo , UnitTypeIssues )
@@ -208,67 +195,50 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
208195 } else {
209196 apiIssue .Action = api .HookIssueAssigned
210197 }
198+ // Assignee comment triggers a webhook
211199 if err := prepareWebhooks (sess , issue .Repo , HookEventIssues , apiIssue ); err != nil {
212200 log .Error ("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v" , issue .IsPull , removed , err )
213- return nil
201+ return false , nil , err
214202 }
215203 }
216- return nil
204+ return removed , comment , nil
217205}
218206
219- // UpdateAPIAssignee is a helper function to add or delete one or multiple issue assignee(s)
220- // Deleting is done the GitHub way (quote from their api documentation):
221- // https://developer.github.com/v3/issues/#edit-an-issue
222- // "assignees" (array): Logins for Users to assign to this issue.
223- // Pass one or more user logins to replace the set of assignees on this Issue.
224- // Send an empty array ([]) to clear all assignees from the Issue.
225- func UpdateAPIAssignee (issue * Issue , oneAssignee string , multipleAssignees []string , doer * User ) (err error ) {
226- var allNewAssignees []* User
207+ // toggles user assignee state in database
208+ func toggleUserAssignee (e * xorm.Session , issue * Issue , assigneeID int64 ) (removed bool , err error ) {
227209
228- // Keep the old assignee thingy for compatibility reasons
229- if oneAssignee != "" {
230- // Prevent double adding assignees
231- var isDouble bool
232- for _ , assignee := range multipleAssignees {
233- if assignee == oneAssignee {
234- isDouble = true
235- break
236- }
237- }
238-
239- if ! isDouble {
240- multipleAssignees = append (multipleAssignees , oneAssignee )
241- }
210+ // Check if the user exists
211+ assignee , err := getUserByID (e , assigneeID )
212+ if err != nil {
213+ return false , err
242214 }
243215
244- // Loop through all assignees to add them
245- for _ , assigneeName := range multipleAssignees {
246- assignee , err := GetUserByName ( assigneeName )
247- if err != nil {
248- return err
216+ // Check if the submitted user is already assigned, if yes delete him otherwise add him
217+ var i int
218+ for i = 0 ; i < len ( issue . Assignees ); i ++ {
219+ if issue . Assignees [ i ]. ID == assigneeID {
220+ break
249221 }
250-
251- allNewAssignees = append (allNewAssignees , assignee )
252222 }
253223
254- // Delete all old assignees not passed
255- if err = DeleteNotPassedAssignee (issue , doer , allNewAssignees ); err != nil {
256- return err
257- }
224+ assigneeIn := IssueAssignees {AssigneeID : assigneeID , IssueID : issue .ID }
258225
259- // Add all new assignees
260- // Update the assignee. The function will check if the user exists, is already
261- // assigned (which he shouldn't as we deleted all assignees before) and
262- // has access to the repo.
263- for _ , assignee := range allNewAssignees {
264- // Extra method to prevent double adding (which would result in removing)
265- err = AddAssigneeIfNotAssigned (issue , doer , assignee .ID )
226+ toBeDeleted := i < len (issue .Assignees )
227+ if toBeDeleted {
228+ issue .Assignees = append (issue .Assignees [:i ], issue .Assignees [i :]... )
229+ _ , err = e .Delete (assigneeIn )
266230 if err != nil {
267- return err
231+ return toBeDeleted , err
232+ }
233+ } else {
234+ issue .Assignees = append (issue .Assignees , assignee )
235+ _ , err = e .Insert (assigneeIn )
236+ if err != nil {
237+ return toBeDeleted , err
268238 }
269239 }
270240
271- return
241+ return toBeDeleted , nil
272242}
273243
274244// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
@@ -292,7 +262,7 @@ func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string
292262 }
293263
294264 // Get the IDs of all assignees
295- assigneeIDs = GetUserIDsByNames (multipleAssignees )
265+ assigneeIDs , err = GetUserIDsByNames (multipleAssignees , false )
296266
297267 return
298268}
0 commit comments