Skip to content

Commit 5b202b3

Browse files
committed
Merge remote-tracking branch 'upstream/main'
* upstream/main: Start using template context function (go-gitea#26254) Allow package cleanup from admin page (go-gitea#25307) Fix text truncate (go-gitea#26354) Fix incorrect sort link with `.profile` repository (go-gitea#26374) Use more `IssueList` instead of `[]*Issue` (go-gitea#26369) Rename code_langauge.go to code_language.go (go-gitea#26377) Add changelog for 1.20.3 (go-gitea#26373) Do not highlight `#number` in documents (go-gitea#26365) Bypass MariaDB performance bug of the "IN" sub-query, fix incorrect IssueIndex (go-gitea#26279) Fix nil pointer dereference error when open link with invalid pull index (go-gitea#26353)
2 parents 531a513 + 6913053 commit 5b202b3

35 files changed

+336
-90
lines changed

CHANGELOG.md

+32-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,38 @@
22

33
This changelog goes through all the changes that have been made in each release
44
without substantial changes to our git log; to see the highlights of what has
5-
been added to each release, please refer to the [blog](https://blog.gitea.io).
5+
been added to each release, please refer to the [blog](https://blog.gitea.com).
66

7-
## [1.20.2](https://github.com/go-gitea/gitea/releases/tag/1.20.2) - 2023-07-29
7+
## [1.20.3](https://github.com/go-gitea/gitea/releases/tag/v1.20.3) - 2023-08-07
8+
9+
* BREAKING
10+
* Fix the wrong derive path (#26271) (#26318)
11+
* SECURITY
12+
* Fix API leaking Usermail if not logged in (#25097) (#26350)
13+
* ENHANCEMENTS
14+
* Display human-readable text instead of cryptic filemodes (#26352) (#26358)
15+
* Hide `last indexed SHA` when a repo could not be indexed yet (#26340) (#26345)
16+
* Fix the topic validation rule and suport dots (#26286) (#26303)
17+
* Fix due date rendering the wrong date in issue (#26268) (#26274)
18+
* Don't autosize textarea in diff view (#26233) (#26244)
19+
* Fix commit compare style (#26209) (#26226)
20+
* Warn instead of reporting an error when a webhook cannot be found (#26039) (#26211)
21+
* BUGFIXES
22+
* Bypass MariaDB performance bug of the "IN" sub-query, fix incorrect IssueIndex (#26279) (#26368)
23+
* Fix incorrect CLI exit code and duplicate error message (#26346) (#26347)
24+
* Prevent newline errors with Debian packages (#26332) (#26342)
25+
* Fix bug with sqlite load read (#26305) (#26339)
26+
* Make git batch operations use parent context timeout instead of default timeout (#26325) (#26330)
27+
* Support getting changed files when commit ID is `EmptySHA` (#26290) (#26316)
28+
* Clarify the logger's MODE config option (#26267) (#26281)
29+
* Use shared template for webhook icons (#26242) (#26246)
30+
* Fix pull request check list is limited (#26179) (#26245)
31+
* Fix attachment clipboard copy on insecure origin (#26224) (#26231)
32+
* Fix access check for org-level project (#26182) (#26223)
33+
* MISC
34+
* Upgrade x/net to 0.13.0 (#26301)
35+
36+
## [1.20.2](https://github.com/go-gitea/gitea/releases/tag/v1.20.2) - 2023-07-29
837

938
* ENHANCEMENTS
1039
* Calculate MAX_WORKERS default value by CPU number (#26177) (#26183)
@@ -32,7 +61,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
3261
* Fix wrong workflow status when rerun a job in an already finished workflow (#26119) (#26124)
3362
* Fix duplicated url prefix on issue context menu (#26066) (#26067)
3463

35-
## [1.20.1](https://github.com/go-gitea/gitea/releases/tag/1.20.1) - 2023-07-22
64+
## [1.20.1](https://github.com/go-gitea/gitea/releases/tag/v1.20.1) - 2023-07-22
3665

3766
* SECURITY
3867
* Disallow dangerous URL schemes (#25960) (#25964)

models/activities/action.go

+24-8
Original file line numberDiff line numberDiff line change
@@ -685,18 +685,34 @@ func NotifyWatchersActions(acts []*Action) error {
685685
}
686686

687687
// DeleteIssueActions delete all actions related with issueID
688-
func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error {
688+
func DeleteIssueActions(ctx context.Context, repoID, issueID, issueIndex int64) error {
689689
// delete actions assigned to this issue
690-
subQuery := builder.Select("`id`").
691-
From("`comment`").
692-
Where(builder.Eq{"`issue_id`": issueID})
693-
if _, err := db.GetEngine(ctx).In("comment_id", subQuery).Delete(&Action{}); err != nil {
694-
return err
690+
e := db.GetEngine(ctx)
691+
692+
// MariaDB has a performance bug: https://jira.mariadb.org/browse/MDEV-16289
693+
// so here it uses "DELETE ... WHERE IN" with pre-queried IDs.
694+
var lastCommentID int64
695+
commentIDs := make([]int64, 0, db.DefaultMaxInSize)
696+
for {
697+
commentIDs = commentIDs[:0]
698+
err := e.Select("`id`").Table(&issues_model.Comment{}).
699+
Where(builder.Eq{"issue_id": issueID}).And("`id` > ?", lastCommentID).
700+
OrderBy("`id`").Limit(db.DefaultMaxInSize).
701+
Find(&commentIDs)
702+
if err != nil {
703+
return err
704+
} else if len(commentIDs) == 0 {
705+
break
706+
} else if _, err = db.GetEngine(ctx).In("comment_id", commentIDs).Delete(&Action{}); err != nil {
707+
return err
708+
} else {
709+
lastCommentID = commentIDs[len(commentIDs)-1]
710+
}
695711
}
696712

697-
_, err := db.GetEngine(ctx).Table("action").Where("repo_id = ?", repoID).
713+
_, err := e.Where("repo_id = ?", repoID).
698714
In("op_type", ActionCreateIssue, ActionCreatePullRequest).
699-
Where("content LIKE ?", strconv.FormatInt(issueID, 10)+"|%").
715+
Where("content LIKE ?", strconv.FormatInt(issueIndex, 10)+"|%"). // "IssueIndex|content..."
700716
Delete(&Action{})
701717
return err
702718
}

models/activities/action_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package activities_test
55

66
import (
7+
"fmt"
78
"path"
89
"testing"
910

@@ -284,3 +285,36 @@ func TestConsistencyUpdateAction(t *testing.T) {
284285
assert.NoError(t, db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions))
285286
unittest.CheckConsistencyFor(t, &activities_model.Action{})
286287
}
288+
289+
func TestDeleteIssueActions(t *testing.T) {
290+
assert.NoError(t, unittest.PrepareTestDatabase())
291+
292+
// load an issue
293+
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 4})
294+
assert.NotEqualValues(t, issue.ID, issue.Index) // it needs to use different ID/Index to test the DeleteIssueActions to delete some actions by IssueIndex
295+
296+
// insert a comment
297+
err := db.Insert(db.DefaultContext, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
298+
assert.NoError(t, err)
299+
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
300+
301+
// truncate action table and insert some actions
302+
err = db.TruncateBeans(db.DefaultContext, &activities_model.Action{})
303+
assert.NoError(t, err)
304+
err = db.Insert(db.DefaultContext, &activities_model.Action{
305+
OpType: activities_model.ActionCommentIssue,
306+
CommentID: comment.ID,
307+
})
308+
assert.NoError(t, err)
309+
err = db.Insert(db.DefaultContext, &activities_model.Action{
310+
OpType: activities_model.ActionCreateIssue,
311+
RepoID: issue.RepoID,
312+
Content: fmt.Sprintf("%d|content...", issue.Index),
313+
})
314+
assert.NoError(t, err)
315+
316+
// assert that the actions exist, then delete them
317+
unittest.AssertCount(t, &activities_model.Action{}, 2)
318+
assert.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index))
319+
unittest.AssertCount(t, &activities_model.Action{}, 0)
320+
}

models/issues/issue.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,8 @@ func (issue *Issue) MovePin(ctx context.Context, newPosition int) error {
854854
}
855855

856856
// GetPinnedIssues returns the pinned Issues for the given Repo and type
857-
func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) ([]*Issue, error) {
858-
issues := make([]*Issue, 0)
857+
func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) (IssueList, error) {
858+
issues := make(IssueList, 0)
859859

860860
err := db.GetEngine(ctx).
861861
Table("issue").
@@ -868,7 +868,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) ([]*Issue,
868868
return nil, err
869869
}
870870

871-
err = IssueList(issues).LoadAttributes(ctx)
871+
err = issues.LoadAttributes(ctx)
872872
if err != nil {
873873
return nil, err
874874
}

models/issues/issue_project.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (issue *Issue) projectBoardID(ctx context.Context) int64 {
5353

5454
// LoadIssuesFromBoard load issues assigned to this board
5555
func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) {
56-
issueList := make([]*Issue, 0, 10)
56+
issueList := make(IssueList, 0, 10)
5757

5858
if b.ID != 0 {
5959
issues, err := Issues(ctx, &IssuesOptions{
@@ -79,7 +79,7 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList
7979
issueList = append(issueList, issues...)
8080
}
8181

82-
if err := IssueList(issueList).LoadComments(ctx); err != nil {
82+
if err := issueList.LoadComments(ctx); err != nil {
8383
return nil, err
8484
}
8585

models/issues/issue_search.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]i
441441
}
442442

443443
// Issues returns a list of issues by given conditions.
444-
func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) {
444+
func Issues(ctx context.Context, opts *IssuesOptions) (IssueList, error) {
445445
sess := db.GetEngine(ctx).
446446
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
447447
applyLimit(sess, opts)
File renamed without changes.

modules/context/context.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package context
66

77
import (
8+
"context"
89
"html"
910
"html/template"
1011
"io"
@@ -31,14 +32,16 @@ import (
3132

3233
// Render represents a template render
3334
type Render interface {
34-
TemplateLookup(tmpl string) (templates.TemplateExecutor, error)
35-
HTML(w io.Writer, status int, name string, data any) error
35+
TemplateLookup(tmpl string, templateCtx context.Context) (templates.TemplateExecutor, error)
36+
HTML(w io.Writer, status int, name string, data any, templateCtx context.Context) error
3637
}
3738

3839
// Context represents context of a request.
3940
type Context struct {
4041
*Base
4142

43+
TemplateContext TemplateContext
44+
4245
Render Render
4346
PageData map[string]any // data used by JavaScript modules in one page, it's `window.config.pageData`
4447

@@ -60,6 +63,8 @@ type Context struct {
6063
Package *Package
6164
}
6265

66+
type TemplateContext map[string]any
67+
6368
func init() {
6469
web.RegisterResponseStatusProvider[*Context](func(req *http.Request) web_types.ResponseStatusProvider {
6570
return req.Context().Value(WebContextKey).(*Context)
@@ -133,8 +138,12 @@ func Contexter() func(next http.Handler) http.Handler {
133138
}
134139
defer baseCleanUp()
135140

141+
// TODO: "install.go" also shares the same logic, which should be refactored to a general function
142+
ctx.TemplateContext = NewTemplateContext(ctx)
143+
ctx.TemplateContext["Locale"] = ctx.Locale
144+
136145
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
137-
ctx.Data["Context"] = &ctx
146+
ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
138147
ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI()
139148
ctx.Data["Link"] = ctx.Link
140149
ctx.Data["locale"] = ctx.Locale

modules/context/context_response.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
7575
return strconv.FormatInt(time.Since(tmplStartTime).Nanoseconds()/1e6, 10) + "ms"
7676
}
7777

78-
err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data)
78+
err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data, ctx.TemplateContext)
7979
if err == nil {
8080
return
8181
}
@@ -93,7 +93,7 @@ func (ctx *Context) HTML(status int, name base.TplName) {
9393
// RenderToString renders the template content to a string
9494
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
9595
var buf strings.Builder
96-
err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data)
96+
err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data, ctx.TemplateContext)
9797
return buf.String(), err
9898
}
9999

modules/context/context_template.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package context
5+
6+
import (
7+
"context"
8+
"errors"
9+
"time"
10+
11+
"code.gitea.io/gitea/modules/log"
12+
)
13+
14+
var _ context.Context = TemplateContext(nil)
15+
16+
func NewTemplateContext(ctx context.Context) TemplateContext {
17+
return TemplateContext{"_ctx": ctx}
18+
}
19+
20+
func (c TemplateContext) parentContext() context.Context {
21+
return c["_ctx"].(context.Context)
22+
}
23+
24+
func (c TemplateContext) Deadline() (deadline time.Time, ok bool) {
25+
return c.parentContext().Deadline()
26+
}
27+
28+
func (c TemplateContext) Done() <-chan struct{} {
29+
return c.parentContext().Done()
30+
}
31+
32+
func (c TemplateContext) Err() error {
33+
return c.parentContext().Err()
34+
}
35+
36+
func (c TemplateContext) Value(key any) any {
37+
return c.parentContext().Value(key)
38+
}
39+
40+
// DataRaceCheck checks whether the template context function "ctx()" returns the consistent context
41+
// as the current template's rendering context (request context), to help to find data race issues as early as possible.
42+
// When the code is proven to be correct and stable, this function should be removed.
43+
func (c TemplateContext) DataRaceCheck(dataCtx context.Context) (string, error) {
44+
if c.parentContext() != dataCtx {
45+
log.Error("TemplateContext.DataRaceCheck: parent context mismatch\n%s", log.Stack(2))
46+
return "", errors.New("parent context mismatch")
47+
}
48+
return "", nil
49+
}

modules/markup/html.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
852852
}
853853

854854
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
855-
if ctx.Metas == nil {
855+
if ctx.Metas == nil || ctx.Metas["mode"] == "document" {
856856
return
857857
}
858858
var (

modules/markup/html_internal_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,30 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
262262
})
263263
}
264264

265+
func TestRender_IssueIndexPattern_Document(t *testing.T) {
266+
setting.AppURL = TestAppURL
267+
metas := map[string]string{
268+
"format": "https://someurl.com/{user}/{repo}/{index}",
269+
"user": "someUser",
270+
"repo": "someRepo",
271+
"style": IssueNameStyleNumeric,
272+
"mode": "document",
273+
}
274+
275+
testRenderIssueIndexPattern(t, "#1", "#1", &RenderContext{
276+
Ctx: git.DefaultContext,
277+
Metas: metas,
278+
})
279+
testRenderIssueIndexPattern(t, "#1312", "#1312", &RenderContext{
280+
Ctx: git.DefaultContext,
281+
Metas: metas,
282+
})
283+
testRenderIssueIndexPattern(t, "!1", "!1", &RenderContext{
284+
Ctx: git.DefaultContext,
285+
Metas: metas,
286+
})
287+
}
288+
265289
func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *RenderContext) {
266290
if ctx.URLPrefix == "" {
267291
ctx.URLPrefix = TestAppURL

modules/markup/html_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,42 @@ func Test_ParseClusterFuzz(t *testing.T) {
529529
assert.NotContains(t, res.String(), "<html")
530530
}
531531

532+
func TestPostProcess_RenderDocument(t *testing.T) {
533+
setting.AppURL = TestAppURL
534+
535+
localMetas := map[string]string{
536+
"user": "go-gitea",
537+
"repo": "gitea",
538+
"mode": "document",
539+
}
540+
541+
test := func(input, expected string) {
542+
var res strings.Builder
543+
err := PostProcess(&RenderContext{
544+
Ctx: git.DefaultContext,
545+
URLPrefix: "https://example.com",
546+
Metas: localMetas,
547+
}, strings.NewReader(input), &res)
548+
assert.NoError(t, err)
549+
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
550+
}
551+
552+
// Issue index shouldn't be post processing in an document.
553+
test(
554+
"#1",
555+
"#1")
556+
557+
// Test that other post processing still works.
558+
test(
559+
":gitea:",
560+
`<span class="emoji" aria-label="gitea"><img alt=":gitea:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/gitea.png"/></span>`)
561+
test(
562+
"Some text with 😄 in the middle",
563+
`Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle`)
564+
test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
565+
`<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4 (comment)</a>`)
566+
}
567+
532568
func TestIssue16020(t *testing.T) {
533569
setting.AppURL = TestAppURL
534570

modules/templates/helper.go

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
// NewFuncMap returns functions for injecting to templates
2929
func NewFuncMap() template.FuncMap {
3030
return map[string]any{
31+
"ctx": func() any { return nil }, // template context function
32+
3133
"DumpVar": dumpVar,
3234

3335
// -----------------------------------------------------------------

0 commit comments

Comments
 (0)