Skip to content

Commit b1c080e

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Prevent panic in doctor command when running default checks (go-gitea#21791) fix webpackChunkName for citation-js-csl (go-gitea#21806) Add plural definitions for German translations (go-gitea#21802) Fix webhook attachment text is not set in review comment (go-gitea#21763) Render number of commits in repo page in a user friendly way (go-gitea#21786) Upgrade golang.org/x/crypto (go-gitea#21792) Allow detect whether it's in a database transaction for a context.Context (go-gitea#21756) Add some documentation to packages (go-gitea#21648) Adjust clone timeout error to suggest increasing timeout (go-gitea#21769) Simplify text color selectors and tweak arc-green colors (go-gitea#21784) Load GitRepo in API before deleting issue (go-gitea#21720) Copy citation file content, in APA and BibTex format, on repo home page (go-gitea#19999) Ignore line anchor links with leading zeroes (go-gitea#21728) Update message of reach_limit_of_creation (go-gitea#21757) Add configuration for CORS allowed headers (go-gitea#21747)
2 parents f152eb2 + d9ba7f7 commit b1c080e

File tree

119 files changed

+875
-340
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+875
-340
lines changed

custom/conf/app.example.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,9 @@ ROUTER = console
11381138
;; allow request with credentials
11391139
;ALLOW_CREDENTIALS = false
11401140
;;
1141+
;; headers to permit
1142+
;HEADERS = Content-Type,User-Agent
1143+
;;
11411144
;; set X-FRAME-OPTIONS header
11421145
;X_FRAME_OPTIONS = SAMEORIGIN
11431146

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
200200
- `METHODS`: **GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS**: list of methods allowed to request
201201
- `MAX_AGE`: **10m**: max time to cache response
202202
- `ALLOW_CREDENTIALS`: **false**: allow request with credentials
203+
- `HEADERS`: **Content-Type,User-Agent**: additional headers that are permitted in requests
203204
- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value.
204205

205206
## UI (`ui`)

docs/content/doc/translation/guidelines.de-de.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ Beispiel: Wenn der Button mit `löschen` beschriftet ist, sollte im Modal die Fr
4545
## Artikeldefinitionen für Anglizismen
4646

4747
* _Der_ Commit (m.)
48-
* _Der_ Branch (m.)
48+
* _Der_ Branch (m.), plural: die Branches
4949
* _Das_ Issue (n.)
5050
* _Der_ Fork (m.)
51-
* _Das_ Repository (n.)
51+
* _Das_ Repository (n.), plural: die Repositories
5252
* _Der_ Pull-Request (m.)
53-
* _Der_ Token (m.)
53+
* _Der_ Token (m.), plural: die Token
5454
* _Das_ Review (n.)
5555
* _Der_ Key (m.)
56-
* _Der_ Committer (m.)
56+
* _Der_ Committer (m.), plural: die Committer
5757

5858
## Weiterführende Links
5959

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ require (
9494
github.com/yuin/goldmark-meta v1.1.0
9595
go.jolheiser.com/hcaptcha v0.0.4
9696
go.jolheiser.com/pwn v0.0.3
97-
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
98-
golang.org/x/net v0.0.0-20220927171203-f486391704dc
97+
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891
98+
golang.org/x/net v0.2.0
9999
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
100-
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec
101-
golang.org/x/text v0.3.8
100+
golang.org/x/sys v0.2.0
101+
golang.org/x/text v0.4.0
102102
golang.org/x/tools v0.1.12
103103
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
104104
gopkg.in/ini.v1 v1.67.0

go.sum

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,8 +1608,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0
16081608
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
16091609
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
16101610
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
1611-
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A=
1612-
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
1611+
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891 h1:WhEPFM1Ck5gaKybeSWvzI7Y/cd8K9K5tJGRxXMACOBA=
1612+
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
16131613
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
16141614
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
16151615
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1721,8 +1721,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
17211721
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
17221722
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
17231723
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
1724-
golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ=
1725-
golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
1724+
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
1725+
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
17261726
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
17271727
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
17281728
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1876,13 +1876,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
18761876
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
18771877
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
18781878
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1879-
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
1880-
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1879+
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
1880+
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
18811881
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
18821882
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
18831883
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1884-
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
18851884
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1885+
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
18861886
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
18871887
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
18881888
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1892,8 +1892,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
18921892
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
18931893
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
18941894
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
1895-
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
1896-
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
1895+
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
1896+
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
18971897
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
18981898
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
18991899
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

models/activities/action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ func NotifyWatchers(actions ...*Action) error {
572572

573573
// NotifyWatchersActions creates batch of actions for every watcher.
574574
func NotifyWatchersActions(acts []*Action) error {
575-
ctx, committer, err := db.TxContext()
575+
ctx, committer, err := db.TxContext(db.DefaultContext)
576576
if err != nil {
577577
return err
578578
}

models/activities/notification.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func CountNotifications(opts *FindNotificationOptions) (int64, error) {
142142

143143
// CreateRepoTransferNotification creates notification for the user a repository was transferred to
144144
func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_model.Repository) error {
145-
ctx, committer, err := db.TxContext()
145+
ctx, committer, err := db.TxContext(db.DefaultContext)
146146
if err != nil {
147147
return err
148148
}
@@ -185,7 +185,7 @@ func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_
185185
// for each watcher, or updates it if already exists
186186
// receiverID > 0 just send to receiver, else send to all watcher
187187
func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error {
188-
ctx, committer, err := db.TxContext()
188+
ctx, committer, err := db.TxContext(db.DefaultContext)
189189
if err != nil {
190190
return err
191191
}

models/asymkey/gpg_key.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ func DeleteGPGKey(doer *user_model.User, id int64) (err error) {
234234
return ErrGPGKeyAccessDenied{doer.ID, key.ID}
235235
}
236236

237-
ctx, committer, err := db.TxContext()
237+
ctx, committer, err := db.TxContext(db.DefaultContext)
238238
if err != nil {
239239
return err
240240
}

models/asymkey/gpg_key_add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func AddGPGKey(ownerID int64, content, token, signature string) ([]*GPGKey, erro
7373
return nil, err
7474
}
7575

76-
ctx, committer, err := db.TxContext()
76+
ctx, committer, err := db.TxContext(db.DefaultContext)
7777
if err != nil {
7878
return nil, err
7979
}

models/asymkey/gpg_key_verify.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131

3232
// VerifyGPGKey marks a GPG key as verified
3333
func VerifyGPGKey(ownerID int64, keyID, token, signature string) (string, error) {
34-
ctx, committer, err := db.TxContext()
34+
ctx, committer, err := db.TxContext(db.DefaultContext)
3535
if err != nil {
3636
return "", err
3737
}

models/asymkey/ssh_key.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func AddPublicKey(ownerID int64, name, content string, authSourceID int64) (*Pub
100100
return nil, err
101101
}
102102

103-
ctx, committer, err := db.TxContext()
103+
ctx, committer, err := db.TxContext(db.DefaultContext)
104104
if err != nil {
105105
return nil, err
106106
}
@@ -321,7 +321,7 @@ func PublicKeyIsExternallyManaged(id int64) (bool, error) {
321321
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
322322
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
323323
// Start session
324-
ctx, committer, err := db.TxContext()
324+
ctx, committer, err := db.TxContext(db.DefaultContext)
325325
if err != nil {
326326
return false, err
327327
}

models/asymkey/ssh_key_deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
126126
accessMode = perm.AccessModeWrite
127127
}
128128

129-
ctx, committer, err := db.TxContext()
129+
ctx, committer, err := db.TxContext(db.DefaultContext)
130130
if err != nil {
131131
return nil, err
132132
}

models/asymkey/ssh_key_principals.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
// AddPrincipalKey adds new principal to database and authorized_principals file.
2828
func AddPrincipalKey(ownerID int64, content string, authSourceID int64) (*PublicKey, error) {
29-
ctx, committer, err := db.TxContext()
29+
ctx, committer, err := db.TxContext(db.DefaultContext)
3030
if err != nil {
3131
return nil, err
3232
}

models/asymkey/ssh_key_verify.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
// VerifySSHKey marks a SSH key as verified
1717
func VerifySSHKey(ownerID int64, fingerprint, token, signature string) (string, error) {
18-
ctx, committer, err := db.TxContext()
18+
ctx, committer, err := db.TxContext(db.DefaultContext)
1919
if err != nil {
2020
return "", err
2121
}

models/auth/oauth2.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ type UpdateOAuth2ApplicationOptions struct {
201201

202202
// UpdateOAuth2Application updates an oauth2 application
203203
func UpdateOAuth2Application(opts UpdateOAuth2ApplicationOptions) (*OAuth2Application, error) {
204-
ctx, committer, err := db.TxContext()
204+
ctx, committer, err := db.TxContext(db.DefaultContext)
205205
if err != nil {
206206
return nil, err
207207
}
@@ -265,7 +265,7 @@ func deleteOAuth2Application(ctx context.Context, id, userid int64) error {
265265

266266
// DeleteOAuth2Application deletes the application with the given id and the grants and auth codes related to it. It checks if the userid was the creator of the app.
267267
func DeleteOAuth2Application(id, userid int64) error {
268-
ctx, committer, err := db.TxContext()
268+
ctx, committer, err := db.TxContext(db.DefaultContext)
269269
if err != nil {
270270
return err
271271
}

models/auth/session.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func ReadSession(key string) (*Session, error) {
3737
Key: key,
3838
}
3939

40-
ctx, committer, err := db.TxContext()
40+
ctx, committer, err := db.TxContext(db.DefaultContext)
4141
if err != nil {
4242
return nil, err
4343
}
@@ -73,7 +73,7 @@ func DestroySession(key string) error {
7373

7474
// RegenerateSession regenerates a session from the old id
7575
func RegenerateSession(oldKey, newKey string) (*Session, error) {
76-
ctx, committer, err := db.TxContext()
76+
ctx, committer, err := db.TxContext(db.DefaultContext)
7777
if err != nil {
7878
return nil, err
7979
}

models/avatars/avatar.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func saveEmailHash(email string) string {
9797
Hash: emailHash,
9898
}
9999
// OK we're going to open a session just because I think that that might hide away any problems with postgres reporting errors
100-
if err := db.WithTx(func(ctx context.Context) error {
100+
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
101101
has, err := db.GetEngine(ctx).Where("email = ? AND hash = ?", emailHash.Email, emailHash.Hash).Get(new(EmailHash))
102102
if has || err != nil {
103103
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time

models/db/context.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"database/sql"
1010

11+
"xorm.io/xorm"
1112
"xorm.io/xorm/schemas"
1213
)
1314

@@ -86,7 +87,11 @@ type Committer interface {
8687
}
8788

8889
// TxContext represents a transaction Context
89-
func TxContext() (*Context, Committer, error) {
90+
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
91+
if InTransaction(parentCtx) {
92+
return nil, nil, ErrAlreadyInTransaction
93+
}
94+
9095
sess := x.NewSession()
9196
if err := sess.Begin(); err != nil {
9297
sess.Close()
@@ -97,14 +102,24 @@ func TxContext() (*Context, Committer, error) {
97102
}
98103

99104
// WithTx represents executing database operations on a transaction
100-
// you can optionally change the context to a parent one
101-
func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error {
102-
parentCtx := DefaultContext
103-
if len(stdCtx) != 0 && stdCtx[0] != nil {
104-
// TODO: make sure parent context has no open session
105-
parentCtx = stdCtx[0]
105+
// This function will always open a new transaction, if a transaction exist in parentCtx return an error.
106+
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error {
107+
if InTransaction(parentCtx) {
108+
return ErrAlreadyInTransaction
109+
}
110+
return txWithNoCheck(parentCtx, f)
111+
}
112+
113+
// AutoTx represents executing database operations on a transaction, if the transaction exist,
114+
// this function will reuse it otherwise will create a new one and close it when finished.
115+
func AutoTx(parentCtx context.Context, f func(ctx context.Context) error) error {
116+
if InTransaction(parentCtx) {
117+
return f(newContext(parentCtx, GetEngine(parentCtx), true))
106118
}
119+
return txWithNoCheck(parentCtx, f)
120+
}
107121

122+
func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error) error {
108123
sess := x.NewSession()
109124
defer sess.Close()
110125
if err := sess.Begin(); err != nil {
@@ -180,3 +195,28 @@ func EstimateCount(ctx context.Context, bean interface{}) (int64, error) {
180195
}
181196
return rows, err
182197
}
198+
199+
// InTransaction returns true if the engine is in a transaction otherwise return false
200+
func InTransaction(ctx context.Context) bool {
201+
var e Engine
202+
if engined, ok := ctx.(Engined); ok {
203+
e = engined.Engine()
204+
} else {
205+
enginedInterface := ctx.Value(enginedContextKey)
206+
if enginedInterface != nil {
207+
e = enginedInterface.(Engined).Engine()
208+
}
209+
}
210+
if e == nil {
211+
return false
212+
}
213+
214+
switch t := e.(type) {
215+
case *xorm.Engine:
216+
return false
217+
case *xorm.Session:
218+
return t.IsInTx()
219+
default:
220+
return false
221+
}
222+
}

models/db/context_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package db_test
6+
7+
import (
8+
"context"
9+
"testing"
10+
11+
"code.gitea.io/gitea/models/db"
12+
"code.gitea.io/gitea/models/unittest"
13+
14+
"github.com/stretchr/testify/assert"
15+
)
16+
17+
func TestInTransaction(t *testing.T) {
18+
assert.NoError(t, unittest.PrepareTestDatabase())
19+
assert.False(t, db.InTransaction(db.DefaultContext))
20+
assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error {
21+
assert.True(t, db.InTransaction(ctx))
22+
return nil
23+
}))
24+
25+
ctx, committer, err := db.TxContext(db.DefaultContext)
26+
assert.NoError(t, err)
27+
defer committer.Close()
28+
assert.True(t, db.InTransaction(ctx))
29+
assert.Error(t, db.WithTx(ctx, func(ctx context.Context) error {
30+
assert.True(t, db.InTransaction(ctx))
31+
return nil
32+
}))
33+
}

models/db/error.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
package db
66

77
import (
8+
"errors"
89
"fmt"
910

1011
"code.gitea.io/gitea/modules/util"
1112
)
1213

14+
var ErrAlreadyInTransaction = errors.New("database connection has already been in a transaction")
15+
1316
// ErrCancelled represents an error due to context cancellation
1417
type ErrCancelled struct {
1518
Message string

0 commit comments

Comments
 (0)