@@ -5,7 +5,6 @@ package issues
5
5
6
6
import (
7
7
"context"
8
- "fmt"
9
8
"time"
10
9
11
10
"code.gitea.io/gitea/models/db"
@@ -15,20 +14,6 @@ import (
15
14
"code.gitea.io/gitea/modules/util"
16
15
)
17
16
18
- // ErrIssueStopwatchNotExist represents an error that stopwatch is not exist
19
- type ErrIssueStopwatchNotExist struct {
20
- UserID int64
21
- IssueID int64
22
- }
23
-
24
- func (err ErrIssueStopwatchNotExist ) Error () string {
25
- return fmt .Sprintf ("issue stopwatch doesn't exist[uid: %d, issue_id: %d" , err .UserID , err .IssueID )
26
- }
27
-
28
- func (err ErrIssueStopwatchNotExist ) Unwrap () error {
29
- return util .ErrNotExist
30
- }
31
-
32
17
// Stopwatch represents a stopwatch for time tracking.
33
18
type Stopwatch struct {
34
19
ID int64 `xorm:"pk autoincr"`
@@ -55,13 +40,11 @@ func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, ex
55
40
return sw , exists , err
56
41
}
57
42
58
- // UserIDCount is a simple coalition of UserID and Count
59
43
type UserStopwatch struct {
60
44
UserID int64
61
45
StopWatches []* Stopwatch
62
46
}
63
47
64
- // GetUIDsAndNotificationCounts between the two provided times
65
48
func GetUIDsAndStopwatch (ctx context.Context ) ([]* UserStopwatch , error ) {
66
49
sws := []* Stopwatch {}
67
50
if err := db .GetEngine (ctx ).Where ("issue_id != 0" ).Find (& sws ); err != nil {
@@ -87,7 +70,7 @@ func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
87
70
return res , nil
88
71
}
89
72
90
- // GetUserStopwatches return list of all stopwatches of a user
73
+ // GetUserStopwatches return list of the user's all stopwatches
91
74
func GetUserStopwatches (ctx context.Context , userID int64 , listOptions db.ListOptions ) ([]* Stopwatch , error ) {
92
75
sws := make ([]* Stopwatch , 0 , 8 )
93
76
sess := db .GetEngine (ctx ).Where ("stopwatch.user_id = ?" , userID )
@@ -102,7 +85,7 @@ func GetUserStopwatches(ctx context.Context, userID int64, listOptions db.ListOp
102
85
return sws , nil
103
86
}
104
87
105
- // CountUserStopwatches return count of all stopwatches of a user
88
+ // CountUserStopwatches return count of the user's all stopwatches
106
89
func CountUserStopwatches (ctx context.Context , userID int64 ) (int64 , error ) {
107
90
return db .GetEngine (ctx ).Where ("user_id = ?" , userID ).Count (& Stopwatch {})
108
91
}
@@ -136,43 +119,21 @@ func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopw
136
119
return exists , sw , issue , err
137
120
}
138
121
139
- // FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
140
- func FinishIssueStopwatchIfPossible (ctx context.Context , user * user_model.User , issue * Issue ) error {
141
- _ , exists , err := getStopwatch (ctx , user .ID , issue .ID )
142
- if err != nil {
143
- return err
144
- }
145
- if ! exists {
146
- return nil
147
- }
148
- return FinishIssueStopwatch (ctx , user , issue )
149
- }
150
-
151
- // CreateOrStopIssueStopwatch create an issue stopwatch if it's not exist, otherwise finish it
152
- func CreateOrStopIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) error {
153
- _ , exists , err := getStopwatch (ctx , user .ID , issue .ID )
154
- if err != nil {
155
- return err
156
- }
157
- if exists {
158
- return FinishIssueStopwatch (ctx , user , issue )
159
- }
160
- return CreateIssueStopwatch (ctx , user , issue )
161
- }
162
-
163
- // FinishIssueStopwatch if stopwatch exist then finish it otherwise return an error
164
- func FinishIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) error {
122
+ // FinishIssueStopwatch if stopwatch exists, then finish it.
123
+ func FinishIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) (ok bool , err error ) {
165
124
sw , exists , err := getStopwatch (ctx , user .ID , issue .ID )
166
125
if err != nil {
167
- return err
126
+ return false , err
127
+ } else if ! exists {
128
+ return false , nil
168
129
}
169
- if ! exists {
170
- return ErrIssueStopwatchNotExist {
171
- UserID : user .ID ,
172
- IssueID : issue .ID ,
173
- }
130
+ if err = finishIssueStopwatch (ctx , user , issue , sw ); err != nil {
131
+ return false , err
174
132
}
133
+ return true , nil
134
+ }
175
135
136
+ func finishIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue , sw * Stopwatch ) error {
176
137
// Create tracked time out of the time difference between start date and actual date
177
138
timediff := time .Now ().Unix () - int64 (sw .CreatedUnix )
178
139
@@ -184,14 +145,12 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
184
145
Time : timediff ,
185
146
}
186
147
187
- if err := db . Insert (ctx , tt ); err != nil {
148
+ if err := issue . LoadRepo (ctx ); err != nil {
188
149
return err
189
150
}
190
-
191
- if err := issue .LoadRepo (ctx ); err != nil {
151
+ if err := db .Insert (ctx , tt ); err != nil {
192
152
return err
193
153
}
194
-
195
154
if _ , err := CreateComment (ctx , & CreateCommentOptions {
196
155
Doer : user ,
197
156
Issue : issue ,
@@ -202,90 +161,74 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
202
161
}); err != nil {
203
162
return err
204
163
}
205
- _ , err = db .DeleteByBean (ctx , sw )
164
+ _ , err : = db .DeleteByBean (ctx , sw )
206
165
return err
207
166
}
208
167
209
- // CreateIssueStopwatch creates a stopwatch if not exist, otherwise return an error
210
- func CreateIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) error {
211
- if err := issue .LoadRepo (ctx ); err != nil {
212
- return err
213
- }
214
-
215
- // if another stopwatch is running: stop it
216
- exists , _ , otherIssue , err := HasUserStopwatch (ctx , user .ID )
217
- if err != nil {
218
- return err
219
- }
220
- if exists {
221
- if err := FinishIssueStopwatch (ctx , user , otherIssue ); err != nil {
222
- return err
168
+ // CreateIssueStopwatch creates a stopwatch if the issue doesn't have the user's stopwatch.
169
+ // It also stops any other stopwatch that might be running for the user.
170
+ func CreateIssueStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) (ok bool , err error ) {
171
+ { // if another issue's stopwatch is running: stop it; if this issue has a stopwatch: return an error.
172
+ exists , otherStopWatch , otherIssue , err := HasUserStopwatch (ctx , user .ID )
173
+ if err != nil {
174
+ return false , err
175
+ }
176
+ if exists {
177
+ if otherStopWatch .IssueID == issue .ID {
178
+ // don't allow starting stopwatch for the same issue
179
+ return false , nil
180
+ }
181
+ // stop the other issue's stopwatch
182
+ if err = finishIssueStopwatch (ctx , user , otherIssue , otherStopWatch ); err != nil {
183
+ return false , err
184
+ }
223
185
}
224
186
}
225
187
226
- // Create stopwatch
227
- sw := & Stopwatch {
228
- UserID : user .ID ,
229
- IssueID : issue .ID ,
188
+ if err = issue .LoadRepo (ctx ); err != nil {
189
+ return false , err
230
190
}
231
-
232
- if err := db .Insert (ctx , sw ); err != nil {
233
- return err
191
+ if err = db .Insert (ctx , & Stopwatch {UserID : user .ID , IssueID : issue .ID }); err != nil {
192
+ return false , err
234
193
}
235
-
236
- if err := issue .LoadRepo (ctx ); err != nil {
237
- return err
238
- }
239
-
240
- if _ , err := CreateComment (ctx , & CreateCommentOptions {
194
+ if _ , err = CreateComment (ctx , & CreateCommentOptions {
241
195
Doer : user ,
242
196
Issue : issue ,
243
197
Repo : issue .Repo ,
244
198
Type : CommentTypeStartTracking ,
245
199
}); err != nil {
246
- return err
200
+ return false , err
247
201
}
248
-
249
- return nil
202
+ return true , nil
250
203
}
251
204
252
205
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
253
- func CancelStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) error {
254
- ctx , committer , err := db .TxContext (ctx )
255
- if err != nil {
256
- return err
257
- }
258
- defer committer .Close ()
259
- if err := cancelStopwatch (ctx , user , issue ); err != nil {
260
- return err
261
- }
262
- return committer .Commit ()
263
- }
264
-
265
- func cancelStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) error {
266
- e := db .GetEngine (ctx )
267
- sw , exists , err := getStopwatch (ctx , user .ID , issue .ID )
268
- if err != nil {
269
- return err
270
- }
271
-
272
- if exists {
273
- if _ , err := e .Delete (sw ); err != nil {
206
+ func CancelStopwatch (ctx context.Context , user * user_model.User , issue * Issue ) (ok bool , err error ) {
207
+ err = db .WithTx (ctx , func (ctx context.Context ) error {
208
+ e := db .GetEngine (ctx )
209
+ sw , exists , err := getStopwatch (ctx , user .ID , issue .ID )
210
+ if err != nil {
274
211
return err
212
+ } else if ! exists {
213
+ return nil
275
214
}
276
215
277
- if err : = issue .LoadRepo (ctx ); err != nil {
216
+ if err = issue .LoadRepo (ctx ); err != nil {
278
217
return err
279
218
}
280
-
281
- if _ , err := CreateComment (ctx , & CreateCommentOptions {
219
+ if _ , err = e .Delete (sw ); err != nil {
220
+ return err
221
+ }
222
+ if _ , err = CreateComment (ctx , & CreateCommentOptions {
282
223
Doer : user ,
283
224
Issue : issue ,
284
225
Repo : issue .Repo ,
285
226
Type : CommentTypeCancelTracking ,
286
227
}); err != nil {
287
228
return err
288
229
}
289
- }
290
- return nil
230
+ ok = true
231
+ return nil
232
+ })
233
+ return ok , err
291
234
}
0 commit comments