Skip to content

Commit 20bfff3

Browse files
Merge remote-tracking branch 'upstream/main' into limit-repo-size
2 parents 136b631 + 6c8ff32 commit 20bfff3

File tree

118 files changed

+665
-337
lines changed

Some content is hidden

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

118 files changed

+665
-337
lines changed

docs/content/doc/advanced/repo-mirror.en-us.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@ For an existing remote repository, you can set up pull mirroring as follows:
4141

4242
The repository now gets mirrored periodically from the remote repository. You can force a sync by selecting **Synchronize Now** in the repository settings.
4343

44+
:exclamation::exclamation: **NOTE:** You can only set up pull mirroring for repos that don't exist yet on your instance. Once the repo is created, you can't convert it into a pull mirror anymore. :exclamation::exclamation:
45+
4446
## Pushing to a remote repository
4547

4648
For an existing repository, you can set up push mirroring as follows:
4749

4850
1. In your repository, go to **Settings** > **Repository**, and then the **Mirror Settings** section.
4951
2. Enter a repository URL.
50-
3. If the repository needs authentication expand the **Authorization** section and fill in your authentication information.
52+
3. If the repository needs authentication expand the **Authorization** section and fill in your authentication information. Note that the requested **password** can also be your access token.
5153
4. Select **Add Push Mirror** to save the configuration.
5254

5355
The repository now gets mirrored periodically to the remote repository. You can force a sync by selecting **Synchronize Now**. In case of an error a message displayed to help you resolve it.
@@ -59,9 +61,11 @@ The repository now gets mirrored periodically to the remote repository. You can
5961
To set up a mirror from Gitea to GitHub, you need to follow these steps:
6062

6163
1. Create a [GitHub personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) with the *public_repo* box checked.
62-
2. Fill in the **Git Remote Repository URL**: `https://github.com/<your_github_group>/<your_github_project>.git`.
63-
3. Fill in the **Authorization** fields with your GitHub username and the personal access token.
64-
4. Select **Add Push Mirror** to save the configuration.
64+
2. Create a repository with that name on GitHub. Unlike Gitea, GitHub does not support creating repositories by pushing to the remote. You can also use an existing remote repo if it has the same commit history as your Gitea repo.
65+
3. In the settings of your Gitea repo, fill in the **Git Remote Repository URL**: `https://github.com/<your_github_group>/<your_github_project>.git`.
66+
4. Fill in the **Authorization** fields with your GitHub username and the personal access token as **Password**.
67+
5. (Optional, available on Gitea 1.18+) Select `Sync when new commits are pushed` so that the mirror will be updated as well as soon as there are changes. You can also disable the periodic sync if you like.
68+
6. Select **Add Push Mirror** to save the configuration.
6569

6670
The repository pushes shortly thereafter. To force a push, select the **Synchronize Now** button.
6771

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)