Skip to content

Commit 5600f34

Browse files
committed
Merge remote-tracking branch 'origin/main' into types-4
* origin/main: (21 commits) Fix toAbsoluteLocaleDate and add more tests (go-gitea#32387) Respect UI.ExploreDefaultSort setting again (go-gitea#32357) Fix absolute-date (go-gitea#32375) Fix undefined errors on Activity page (go-gitea#32378) Add new [lfs_client].BATCH_SIZE and [server].LFS_MAX_BATCH_SIZE config settings. (go-gitea#32307) remove unused call to $.HeadRepo in view_title template (go-gitea#32317) Fix clean tmp dir (go-gitea#32360) Optimize branch protection rule loading (go-gitea#32280) Suggestions for issues (go-gitea#32327) Migrate vue components to setup (go-gitea#32329) Fix db engine (go-gitea#32351) Refactor the DB migration system slightly (go-gitea#32344) Fix broken image when editing comment with non-image attachments (go-gitea#32319) Fix disable 2fa bug (go-gitea#32320) Upgrade rollup to 4.24.0 (go-gitea#32312) Upgrade vue to 3.5.12 (go-gitea#32311) Make admins adhere to branch protection rules (go-gitea#32248) Prevent from submitting issue/comment on uploading (go-gitea#32263) Add warn log when deleting inactive users (go-gitea#32318) Add `DISABLE_ORGANIZATIONS_PAGE` and `DISABLE_CODE_PAGE` settings for explore pages and fix an issue related to user search (go-gitea#32288) ...
2 parents b78cbd6 + aee9801 commit 5600f34

File tree

82 files changed

+2058
-1738
lines changed

Some content is hidden

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

82 files changed

+2058
-1738
lines changed

cmd/admin_auth_ldap.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
386386
return a.createAuthSource(ctx, authSource)
387387
}
388388

389-
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
389+
// updateLdapSimpleAuth updates a new LDAP (simple auth) authentication source.
390390
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
391391
ctx, cancel := installSignals()
392392
defer cancel()

custom/conf/app.example.ini

+26
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ RUN_USER = ; git
324324
;; Maximum number of locks returned per page
325325
;LFS_LOCKS_PAGING_NUM = 50
326326
;;
327+
;; When clients make lfs batch requests, reject them if there are more pointers than this number
328+
;; zero means 'unlimited'
329+
;LFS_MAX_BATCH_SIZE = 0
330+
;;
327331
;; Allow graceful restarts using SIGHUP to fork
328332
;ALLOW_GRACEFUL_RESTARTS = true
329333
;;
@@ -907,6 +911,24 @@ LEVEL = Info
907911
;; Valid site url schemes for user profiles
908912
;VALID_SITE_URL_SCHEMES=http,https
909913

914+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
915+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
916+
;[service.explore]
917+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
918+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
919+
;;
920+
;; Only allow signed in users to view the explore pages.
921+
;REQUIRE_SIGNIN_VIEW = false
922+
;;
923+
;; Disable the users explore page.
924+
;DISABLE_USERS_PAGE = false
925+
;;
926+
;; Disable the organizations explore page.
927+
;DISABLE_ORGANIZATIONS_PAGE = false
928+
;;
929+
;; Disable the code explore page.
930+
;DISABLE_CODE_PAGE = false
931+
;;
910932

911933
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
912934
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2620,6 +2642,10 @@ LEVEL = Info
26202642
;; override the azure blob base path if storage type is azureblob
26212643
;AZURE_BLOB_BASE_PATH = lfs/
26222644

2645+
;[lfs_client]
2646+
;; When mirroring an upstream lfs endpoint, limit the number of pointers in each batch request to this number
2647+
;BATCH_SIZE = 20
2648+
26232649
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26242650
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26252651
;; settings for packages, will override storage setting

models/db/context.go

+67-47
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ package db
66
import (
77
"context"
88
"database/sql"
9+
"errors"
10+
"runtime"
11+
"slices"
12+
"sync"
13+
14+
"code.gitea.io/gitea/modules/setting"
915

1016
"xorm.io/builder"
1117
"xorm.io/xorm"
@@ -15,76 +21,90 @@ import (
1521
// will be overwritten by Init with HammerContext
1622
var DefaultContext context.Context
1723

18-
// contextKey is a value for use with context.WithValue.
19-
type contextKey struct {
20-
name string
21-
}
24+
type engineContextKeyType struct{}
2225

23-
// enginedContextKey is a context key. It is used with context.Value() to get the current Engined for the context
24-
var (
25-
enginedContextKey = &contextKey{"engined"}
26-
_ Engined = &Context{}
27-
)
26+
var engineContextKey = engineContextKeyType{}
2827

2928
// Context represents a db context
3029
type Context struct {
3130
context.Context
32-
e Engine
33-
transaction bool
34-
}
35-
36-
func newContext(ctx context.Context, e Engine, transaction bool) *Context {
37-
return &Context{
38-
Context: ctx,
39-
e: e,
40-
transaction: transaction,
41-
}
42-
}
43-
44-
// InTransaction if context is in a transaction
45-
func (ctx *Context) InTransaction() bool {
46-
return ctx.transaction
31+
engine Engine
4732
}
4833

49-
// Engine returns db engine
50-
func (ctx *Context) Engine() Engine {
51-
return ctx.e
34+
func newContext(ctx context.Context, e Engine) *Context {
35+
return &Context{Context: ctx, engine: e}
5236
}
5337

5438
// Value shadows Value for context.Context but allows us to get ourselves and an Engined object
5539
func (ctx *Context) Value(key any) any {
56-
if key == enginedContextKey {
40+
if key == engineContextKey {
5741
return ctx
5842
}
5943
return ctx.Context.Value(key)
6044
}
6145

6246
// WithContext returns this engine tied to this context
6347
func (ctx *Context) WithContext(other context.Context) *Context {
64-
return newContext(ctx, ctx.e.Context(other), ctx.transaction)
48+
return newContext(ctx, ctx.engine.Context(other))
6549
}
6650

67-
// Engined structs provide an Engine
68-
type Engined interface {
69-
Engine() Engine
51+
var (
52+
contextSafetyOnce sync.Once
53+
contextSafetyDeniedFuncPCs []uintptr
54+
)
55+
56+
func contextSafetyCheck(e Engine) {
57+
if setting.IsProd && !setting.IsInTesting {
58+
return
59+
}
60+
if e == nil {
61+
return
62+
}
63+
// Only do this check for non-end-users. If the problem could be fixed in the future, this code could be removed.
64+
contextSafetyOnce.Do(func() {
65+
// try to figure out the bad functions to deny
66+
type m struct{}
67+
_ = e.SQL("SELECT 1").Iterate(&m{}, func(int, any) error {
68+
callers := make([]uintptr, 32)
69+
callerNum := runtime.Callers(1, callers)
70+
for i := 0; i < callerNum; i++ {
71+
if funcName := runtime.FuncForPC(callers[i]).Name(); funcName == "xorm.io/xorm.(*Session).Iterate" {
72+
contextSafetyDeniedFuncPCs = append(contextSafetyDeniedFuncPCs, callers[i])
73+
}
74+
}
75+
return nil
76+
})
77+
if len(contextSafetyDeniedFuncPCs) != 1 {
78+
panic(errors.New("unable to determine the functions to deny"))
79+
}
80+
})
81+
82+
// it should be very fast: xxxx ns/op
83+
callers := make([]uintptr, 32)
84+
callerNum := runtime.Callers(3, callers) // skip 3: runtime.Callers, contextSafetyCheck, GetEngine
85+
for i := 0; i < callerNum; i++ {
86+
if slices.Contains(contextSafetyDeniedFuncPCs, callers[i]) {
87+
panic(errors.New("using database context in an iterator would cause corrupted results"))
88+
}
89+
}
7090
}
7191

72-
// GetEngine will get a db Engine from this context or return an Engine restricted to this context
92+
// GetEngine gets an existing db Engine/Statement or creates a new Session
7393
func GetEngine(ctx context.Context) Engine {
74-
if e := getEngine(ctx); e != nil {
94+
if e := getExistingEngine(ctx); e != nil {
7595
return e
7696
}
7797
return x.Context(ctx)
7898
}
7999

80-
// getEngine will get a db Engine from this context or return nil
81-
func getEngine(ctx context.Context) Engine {
82-
if engined, ok := ctx.(Engined); ok {
83-
return engined.Engine()
100+
// getExistingEngine gets an existing db Engine/Statement from this context or returns nil
101+
func getExistingEngine(ctx context.Context) (e Engine) {
102+
defer func() { contextSafetyCheck(e) }()
103+
if engined, ok := ctx.(*Context); ok {
104+
return engined.engine
84105
}
85-
enginedInterface := ctx.Value(enginedContextKey)
86-
if enginedInterface != nil {
87-
return enginedInterface.(Engined).Engine()
106+
if engined, ok := ctx.Value(engineContextKey).(*Context); ok {
107+
return engined.engine
88108
}
89109
return nil
90110
}
@@ -132,23 +152,23 @@ func (c *halfCommitter) Close() error {
132152
// d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback.
133153
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
134154
if sess, ok := inTransaction(parentCtx); ok {
135-
return newContext(parentCtx, sess, true), &halfCommitter{committer: sess}, nil
155+
return newContext(parentCtx, sess), &halfCommitter{committer: sess}, nil
136156
}
137157

138158
sess := x.NewSession()
139159
if err := sess.Begin(); err != nil {
140-
sess.Close()
160+
_ = sess.Close()
141161
return nil, nil, err
142162
}
143163

144-
return newContext(DefaultContext, sess, true), sess, nil
164+
return newContext(DefaultContext, sess), sess, nil
145165
}
146166

147167
// WithTx represents executing database operations on a transaction, if the transaction exist,
148168
// this function will reuse it otherwise will create a new one and close it when finished.
149169
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error {
150170
if sess, ok := inTransaction(parentCtx); ok {
151-
err := f(newContext(parentCtx, sess, true))
171+
err := f(newContext(parentCtx, sess))
152172
if err != nil {
153173
// rollback immediately, in case the caller ignores returned error and tries to commit the transaction.
154174
_ = sess.Close()
@@ -165,7 +185,7 @@ func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error)
165185
return err
166186
}
167187

168-
if err := f(newContext(parentCtx, sess, true)); err != nil {
188+
if err := f(newContext(parentCtx, sess)); err != nil {
169189
return err
170190
}
171191

@@ -312,7 +332,7 @@ func InTransaction(ctx context.Context) bool {
312332
}
313333

314334
func inTransaction(ctx context.Context) (*xorm.Session, bool) {
315-
e := getEngine(ctx)
335+
e := getExistingEngine(ctx)
316336
if e == nil {
317337
return nil, false
318338
}

models/db/context_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,47 @@ func TestTxContext(t *testing.T) {
8484
}))
8585
}
8686
}
87+
88+
func TestContextSafety(t *testing.T) {
89+
type TestModel1 struct {
90+
ID int64
91+
}
92+
type TestModel2 struct {
93+
ID int64
94+
}
95+
assert.NoError(t, unittest.GetXORMEngine().Sync(&TestModel1{}, &TestModel2{}))
96+
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &TestModel1{}, &TestModel2{}))
97+
testCount := 10
98+
for i := 1; i <= testCount; i++ {
99+
assert.NoError(t, db.Insert(db.DefaultContext, &TestModel1{ID: int64(i)}))
100+
assert.NoError(t, db.Insert(db.DefaultContext, &TestModel2{ID: int64(-i)}))
101+
}
102+
103+
actualCount := 0
104+
// here: db.GetEngine(db.DefaultContext) is a new *Session created from *Engine
105+
_ = db.WithTx(db.DefaultContext, 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++
117+
return nil
118+
})
119+
return nil
120+
})
121+
assert.EqualValues(t, testCount, actualCount)
122+
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(db.DefaultContext)
127+
return nil
128+
})
129+
})
130+
}

models/db/engine.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,7 @@ func InitEngine(ctx context.Context) error {
161161
// SetDefaultEngine sets the default engine for db
162162
func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) {
163163
x = eng
164-
DefaultContext = &Context{
165-
Context: ctx,
166-
e: x,
167-
}
164+
DefaultContext = &Context{Context: ctx, engine: x}
168165
}
169166

170167
// UnsetDefaultEngine closes and unsets the default engine

models/db/install/db.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func getXORMEngine() *xorm.Engine {
14-
return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine)
14+
return db.GetEngine(db.DefaultContext).(*xorm.Engine)
1515
}
1616

1717
// CheckDatabaseConnection checks the database connection

models/db/iterate.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"xorm.io/builder"
1212
)
1313

14-
// Iterate iterate all the Bean object
14+
// Iterate iterates all the Bean object
1515
func Iterate[Bean any](ctx context.Context, cond builder.Cond, f func(ctx context.Context, bean *Bean) error) error {
1616
var start int
1717
batchSize := setting.Database.IterateBufferSize

models/git/protected_branch.go

+15-8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type ProtectedBranch struct {
6363
RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"`
6464
ProtectedFilePatterns string `xorm:"TEXT"`
6565
UnprotectedFilePatterns string `xorm:"TEXT"`
66+
BlockAdminMergeOverride bool `xorm:"NOT NULL DEFAULT false"`
6667

6768
CreatedUnix timeutil.TimeStamp `xorm:"created"`
6869
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
@@ -83,14 +84,20 @@ func IsRuleNameSpecial(ruleName string) bool {
8384
}
8485

8586
func (protectBranch *ProtectedBranch) loadGlob() {
86-
if protectBranch.globRule == nil {
87-
var err error
88-
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
89-
if err != nil {
90-
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
91-
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
92-
}
93-
protectBranch.isPlainName = !IsRuleNameSpecial(protectBranch.RuleName)
87+
if protectBranch.isPlainName || protectBranch.globRule != nil {
88+
return
89+
}
90+
// detect if it is not glob
91+
if !IsRuleNameSpecial(protectBranch.RuleName) {
92+
protectBranch.isPlainName = true
93+
return
94+
}
95+
// now we load the glob
96+
var err error
97+
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
98+
if err != nil {
99+
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
100+
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
94101
}
95102
}
96103

models/git/protected_banch_list_test.go models/git/protected_branch_list_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,32 @@ func TestBranchRuleMatchPriority(t *testing.T) {
7474
}
7575
}
7676
}
77+
78+
func TestBranchRuleSort(t *testing.T) {
79+
in := []*ProtectedBranch{{
80+
RuleName: "b",
81+
CreatedUnix: 1,
82+
}, {
83+
RuleName: "b/*",
84+
CreatedUnix: 3,
85+
}, {
86+
RuleName: "a/*",
87+
CreatedUnix: 2,
88+
}, {
89+
RuleName: "c",
90+
CreatedUnix: 0,
91+
}, {
92+
RuleName: "a",
93+
CreatedUnix: 4,
94+
}}
95+
expect := []string{"c", "b", "a", "a/*", "b/*"}
96+
97+
pbr := ProtectedBranchRules(in)
98+
pbr.sort()
99+
100+
var got []string
101+
for i := range pbr {
102+
got = append(got, pbr[i].RuleName)
103+
}
104+
assert.Equal(t, expect, got)
105+
}

0 commit comments

Comments
 (0)