Skip to content

Commit 9bba399

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: [skip ci] Updated translations via Crowdin when sorting issues by nearest due date, issues without due date should be sorted ascending (go-gitea#35267) [skip ci] Updated translations via Crowdin Upgrade xz to v0.5.15 (go-gitea#35377) Refactor db package (go-gitea#35380) Remove the duplicated function GetTags (go-gitea#35375) [skip ci] Updated translations via Crowdin Allow foreachref parser to grow its buffer (go-gitea#35365) Remove global context from db package (go-gitea#35371) Use gitrepo.SetDefaultBranch when set default branch of wiki repository (go-gitea#33911) Deleting branch could delete broken branch which has database record but git branch is missing (go-gitea#35360)
2 parents 553f2da + fd7ebaf commit 9bba399

File tree

27 files changed

+251
-306
lines changed

27 files changed

+251
-306
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ require (
107107
github.com/stretchr/testify v1.10.0
108108
github.com/syndtr/goleveldb v1.0.0
109109
github.com/tstranex/u2f v1.0.0
110-
github.com/ulikunitz/xz v0.5.12
110+
github.com/ulikunitz/xz v0.5.15
111111
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
112112
github.com/urfave/cli/v3 v3.3.3
113113
github.com/wneessen/go-mail v0.6.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,8 @@ github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGB
684684
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
685685
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
686686
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
687-
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
688-
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
687+
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
688+
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
689689
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
690690
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
691691
github.com/urfave/cli-docs/v3 v3.0.0-alpha6 h1:w/l/N0xw1rO/aHRIGXJ0lDwwYFOzilup1qGvIytP3BI=

models/auth/session.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func RegenerateSession(ctx context.Context, oldKey, newKey string) (*Session, er
8686
}
8787
}
8888

89-
if _, err := db.Exec(ctx, "UPDATE "+db.TableName(&Session{})+" SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil {
89+
if _, err := db.Exec(ctx, "UPDATE `session` SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil {
9090
return nil, err
9191
}
9292

models/auth/source_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"testing"
99

1010
auth_model "code.gitea.io/gitea/models/auth"
11-
"code.gitea.io/gitea/models/db"
1211
"code.gitea.io/gitea/models/unittest"
1312
"code.gitea.io/gitea/modules/json"
1413

@@ -40,7 +39,7 @@ func (source *TestSource) ToDB() ([]byte, error) {
4039
func TestDumpAuthSource(t *testing.T) {
4140
assert.NoError(t, unittest.PrepareTestDatabase())
4241

43-
authSourceSchema, err := db.TableInfo(new(auth_model.Source))
42+
authSourceSchema, err := unittest.GetXORMEngine().TableInfo(new(auth_model.Source))
4443
assert.NoError(t, err)
4544

4645
auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource))

models/db/context.go

Lines changed: 21 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,8 @@ type engineContextKeyType struct{}
2121

2222
var engineContextKey = engineContextKeyType{}
2323

24-
type xormContextType struct {
25-
context.Context
26-
engine Engine
27-
}
28-
29-
var xormContext *xormContextType
30-
31-
func newContext(ctx context.Context, e Engine) *xormContextType {
32-
return &xormContextType{Context: ctx, engine: e}
33-
}
34-
35-
// Value shadows Value for context.Context but allows us to get ourselves and an Engined object
36-
func (ctx *xormContextType) Value(key any) any {
37-
if key == engineContextKey {
38-
return ctx
39-
}
40-
return ctx.Context.Value(key)
41-
}
42-
43-
// WithContext returns this engine tied to this context
44-
func (ctx *xormContextType) WithContext(other context.Context) *xormContextType {
45-
return newContext(ctx, ctx.engine.Context(other))
24+
func withContextEngine(ctx context.Context, e Engine) context.Context {
25+
return context.WithValue(ctx, engineContextKey, e)
4626
}
4727

4828
var (
@@ -81,35 +61,26 @@ func contextSafetyCheck(e Engine) {
8161
callerNum := runtime.Callers(3, callers) // skip 3: runtime.Callers, contextSafetyCheck, GetEngine
8262
for i := range callerNum {
8363
if slices.Contains(contextSafetyDeniedFuncPCs, callers[i]) {
84-
panic(errors.New("using database context in an iterator would cause corrupted results"))
64+
panic(errors.New("using session context in an iterator would cause corrupted results"))
8565
}
8666
}
8767
}
8868

8969
// GetEngine gets an existing db Engine/Statement or creates a new Session
90-
func GetEngine(ctx context.Context) (e Engine) {
91-
defer func() { contextSafetyCheck(e) }()
92-
if e := getExistingEngine(ctx); e != nil {
93-
return e
70+
func GetEngine(ctx context.Context) Engine {
71+
if engine, ok := ctx.Value(engineContextKey).(Engine); ok {
72+
// if reusing the existing session, need to do "contextSafetyCheck" because the Iterate creates a "autoResetStatement=false" session
73+
contextSafetyCheck(engine)
74+
return engine
9475
}
76+
// no need to do "contextSafetyCheck" because it's a new Session
9577
return xormEngine.Context(ctx)
9678
}
9779

9880
func GetXORMEngineForTesting() *xorm.Engine {
9981
return xormEngine
10082
}
10183

102-
// getExistingEngine gets an existing db Engine/Statement from this context or returns nil
103-
func getExistingEngine(ctx context.Context) (e Engine) {
104-
if engined, ok := ctx.(*xormContextType); ok {
105-
return engined.engine
106-
}
107-
if engined, ok := ctx.Value(engineContextKey).(*xormContextType); ok {
108-
return engined.engine
109-
}
110-
return nil
111-
}
112-
11384
// Committer represents an interface to Commit or Close the Context
11485
type Committer interface {
11586
Commit() error
@@ -152,24 +123,23 @@ func (c *halfCommitter) Close() error {
152123
// And all operations submitted by the caller stack will be rollbacked as well, not only the operations in the current function.
153124
// d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback.
154125
func TxContext(parentCtx context.Context) (context.Context, Committer, error) {
155-
if sess, ok := inTransaction(parentCtx); ok {
156-
return newContext(parentCtx, sess), &halfCommitter{committer: sess}, nil
126+
if sess := getTransactionSession(parentCtx); sess != nil {
127+
return withContextEngine(parentCtx, sess), &halfCommitter{committer: sess}, nil
157128
}
158129

159130
sess := xormEngine.NewSession()
160131
if err := sess.Begin(); err != nil {
161132
_ = sess.Close()
162133
return nil, nil, err
163134
}
164-
165-
return newContext(xormContext, sess), sess, nil
135+
return withContextEngine(parentCtx, sess), sess, nil
166136
}
167137

168138
// WithTx represents executing database operations on a transaction, if the transaction exist,
169139
// this function will reuse it otherwise will create a new one and close it when finished.
170140
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error {
171-
if sess, ok := inTransaction(parentCtx); ok {
172-
err := f(newContext(parentCtx, sess))
141+
if sess := getTransactionSession(parentCtx); sess != nil {
142+
err := f(withContextEngine(parentCtx, sess))
173143
if err != nil {
174144
// rollback immediately, in case the caller ignores returned error and tries to commit the transaction.
175145
_ = sess.Close()
@@ -195,7 +165,7 @@ func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error)
195165
return err
196166
}
197167

198-
if err := f(newContext(parentCtx, sess)); err != nil {
168+
if err := f(withContextEngine(parentCtx, sess)); err != nil {
199169
return err
200170
}
201171

@@ -333,32 +303,15 @@ func CountByBean(ctx context.Context, bean any) (int64, error) {
333303
return GetEngine(ctx).Count(bean)
334304
}
335305

336-
// TableName returns the table name according a bean object
337-
func TableName(bean any) string {
338-
return xormEngine.TableName(bean)
339-
}
340-
341306
// InTransaction returns true if the engine is in a transaction otherwise return false
342307
func InTransaction(ctx context.Context) bool {
343-
_, ok := inTransaction(ctx)
344-
return ok
308+
return getTransactionSession(ctx) != nil
345309
}
346310

347-
func inTransaction(ctx context.Context) (*xorm.Session, bool) {
348-
e := getExistingEngine(ctx)
349-
if e == nil {
350-
return nil, false
351-
}
352-
353-
switch t := e.(type) {
354-
case *xorm.Engine:
355-
return nil, false
356-
case *xorm.Session:
357-
if t.IsInTx() {
358-
return t, true
359-
}
360-
return nil, false
361-
default:
362-
return nil, false
311+
func getTransactionSession(ctx context.Context) *xorm.Session {
312+
e, _ := ctx.Value(engineContextKey).(Engine)
313+
if sess, ok := e.(*xorm.Session); ok && sess.IsInTx() {
314+
return sess
363315
}
316+
return nil
364317
}

models/db/context_test.go

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,31 +100,36 @@ func TestContextSafety(t *testing.T) {
100100
assert.NoError(t, db.Insert(t.Context(), &TestModel2{ID: int64(-i)}))
101101
}
102102

103-
actualCount := 0
104-
// here: db.GetEngine(t.Context()) is a new *Session created from *Engine
105-
_ = db.WithTx(t.Context(), func(ctx context.Context) error {
106-
_ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
107-
// here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false,
108-
// and the internal states (including "cond" and others) are always there and not be reset in this callback.
109-
m1 := bean.(*TestModel1)
110-
assert.EqualValues(t, i+1, m1.ID)
111-
112-
// here: XORM bug, it fails because the SQL becomes "WHERE id=-1", "WHERE id=-1 AND id=-2", "WHERE id=-1 AND id=-2 AND id=-3" ...
113-
// and it conflicts with the "Iterate"'s internal states.
114-
// has, err := db.GetEngine(ctx).Get(&TestModel2{ID: -m1.ID})
115-
116-
actualCount++
103+
t.Run("Show-XORM-Bug", func(t *testing.T) {
104+
actualCount := 0
105+
// here: db.GetEngine(t.Context()) is a new *Session created from *Engine
106+
_ = db.WithTx(t.Context(), func(ctx context.Context) error {
107+
_ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
108+
// here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false,
109+
// and the internal states (including "cond" and others) are always there and not be reset in this callback.
110+
m1 := bean.(*TestModel1)
111+
assert.EqualValues(t, i+1, m1.ID)
112+
113+
// here: XORM bug, it fails because the SQL becomes "WHERE id=-1", "WHERE id=-1 AND id=-2", "WHERE id=-1 AND id=-2 AND id=-3" ...
114+
// and it conflicts with the "Iterate"'s internal states.
115+
// has, err := db.GetEngine(ctx).Get(&TestModel2{ID: -m1.ID})
116+
117+
actualCount++
118+
return nil
119+
})
117120
return nil
118121
})
119-
return nil
122+
assert.Equal(t, testCount, actualCount)
120123
})
121-
assert.Equal(t, testCount, actualCount)
122124

123-
// deny the bad usages
124-
assert.PanicsWithError(t, "using database context in an iterator would cause corrupted results", func() {
125-
_ = unittest.GetXORMEngine().Iterate(&TestModel1{}, func(i int, bean any) error {
126-
_ = db.GetEngine(t.Context())
127-
return nil
125+
t.Run("DenyBadUsage", func(t *testing.T) {
126+
assert.PanicsWithError(t, "using session context in an iterator would cause corrupted results", func() {
127+
_ = db.WithTx(t.Context(), func(ctx context.Context) error {
128+
return db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
129+
_ = db.GetEngine(ctx)
130+
return nil
131+
})
132+
})
128133
})
129134
})
130135
}

models/db/engine.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"strings"
1313

1414
"xorm.io/xorm"
15-
"xorm.io/xorm/schemas"
1615

1716
_ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver
1817
_ "github.com/lib/pq" // Needed for the Postgresql driver
@@ -67,11 +66,6 @@ var (
6766
_ Engine = (*xorm.Session)(nil)
6867
)
6968

70-
// TableInfo returns table's information via an object
71-
func TableInfo(v any) (*schemas.Table, error) {
72-
return xormEngine.TableInfo(v)
73-
}
74-
7569
// RegisterModel registers model, if initFuncs provided, it will be invoked after data model sync
7670
func RegisterModel(bean any, initFunc ...func() error) {
7771
registeredModels = append(registeredModels, bean)

models/db/engine_init.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ func InitEngine(ctx context.Context) error {
8686
func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) {
8787
xormEngine = eng
8888
xormEngine.SetDefaultContext(ctx)
89-
xormContext = &xormContextType{Context: ctx, engine: xormEngine}
9089
}
9190

9291
// UnsetDefaultEngine closes and unsets the default engine
@@ -98,7 +97,6 @@ func UnsetDefaultEngine() {
9897
_ = xormEngine.Close()
9998
xormEngine = nil
10099
}
101-
xormContext = nil
102100
}
103101

104102
// InitEngineWithMigration initializes a new xorm.Engine and sets it as the XORM's default context

models/db/engine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func TestPrimaryKeys(t *testing.T) {
7070
}
7171

7272
for _, bean := range beans {
73-
table, err := db.TableInfo(bean)
73+
table, err := db.GetXORMEngineForTesting().TableInfo(bean)
7474
if err != nil {
7575
t.Fatal(err)
7676
}

models/db/index.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ type ResourceIndex struct {
1919
MaxIndex int64 `xorm:"index"`
2020
}
2121

22-
var (
23-
// ErrResouceOutdated represents an error when request resource outdated
24-
ErrResouceOutdated = errors.New("resource outdated")
25-
// ErrGetResourceIndexFailed represents an error when resource index retries 3 times
26-
ErrGetResourceIndexFailed = errors.New("get resource index failed")
27-
)
22+
var ErrGetResourceIndexFailed = errors.New("get resource index failed")
2823

2924
// SyncMaxResourceIndex sync the max index with the resource
3025
func SyncMaxResourceIndex(ctx context.Context, tableName string, groupID, maxIndex int64) (err error) {

0 commit comments

Comments
 (0)