Merge pull request '[gitea] cherry-pick' (#2397) from earl-warren/forgejo:wip-gitea-cherry-pick into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2397 Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
commit
0533022d63
68 changed files with 810 additions and 350 deletions
|
@ -55,7 +55,9 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
|
|||
case webhook_module.HookEventPullRequest,
|
||||
webhook_module.HookEventPullRequestSync,
|
||||
webhook_module.HookEventPullRequestAssign,
|
||||
webhook_module.HookEventPullRequestLabel:
|
||||
webhook_module.HookEventPullRequestLabel,
|
||||
webhook_module.HookEventPullRequestReviewRequest,
|
||||
webhook_module.HookEventPullRequestMilestone:
|
||||
return true
|
||||
|
||||
default:
|
||||
|
|
|
@ -186,7 +186,9 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
|
|||
webhook_module.HookEventPullRequest,
|
||||
webhook_module.HookEventPullRequestSync,
|
||||
webhook_module.HookEventPullRequestAssign,
|
||||
webhook_module.HookEventPullRequestLabel:
|
||||
webhook_module.HookEventPullRequestLabel,
|
||||
webhook_module.HookEventPullRequestReviewRequest,
|
||||
webhook_module.HookEventPullRequestMilestone:
|
||||
return matchPullRequestEvent(gitRepo, commit, payload.(*api.PullRequestPayload), evt)
|
||||
|
||||
case // pull_request_review
|
||||
|
@ -362,13 +364,13 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
|
|||
} else {
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||
// Actions with the same name:
|
||||
// opened, edited, closed, reopened, assigned, unassigned
|
||||
// opened, edited, closed, reopened, assigned, unassigned, review_requested, review_request_removed, milestoned, demilestoned
|
||||
// Actions need to be converted:
|
||||
// synchronized -> synchronize
|
||||
// label_updated -> labeled
|
||||
// label_cleared -> unlabeled
|
||||
// Unsupported activity types:
|
||||
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
|
||||
// converted_to_draft, ready_for_review, locked, unlocked, auto_merge_enabled, auto_merge_disabled, enqueued, dequeued
|
||||
|
||||
action := prPayload.Action
|
||||
switch action {
|
||||
|
|
|
@ -90,6 +90,20 @@ func (ctx *Context) HTML(status int, name base.TplName) {
|
|||
}
|
||||
}
|
||||
|
||||
// JSONTemplate renders the template as JSON response
|
||||
// keep in mind that the template is processed in HTML context, so JSON-things should be handled carefully, eg: by JSEscape
|
||||
func (ctx *Context) JSONTemplate(tmpl base.TplName) {
|
||||
t, err := ctx.Render.TemplateLookup(string(tmpl), nil)
|
||||
if err != nil {
|
||||
ctx.ServerError("unable to find template", err)
|
||||
return
|
||||
}
|
||||
ctx.Resp.Header().Set("Content-Type", "application/json")
|
||||
if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
|
||||
ctx.ServerError("unable to execute template", err)
|
||||
}
|
||||
}
|
||||
|
||||
// RenderToString renders the template content to a string
|
||||
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
|
||||
var buf strings.Builder
|
||||
|
|
|
@ -5,10 +5,7 @@ package context
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
var _ context.Context = TemplateContext(nil)
|
||||
|
@ -36,14 +33,3 @@ func (c TemplateContext) Err() error {
|
|||
func (c TemplateContext) Value(key any) any {
|
||||
return c.parentContext().Value(key)
|
||||
}
|
||||
|
||||
// DataRaceCheck checks whether the template context function "ctx()" returns the consistent context
|
||||
// as the current template's rendering context (request context), to help to find data race issues as early as possible.
|
||||
// When the code is proven to be correct and stable, this function should be removed.
|
||||
func (c TemplateContext) DataRaceCheck(dataCtx context.Context) (string, error) {
|
||||
if c.parentContext() != dataCtx {
|
||||
log.Error("TemplateContext.DataRaceCheck: parent context mismatch\n%s", log.Stack(2))
|
||||
return "", errors.New("parent context mismatch")
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func NewFuncMap() template.FuncMap {
|
|||
"Safe": Safe,
|
||||
"Escape": Escape,
|
||||
"QueryEscape": url.QueryEscape,
|
||||
"JSEscape": template.JSEscapeString,
|
||||
"JSEscape": JSEscapeSafe,
|
||||
"Str2html": Str2html, // TODO: rename it to SanitizeHTML
|
||||
"URLJoin": util.URLJoin,
|
||||
"DotEscape": DotEscape,
|
||||
|
@ -214,6 +214,10 @@ func Escape(s any) template.HTML {
|
|||
panic(fmt.Sprintf("unexpected type %T", s))
|
||||
}
|
||||
|
||||
func JSEscapeSafe(s string) template.HTML {
|
||||
return template.HTML(template.JSEscapeString(s))
|
||||
}
|
||||
|
||||
func RenderEmojiPlain(s any) any {
|
||||
switch v := s.(type) {
|
||||
case string:
|
||||
|
|
|
@ -52,3 +52,7 @@ func TestSubjectBodySeparator(t *testing.T) {
|
|||
"",
|
||||
"Insuficient\n--\nSeparators")
|
||||
}
|
||||
|
||||
func TestJSEscapeSafe(t *testing.T) {
|
||||
assert.EqualValues(t, `\u0026\u003C\u003E\'\"`, JSEscapeSafe(`&<>'"`))
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package i18n
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -82,6 +83,71 @@ c=22
|
|||
assert.Equal(t, "22", lang1.TrString("c"))
|
||||
}
|
||||
|
||||
type stringerPointerReceiver struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (s *stringerPointerReceiver) String() string {
|
||||
return s.s
|
||||
}
|
||||
|
||||
type stringerStructReceiver struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (s stringerStructReceiver) String() string {
|
||||
return s.s
|
||||
}
|
||||
|
||||
type errorStructReceiver struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (e errorStructReceiver) Error() string {
|
||||
return e.s
|
||||
}
|
||||
|
||||
type errorPointerReceiver struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (e *errorPointerReceiver) Error() string {
|
||||
return e.s
|
||||
}
|
||||
|
||||
func TestLocaleWithTemplate(t *testing.T) {
|
||||
ls := NewLocaleStore()
|
||||
assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", []byte(`key=<a>%s</a>`), nil))
|
||||
lang1, _ := ls.Locale("lang1")
|
||||
|
||||
tmpl := template.New("test").Funcs(template.FuncMap{"tr": lang1.TrHTML})
|
||||
tmpl = template.Must(tmpl.Parse(`{{tr "key" .var}}`))
|
||||
|
||||
cases := []struct {
|
||||
in any
|
||||
want string
|
||||
}{
|
||||
{"<str>", "<a><str></a>"},
|
||||
{[]byte("<bytes>"), "<a>[60 98 121 116 101 115 62]</a>"},
|
||||
{template.HTML("<html>"), "<a><html></a>"},
|
||||
{stringerPointerReceiver{"<stringerPointerReceiver>"}, "<a>{<stringerPointerReceiver>}</a>"},
|
||||
{&stringerPointerReceiver{"<stringerPointerReceiver ptr>"}, "<a><stringerPointerReceiver ptr></a>"},
|
||||
{stringerStructReceiver{"<stringerStructReceiver>"}, "<a><stringerStructReceiver></a>"},
|
||||
{&stringerStructReceiver{"<stringerStructReceiver ptr>"}, "<a><stringerStructReceiver ptr></a>"},
|
||||
{errorStructReceiver{"<errorStructReceiver>"}, "<a><errorStructReceiver></a>"},
|
||||
{&errorStructReceiver{"<errorStructReceiver ptr>"}, "<a><errorStructReceiver ptr></a>"},
|
||||
{errorPointerReceiver{"<errorPointerReceiver>"}, "<a>{<errorPointerReceiver>}</a>"},
|
||||
{&errorPointerReceiver{"<errorPointerReceiver ptr>"}, "<a><errorPointerReceiver ptr></a>"},
|
||||
}
|
||||
|
||||
buf := &strings.Builder{}
|
||||
for _, c := range cases {
|
||||
buf.Reset()
|
||||
assert.NoError(t, tmpl.Execute(buf, map[string]any{"var": c.in}))
|
||||
assert.Equal(t, c.want, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocaleStoreQuirks(t *testing.T) {
|
||||
const nl = "\n"
|
||||
q := func(q1, s string, q2 ...string) string {
|
||||
|
|
|
@ -136,12 +136,14 @@ func (l *locale) TrHTML(trKey string, trArgs ...any) template.HTML {
|
|||
args := slices.Clone(trArgs)
|
||||
for i, v := range args {
|
||||
switch v := v.(type) {
|
||||
case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
|
||||
// for most basic types (including template.HTML which is safe), just do nothing and use it
|
||||
case string:
|
||||
args[i] = template.HTML(template.HTMLEscapeString(v))
|
||||
args[i] = template.HTMLEscapeString(v)
|
||||
case fmt.Stringer:
|
||||
args[i] = template.HTMLEscapeString(v.String())
|
||||
default: // int, float, include template.HTML
|
||||
// do nothing, just use it
|
||||
default:
|
||||
args[i] = template.HTMLEscapeString(fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
return template.HTML(l.TrString(trKey, args...))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue