Skip to content

Commit a8b8d32

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Remove duplicate empty repo check in delete branch API (go-gitea#32569) Optimize installation-page experience (go-gitea#32558) Remove unnecessary code (go-gitea#32560) Fix a compilation error in the Gitpod environment (go-gitea#32559) Use user.FullName in Oauth2 id_token response (go-gitea#32542) Fix some places which doesn't repsect org full name setting (go-gitea#32243) Refactor push mirror find and add check for updating push mirror (go-gitea#32539) Refactor markup render system (go-gitea#32533) Refactor find forks and fix possible bugs that weak permissions check (go-gitea#32528) Use better name for userinfo structure (go-gitea#32544)
2 parents 94a747f + 355889d commit a8b8d32

Some content is hidden

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

69 files changed

+929
-705
lines changed

flake.nix

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
poetry
3030

3131
# backend
32-
go_1_22
3332
gofumpt
3433
sqlite
3534
];

models/db/collation.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ func CheckCollations(x *xorm.Engine) (*CheckCollationsResult, error) {
6868

6969
var candidateCollations []string
7070
if x.Dialect().URI().DBType == schemas.MYSQL {
71-
if _, err = x.SQL("SELECT @@collation_database").Get(&res.DatabaseCollation); err != nil {
71+
_, err = x.SQL("SELECT DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?", setting.Database.Name).Get(&res.DatabaseCollation)
72+
if err != nil {
7273
return nil, err
7374
}
7475
res.IsCollationCaseSensitive = func(s string) bool {

models/repo/fork.go

-15
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,6 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
5454
return &forkedRepo, nil
5555
}
5656

57-
// GetForks returns all the forks of the repository
58-
func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) {
59-
sess := db.GetEngine(ctx)
60-
61-
var forks []*Repository
62-
if listOptions.Page == 0 {
63-
forks = make([]*Repository, 0, repo.NumForks)
64-
} else {
65-
forks = make([]*Repository, 0, listOptions.PageSize)
66-
sess = db.SetSessionPagination(sess, &listOptions)
67-
}
68-
69-
return forks, sess.Find(&forks, &Repository{ForkID: repo.ID})
70-
}
71-
7257
// IncrementRepoForkNum increment repository fork number
7358
func IncrementRepoForkNum(ctx context.Context, repoID int64) error {
7459
_, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", repoID)

models/repo/pushmirror.go

+34-16
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ import (
99

1010
"code.gitea.io/gitea/models/db"
1111
"code.gitea.io/gitea/modules/log"
12+
"code.gitea.io/gitea/modules/optional"
1213
"code.gitea.io/gitea/modules/timeutil"
1314
"code.gitea.io/gitea/modules/util"
1415

1516
"xorm.io/builder"
1617
)
1718

18-
// ErrPushMirrorNotExist mirror does not exist error
19-
var ErrPushMirrorNotExist = util.NewNotExistErrorf("PushMirror does not exist")
20-
2119
// PushMirror represents mirror information of a repository.
2220
type PushMirror struct {
2321
ID int64 `xorm:"pk autoincr"`
@@ -96,26 +94,46 @@ func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error {
9694
return util.NewInvalidArgumentErrorf("repoID required and must be set")
9795
}
9896

97+
type findPushMirrorOptions struct {
98+
db.ListOptions
99+
RepoID int64
100+
SyncOnCommit optional.Option[bool]
101+
}
102+
103+
func (opts findPushMirrorOptions) ToConds() builder.Cond {
104+
cond := builder.NewCond()
105+
if opts.RepoID > 0 {
106+
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
107+
}
108+
if opts.SyncOnCommit.Has() {
109+
cond = cond.And(builder.Eq{"sync_on_commit": opts.SyncOnCommit.Value()})
110+
}
111+
return cond
112+
}
113+
99114
// GetPushMirrorsByRepoID returns push-mirror information of a repository.
100115
func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*PushMirror, int64, error) {
101-
sess := db.GetEngine(ctx).Where("repo_id = ?", repoID)
102-
if listOptions.Page != 0 {
103-
sess = db.SetSessionPagination(sess, &listOptions)
104-
mirrors := make([]*PushMirror, 0, listOptions.PageSize)
105-
count, err := sess.FindAndCount(&mirrors)
106-
return mirrors, count, err
116+
return db.FindAndCount[PushMirror](ctx, findPushMirrorOptions{
117+
ListOptions: listOptions,
118+
RepoID: repoID,
119+
})
120+
}
121+
122+
func GetPushMirrorByIDAndRepoID(ctx context.Context, id, repoID int64) (*PushMirror, bool, error) {
123+
var pushMirror PushMirror
124+
has, err := db.GetEngine(ctx).Where("id = ?", id).And("repo_id = ?", repoID).Get(&pushMirror)
125+
if !has || err != nil {
126+
return nil, has, err
107127
}
108-
mirrors := make([]*PushMirror, 0, 10)
109-
count, err := sess.FindAndCount(&mirrors)
110-
return mirrors, count, err
128+
return &pushMirror, true, nil
111129
}
112130

113131
// GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
114132
func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) {
115-
mirrors := make([]*PushMirror, 0, 10)
116-
return mirrors, db.GetEngine(ctx).
117-
Where("repo_id = ? AND sync_on_commit = ?", repoID, true).
118-
Find(&mirrors)
133+
return db.Find[PushMirror](ctx, findPushMirrorOptions{
134+
RepoID: repoID,
135+
SyncOnCommit: optional.Some(true),
136+
})
119137
}
120138

121139
// PushMirrorsIterate iterates all push-mirror repositories.

models/repo/repo_list.go

+18-8
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,14 @@ func (repos RepositoryList) IDs() []int64 {
9898
return repoIDs
9999
}
100100

101-
// LoadAttributes loads the attributes for the given RepositoryList
102-
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
101+
func (repos RepositoryList) LoadOwners(ctx context.Context) error {
103102
if len(repos) == 0 {
104103
return nil
105104
}
106105

107106
userIDs := container.FilterSlice(repos, func(repo *Repository) (int64, bool) {
108107
return repo.OwnerID, true
109108
})
110-
repoIDs := make([]int64, len(repos))
111-
for i := range repos {
112-
repoIDs[i] = repos[i].ID
113-
}
114109

115110
// Load owners.
116111
users := make(map[int64]*user_model.User, len(userIDs))
@@ -123,12 +118,19 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
123118
for i := range repos {
124119
repos[i].Owner = users[repos[i].OwnerID]
125120
}
121+
return nil
122+
}
123+
124+
func (repos RepositoryList) LoadLanguageStats(ctx context.Context) error {
125+
if len(repos) == 0 {
126+
return nil
127+
}
126128

127129
// Load primary language.
128130
stats := make(LanguageStatList, 0, len(repos))
129131
if err := db.GetEngine(ctx).
130132
Where("`is_primary` = ? AND `language` != ?", true, "other").
131-
In("`repo_id`", repoIDs).
133+
In("`repo_id`", repos.IDs()).
132134
Find(&stats); err != nil {
133135
return fmt.Errorf("find primary languages: %w", err)
134136
}
@@ -141,10 +143,18 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
141143
}
142144
}
143145
}
144-
145146
return nil
146147
}
147148

149+
// LoadAttributes loads the attributes for the given RepositoryList
150+
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
151+
if err := repos.LoadOwners(ctx); err != nil {
152+
return err
153+
}
154+
155+
return repos.LoadLanguageStats(ctx)
156+
}
157+
148158
// SearchRepoOptions holds the search options
149159
type SearchRepoOptions struct {
150160
db.ListOptions

modules/html/html.go

-25
This file was deleted.

modules/htmlutil/html.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package htmlutil
5+
6+
import (
7+
"fmt"
8+
"html/template"
9+
"slices"
10+
)
11+
12+
// ParseSizeAndClass get size and class from string with default values
13+
// If present, "others" expects the new size first and then the classes to use
14+
func ParseSizeAndClass(defaultSize int, defaultClass string, others ...any) (int, string) {
15+
size := defaultSize
16+
if len(others) >= 1 {
17+
if v, ok := others[0].(int); ok && v != 0 {
18+
size = v
19+
}
20+
}
21+
class := defaultClass
22+
if len(others) >= 2 {
23+
if v, ok := others[1].(string); ok && v != "" {
24+
if class != "" {
25+
class += " "
26+
}
27+
class += v
28+
}
29+
}
30+
return size, class
31+
}
32+
33+
func HTMLFormat(s string, rawArgs ...any) template.HTML {
34+
args := slices.Clone(rawArgs)
35+
for i, v := range args {
36+
switch v := v.(type) {
37+
case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
38+
// for most basic types (including template.HTML which is safe), just do nothing and use it
39+
case string:
40+
args[i] = template.HTMLEscapeString(v)
41+
case fmt.Stringer:
42+
args[i] = template.HTMLEscapeString(v.String())
43+
default:
44+
args[i] = template.HTMLEscapeString(fmt.Sprint(v))
45+
}
46+
}
47+
return template.HTML(fmt.Sprintf(s, args...))
48+
}

modules/htmlutil/html_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package htmlutil
5+
6+
import (
7+
"html/template"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestHTMLFormat(t *testing.T) {
14+
assert.Equal(t, template.HTML("<a>&lt; < 1</a>"), HTMLFormat("<a>%s %s %d</a>", "<", template.HTML("<"), 1))
15+
}

modules/markup/asciicast/asciicast.go

+2-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"io"
99
"net/url"
10-
"regexp"
1110

1211
"code.gitea.io/gitea/modules/markup"
1312
"code.gitea.io/gitea/modules/setting"
@@ -38,10 +37,7 @@ const (
3837

3938
// SanitizerRules implements markup.Renderer
4039
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
41-
return []setting.MarkupSanitizerRule{
42-
{Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)},
43-
{Element: "div", AllowAttr: playerSrcAttr},
44-
}
40+
return []setting.MarkupSanitizerRule{{Element: "div", AllowAttr: playerSrcAttr}}
4541
}
4642

4743
// Render implements markup.Renderer
@@ -53,12 +49,5 @@ func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer)
5349
ctx.Metas["BranchNameSubURL"],
5450
url.PathEscape(ctx.RelativePath),
5551
)
56-
57-
_, err := io.WriteString(output, fmt.Sprintf(
58-
`<div class="%s" %s="%s"></div>`,
59-
playerClassName,
60-
playerSrcAttr,
61-
rawURL,
62-
))
63-
return err
52+
return ctx.RenderInternal.FormatWithSafeAttrs(output, `<div class="%s" %s="%s"></div>`, playerClassName, playerSrcAttr, rawURL)
6453
}

modules/markup/common/html.go

-16
This file was deleted.

modules/markup/common/linkify.go

+15-3
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,27 @@ package common
99
import (
1010
"bytes"
1111
"regexp"
12+
"sync"
1213

1314
"github.com/yuin/goldmark"
1415
"github.com/yuin/goldmark/ast"
1516
"github.com/yuin/goldmark/parser"
1617
"github.com/yuin/goldmark/text"
1718
"github.com/yuin/goldmark/util"
19+
"mvdan.cc/xurls/v2"
1820
)
1921

20-
var wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}((?:/|[#?])[-a-zA-Z0-9@:%_\+.~#!?&//=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
22+
type GlobalVarsType struct {
23+
wwwURLRegxp *regexp.Regexp
24+
LinkRegex *regexp.Regexp // fast matching a URL link, no any extra validation.
25+
}
26+
27+
var GlobalVars = sync.OnceValue[*GlobalVarsType](func() *GlobalVarsType {
28+
v := &GlobalVarsType{}
29+
v.wwwURLRegxp = regexp.MustCompile(`^www\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}((?:/|[#?])[-a-zA-Z0-9@:%_\+.~#!?&//=\(\);,'">\^{}\[\]` + "`" + `]*)?`)
30+
v.LinkRegex, _ = xurls.StrictMatchingScheme("https?://")
31+
return v
32+
})
2133

2234
type linkifyParser struct{}
2335

@@ -60,10 +72,10 @@ func (s *linkifyParser) Parse(parent ast.Node, block text.Reader, pc parser.Cont
6072
var protocol []byte
6173
typ := ast.AutoLinkURL
6274
if bytes.HasPrefix(line, protoHTTP) || bytes.HasPrefix(line, protoHTTPS) || bytes.HasPrefix(line, protoFTP) {
63-
m = LinkRegex.FindSubmatchIndex(line)
75+
m = GlobalVars().LinkRegex.FindSubmatchIndex(line)
6476
}
6577
if m == nil && bytes.HasPrefix(line, domainWWW) {
66-
m = wwwURLRegxp.FindSubmatchIndex(line)
78+
m = GlobalVars().wwwURLRegxp.FindSubmatchIndex(line)
6779
protocol = []byte("http")
6880
}
6981
if m != nil {

modules/markup/console/console.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ package console
66
import (
77
"bytes"
88
"io"
9-
"path/filepath"
10-
"regexp"
9+
"path"
1110

1211
"code.gitea.io/gitea/modules/markup"
1312
"code.gitea.io/gitea/modules/setting"
@@ -36,7 +35,7 @@ func (Renderer) Extensions() []string {
3635
// SanitizerRules implements markup.Renderer
3736
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
3837
return []setting.MarkupSanitizerRule{
39-
{Element: "span", AllowAttr: "class", Regexp: regexp.MustCompile(`^term-((fg[ix]?|bg)\d+|container)$`)},
38+
{Element: "span", AllowAttr: "class", Regexp: `^term-((fg[ix]?|bg)\d+|container)$`},
4039
}
4140
}
4241

@@ -46,7 +45,7 @@ func (Renderer) CanRender(filename string, input io.Reader) bool {
4645
if err != nil {
4746
return false
4847
}
49-
if enry.GetLanguage(filepath.Base(filename), buf) != enry.OtherLanguage {
48+
if enry.GetLanguage(path.Base(filename), buf) != enry.OtherLanguage {
5049
return false
5150
}
5251
return bytes.ContainsRune(buf, '\x1b')

0 commit comments

Comments
 (0)