mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-07 05:39:32 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
555 files changed
+7181
-4242
No files matched your search
@@ -23,13 +23,11 @@ import (
|
||||
type DetectedWorkflow struct {
|
||||
EntryName string
|
||||
TriggerEvent string
|
||||
Commit *git.Commit
|
||||
Ref string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
model.OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
|
||||
model.OnDecodeNodeError = func(node yaml.Node, out any, err error) {
|
||||
// Log the error instead of panic or fatal.
|
||||
// It will be a big job to refactor act/pkg/model to return decode error,
|
||||
// so we just log the error and return empty value, and improve it later.
|
||||
@@ -120,7 +118,6 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
|
||||
dwf := &DetectedWorkflow{
|
||||
EntryName: entry.Name(),
|
||||
TriggerEvent: evt.Name,
|
||||
Commit: commit,
|
||||
Content: content,
|
||||
}
|
||||
workflows = append(workflows, dwf)
|
||||
@@ -335,44 +332,47 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
|
||||
}
|
||||
|
||||
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||
// with no special filter parameters
|
||||
if len(evt.Acts()) == 0 {
|
||||
acts := evt.Acts()
|
||||
activityTypeMatched := false
|
||||
matchTimes := 0
|
||||
|
||||
if vals, ok := acts["types"]; !ok {
|
||||
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||
activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||
} 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
|
||||
// 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
|
||||
|
||||
action := prPayload.Action
|
||||
switch action {
|
||||
case api.HookIssueSynchronized:
|
||||
action = "synchronize"
|
||||
case api.HookIssueLabelUpdated:
|
||||
action = "labeled"
|
||||
case api.HookIssueLabelCleared:
|
||||
action = "unlabeled"
|
||||
}
|
||||
log.Trace("matching pull_request %s with %v", action, vals)
|
||||
for _, val := range vals {
|
||||
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||
activityTypeMatched = true
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchTimes := 0
|
||||
// all acts conditions should be satisfied
|
||||
for cond, vals := range evt.Acts() {
|
||||
for cond, vals := range acts {
|
||||
switch cond {
|
||||
case "types":
|
||||
// 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
|
||||
// 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
|
||||
|
||||
action := prPayload.Action
|
||||
switch action {
|
||||
case api.HookIssueSynchronized:
|
||||
action = "synchronize"
|
||||
case api.HookIssueLabelUpdated:
|
||||
action = "labeled"
|
||||
case api.HookIssueLabelCleared:
|
||||
action = "unlabeled"
|
||||
}
|
||||
log.Trace("matching pull_request %s with %v", action, vals)
|
||||
for _, val := range vals {
|
||||
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
case "branches":
|
||||
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||
@@ -421,7 +421,7 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
|
||||
log.Warn("pull request event unsupported condition %q", cond)
|
||||
}
|
||||
}
|
||||
return matchTimes == len(evt.Acts())
|
||||
return activityTypeMatched && matchTimes == len(evt.Acts())
|
||||
}
|
||||
|
||||
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
||||
|
||||
@@ -57,6 +57,25 @@ func TestDetectMatched(t *testing.T) {
|
||||
yamlOn: "on: pull_request",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with no activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueClosed},
|
||||
yamlOn: "on: pull_request",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with branches",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{
|
||||
Action: api.HookIssueClosed,
|
||||
PullRequest: &api.PullRequest{
|
||||
Base: &api.PRBranchInfo{},
|
||||
},
|
||||
},
|
||||
yamlOn: "on:\n pull_request:\n branches: [main]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action matches GithubEventPullRequest(pull_request) with `label` activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
|
||||
@@ -63,19 +63,19 @@ type Client struct {
|
||||
// NewClient function
|
||||
func NewClient(user *user_model.User, pubID string) (c *Client, err error) {
|
||||
if err = containsRequiredHTTPHeaders(http.MethodGet, setting.Federation.GetHeaders); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
} else if err = containsRequiredHTTPHeaders(http.MethodPost, setting.Federation.PostHeaders); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
priv, err := GetPrivateKey(user)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
privPem, _ := pem.Decode([]byte(priv))
|
||||
privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c = &Client{
|
||||
@@ -99,14 +99,14 @@ func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error)
|
||||
buf := bytes.NewBuffer(b)
|
||||
req, err = http.NewRequest(http.MethodPost, to, buf)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Content-Type", ActivityStreamsContentType)
|
||||
req.Header.Add("Date", CurrentTime())
|
||||
req.Header.Add("User-Agent", "Gitea/"+setting.AppVer)
|
||||
signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
err = signer.SignRequest(c.priv, c.pubID, req, b)
|
||||
return req, err
|
||||
@@ -116,7 +116,7 @@ func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error)
|
||||
func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) {
|
||||
var req *http.Request
|
||||
if req, err = c.NewRequest(b, to); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
resp, err = c.client.Do(req)
|
||||
return resp, err
|
||||
|
||||
@@ -15,22 +15,22 @@ func GetKeyPair(user *user_model.User) (pub, priv string, err error) {
|
||||
var settings map[string]*user_model.Setting
|
||||
settings, err = user_model.GetSettings(user.ID, []string{user_model.UserActivityPubPrivPem, user_model.UserActivityPubPubPem})
|
||||
if err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
} else if len(settings) == 0 {
|
||||
if priv, pub, err = util.GenerateKeyPair(rsaBits); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
if err = user_model.SetUserSetting(user.ID, user_model.UserActivityPubPrivPem, priv); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
if err = user_model.SetUserSetting(user.ID, user_model.UserActivityPubPubPem, pub); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
return
|
||||
return pub, priv, err
|
||||
} else {
|
||||
priv = settings[user_model.UserActivityPubPrivPem].SettingValue
|
||||
pub = settings[user_model.UserActivityPubPubPem].SettingValue
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) {
|
||||
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
|
||||
continue
|
||||
}
|
||||
layerDirs = append(layerDirs, ".")
|
||||
for _, dir := range layerDirs {
|
||||
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil {
|
||||
log.Error("Unable to watch directory %s: %v", dir, err)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package avatar_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/png"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/avatar"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_HashAvatar(t *testing.T) {
|
||||
myImage := image.NewRGBA(image.Rect(0, 0, 32, 32))
|
||||
var buff bytes.Buffer
|
||||
png.Encode(&buff, myImage)
|
||||
|
||||
assert.EqualValues(t, "9ddb5bac41d57e72aa876321d0c09d71090c05f94bc625303801be2f3240d2cb", avatar.HashAvatar(1, buff.Bytes()))
|
||||
assert.EqualValues(t, "9a5d44e5d637b9582a976676e8f3de1dccd877c2fe3e66ca3fab1629f2f47609", avatar.HashAvatar(8, buff.Bytes()))
|
||||
assert.EqualValues(t, "ed7399158672088770de6f5211ce15528ebd675e92fc4fc060c025f4b2794ccb", avatar.HashAvatar(1024, buff.Bytes()))
|
||||
assert.EqualValues(t, "161178642c7d59eb25a61dddced5e6b66eae1c70880d5f148b1b497b767e72d9", avatar.HashAvatar(1024, []byte{}))
|
||||
}
|
||||
@@ -107,7 +107,7 @@ const TimeLimitCodeLength = 12 + 6 + 40
|
||||
|
||||
// CreateTimeLimitCode create a time limit code
|
||||
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
|
||||
func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string {
|
||||
func CreateTimeLimitCode(data string, minutes int, startInf any) string {
|
||||
format := "200601021504"
|
||||
|
||||
var start, end time.Time
|
||||
@@ -252,7 +252,7 @@ func SetupGiteaRoot() string {
|
||||
}
|
||||
|
||||
// FormatNumberSI format a number
|
||||
func FormatNumberSI(data interface{}) string {
|
||||
func FormatNumberSI(data any) string {
|
||||
var num int64
|
||||
if num1, ok := data.(int64); ok {
|
||||
num = num1
|
||||
|
||||
Vendored
+3
-3
@@ -24,7 +24,7 @@ type RedisCacher struct {
|
||||
}
|
||||
|
||||
// toStr convert string/int/int64 interface to string. it's only used by the RedisCacher.Put internally
|
||||
func toStr(v interface{}) string {
|
||||
func toStr(v any) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func toStr(v interface{}) string {
|
||||
|
||||
// Put puts value (string type) into cache with key and expire time.
|
||||
// If expired is 0, it lives forever.
|
||||
func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
||||
func (c *RedisCacher) Put(key string, val any, expire int64) error {
|
||||
// this function is not well-designed, it only puts string values into cache
|
||||
key = c.prefix + key
|
||||
if expire == 0 {
|
||||
@@ -65,7 +65,7 @@ func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *RedisCacher) Get(key string) interface{} {
|
||||
func (c *RedisCacher) Get(key string) any {
|
||||
val, err := c.c.Get(graceful.GetManager().HammerContext(), c.prefix+key).Result()
|
||||
if err != nil {
|
||||
return nil
|
||||
|
||||
Vendored
+4
-4
@@ -30,7 +30,7 @@ type TwoQueueCacheConfig struct {
|
||||
|
||||
// MemoryItem represents a memory cache item.
|
||||
type MemoryItem struct {
|
||||
Val interface{}
|
||||
Val any
|
||||
Created int64
|
||||
Timeout int64
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func (item *MemoryItem) hasExpired() bool {
|
||||
var _ mc.Cache = &TwoQueueCache{}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
||||
func (c *TwoQueueCache) Put(key string, val any, timeout int64) error {
|
||||
item := &MemoryItem{
|
||||
Val: val,
|
||||
Created: time.Now().Unix(),
|
||||
@@ -56,7 +56,7 @@ func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *TwoQueueCache) Get(key string) interface{} {
|
||||
func (c *TwoQueueCache) Get(key string) any {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
cached, ok := c.cache.Get(key)
|
||||
@@ -146,7 +146,7 @@ func (c *TwoQueueCache) Flush() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *TwoQueueCache) checkAndInvalidate(key interface{}) {
|
||||
func (c *TwoQueueCache) checkAndInvalidate(key any) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
cached, ok := c.cache.Peek(key)
|
||||
|
||||
@@ -90,7 +90,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].Locale < tables[j].Locale
|
||||
})
|
||||
data := map[string]interface{}{
|
||||
data := map[string]any{
|
||||
"Tables": tables,
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
||||
}
|
||||
}
|
||||
|
||||
func runTemplate(t *template.Template, filename string, data interface{}) error {
|
||||
func runTemplate(t *template.Template, filename string, data any) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := t.Execute(buf, data); err != nil {
|
||||
return fmt.Errorf("unable to execute template: %w", err)
|
||||
@@ -172,17 +172,17 @@ var AmbiguousCharacters = map[string]*AmbiguousTable{
|
||||
|
||||
`))
|
||||
|
||||
func logf(format string, args ...interface{}) {
|
||||
func logf(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
}
|
||||
|
||||
func verbosef(format string, args ...interface{}) {
|
||||
func verbosef(format string, args ...any) {
|
||||
if verbose {
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
func fatalf(format string, args ...any) {
|
||||
logf("fatal: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -52,7 +52,7 @@ Usage: %[1]s [-v] [-o output.go]
|
||||
}
|
||||
}
|
||||
|
||||
func runTemplate(t *template.Template, filename string, data interface{}) error {
|
||||
func runTemplate(t *template.Template, filename string, data any) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := t.Execute(buf, data); err != nil {
|
||||
return fmt.Errorf("unable to execute template: %w", err)
|
||||
@@ -105,17 +105,17 @@ var InvisibleRanges = &unicode.RangeTable{
|
||||
}
|
||||
`))
|
||||
|
||||
func logf(format string, args ...interface{}) {
|
||||
func logf(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
}
|
||||
|
||||
func verbosef(format string, args ...interface{}) {
|
||||
func verbosef(format string, args ...any) {
|
||||
if verbose {
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
func fatalf(format string, args ...any) {
|
||||
logf("fatal: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -23,7 +23,7 @@ type routerLoggerOptions struct {
|
||||
Identity *string
|
||||
Start *time.Time
|
||||
ResponseWriter http.ResponseWriter
|
||||
Ctx map[string]interface{}
|
||||
Ctx map[string]any
|
||||
RequestID *string
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func AccessLogger() func(http.Handler) http.Handler {
|
||||
Identity: &identity,
|
||||
Start: &start,
|
||||
ResponseWriter: rw,
|
||||
Ctx: map[string]interface{}{
|
||||
Ctx: map[string]any{
|
||||
"RemoteAddr": req.RemoteAddr,
|
||||
"RemoteHost": reqHost,
|
||||
"Req": req,
|
||||
|
||||
@@ -108,7 +108,7 @@ func (ctx *APIContext) ServerError(title string, err error) {
|
||||
|
||||
// Error responds with an error message to client with given obj as the message.
|
||||
// If status is 500, also it prints error to log.
|
||||
func (ctx *APIContext) Error(status int, title string, obj interface{}) {
|
||||
func (ctx *APIContext) Error(status int, title string, obj any) {
|
||||
var message string
|
||||
if err, ok := obj.(error); ok {
|
||||
message = err.Error()
|
||||
@@ -265,7 +265,7 @@ func APIContexter() func(http.Handler) http.Handler {
|
||||
|
||||
// NotFound handles 404s for APIContext
|
||||
// String will replace message, errors will be added to a slice
|
||||
func (ctx *APIContext) NotFound(objs ...interface{}) {
|
||||
func (ctx *APIContext) NotFound(objs ...any) {
|
||||
message := ctx.Tr("error.not_found")
|
||||
var errors []string
|
||||
for _, obj := range objs {
|
||||
@@ -281,7 +281,7 @@ func (ctx *APIContext) NotFound(objs ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusNotFound, map[string]interface{}{
|
||||
ctx.JSON(http.StatusNotFound, map[string]any{
|
||||
"message": message,
|
||||
"url": setting.API.SwaggerURL,
|
||||
"errors": errors,
|
||||
@@ -294,7 +294,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
|
||||
return func(ctx *APIContext) (cancel context.CancelFunc) {
|
||||
// Empty repository does not have reference information.
|
||||
if ctx.Repo.Repository.IsEmpty && !(len(allowEmpty) != 0 && allowEmpty[0]) {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// For API calls.
|
||||
@@ -303,7 +303,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
|
||||
gitRepo, err := git.OpenRepository(ctx, repoPath)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "RepoRef Invalid repo "+repoPath, err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.GitRepo = gitRepo
|
||||
// We opened it, we should close it
|
||||
|
||||
@@ -128,7 +128,7 @@ func (b *Base) Error(status int, contents ...string) {
|
||||
}
|
||||
|
||||
// JSON render content as JSON
|
||||
func (b *Base) JSON(status int, content interface{}) {
|
||||
func (b *Base) JSON(status int, content any) {
|
||||
b.Resp.Header().Set("Content-Type", "application/json;charset=utf-8")
|
||||
b.Resp.WriteHeader(status)
|
||||
if err := json.NewEncoder(b.Resp).Encode(content); err != nil {
|
||||
|
||||
@@ -60,7 +60,7 @@ const (
|
||||
|
||||
// VerifyCaptcha verifies Captcha data
|
||||
// No-op if captchas are not enabled
|
||||
func VerifyCaptcha(ctx *Context, tpl base.TplName, form interface{}) {
|
||||
func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
|
||||
if !setting.Service.EnableCaptcha {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
// Render represents a template render
|
||||
type Render interface {
|
||||
TemplateLookup(tmpl string) (templates.TemplateExecutor, error)
|
||||
HTML(w io.Writer, status int, name string, data interface{}) error
|
||||
HTML(w io.Writer, status int, name string, data any) error
|
||||
}
|
||||
|
||||
// Context represents context of a request.
|
||||
@@ -69,7 +69,7 @@ func init() {
|
||||
// TrHTMLEscapeArgs runs ".Locale.Tr()" but pre-escapes all arguments with html.EscapeString.
|
||||
// This is useful if the locale message is intended to only produce HTML content.
|
||||
func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {
|
||||
trArgs := make([]interface{}, len(args))
|
||||
trArgs := make([]any, len(args))
|
||||
for i, arg := range args {
|
||||
trArgs[i] = html.EscapeString(arg)
|
||||
}
|
||||
|
||||
@@ -91,14 +91,14 @@ func (ctx *Context) HTML(status int, name base.TplName) {
|
||||
}
|
||||
|
||||
// RenderToString renders the template content to a string
|
||||
func (ctx *Context) RenderToString(name base.TplName, data map[string]interface{}) (string, error) {
|
||||
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
|
||||
var buf strings.Builder
|
||||
err := ctx.Render.HTML(&buf, http.StatusOK, string(name), data)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
// RenderWithErr used for page has form validation but need to prompt error to users.
|
||||
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
|
||||
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form any) {
|
||||
if form != nil {
|
||||
middleware.AssignForm(form, ctx.Data)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,6 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||
}
|
||||
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
|
||||
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
|
||||
ctx.Data["IsProjectEnabled"] = true
|
||||
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
ctx.Data["IsPublicMember"] = func(uid int64) bool {
|
||||
|
||||
@@ -33,7 +33,7 @@ type packageAssignmentCtx struct {
|
||||
// PackageAssignment returns a middleware to handle Context.Package assignment
|
||||
func PackageAssignment() func(ctx *Context) {
|
||||
return func(ctx *Context) {
|
||||
errorFn := func(status int, title string, obj interface{}) {
|
||||
errorFn := func(status int, title string, obj any) {
|
||||
err, ok := obj.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf("%s", obj)
|
||||
@@ -57,7 +57,7 @@ func PackageAssignmentAPI() func(ctx *APIContext) {
|
||||
}
|
||||
}
|
||||
|
||||
func packageAssignment(ctx *packageAssignmentCtx, errCb func(int, string, interface{})) *Package {
|
||||
func packageAssignment(ctx *packageAssignmentCtx, errCb func(int, string, any)) *Package {
|
||||
pkg := &Package{
|
||||
Owner: ctx.ContextUser,
|
||||
}
|
||||
@@ -108,18 +108,28 @@ func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.A
|
||||
|
||||
if doer != nil && !doer.IsGhost() {
|
||||
// 1. If user is logged in, check all team packages permissions
|
||||
teams, err := organization.GetUserOrgTeams(ctx, org.ID, doer.ID)
|
||||
var err error
|
||||
accessMode, err = org.GetOrgUserMaxAuthorizeLevel(doer.ID)
|
||||
if err != nil {
|
||||
return accessMode, err
|
||||
}
|
||||
for _, t := range teams {
|
||||
perm := t.UnitAccessMode(ctx, unit.TypePackages)
|
||||
if accessMode < perm {
|
||||
accessMode = perm
|
||||
// If access mode is less than write check every team for more permissions
|
||||
// The minimum possible access mode is read for org members
|
||||
if accessMode < perm.AccessModeWrite {
|
||||
teams, err := organization.GetUserOrgTeams(ctx, org.ID, doer.ID)
|
||||
if err != nil {
|
||||
return accessMode, err
|
||||
}
|
||||
for _, t := range teams {
|
||||
perm := t.UnitAccessMode(ctx, unit.TypePackages)
|
||||
if accessMode < perm {
|
||||
accessMode = perm
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if organization.HasOrgOrUserVisible(ctx, pkg.Owner, doer) {
|
||||
// 2. If user is non-login, check if org is visible to non-login user
|
||||
}
|
||||
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, pkg.Owner, doer) {
|
||||
// 2. If user is unauthorized or no org member, check if org is visible
|
||||
accessMode = perm.AccessModeRead
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -32,7 +32,7 @@ func (p *Pagination) AddParam(ctx *Context, paramKey, ctxKey string) {
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
paramData := fmt.Sprintf("%v", ctx.Data[ctxKey]) // cast interface{} to string
|
||||
paramData := fmt.Sprintf("%v", ctx.Data[ctxKey]) // cast any to string
|
||||
urlParam := fmt.Sprintf("%s=%v", url.QueryEscape(paramKey), url.QueryEscape(paramData))
|
||||
p.urlParams = append(p.urlParams, urlParam)
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) {
|
||||
}
|
||||
if log.IsTrace() {
|
||||
var format string
|
||||
var args []interface{}
|
||||
var args []any
|
||||
if ctx.IsSigned {
|
||||
format = "Permission Denied: User %-v cannot read ["
|
||||
args = append(args, ctx.Doer)
|
||||
|
||||
@@ -53,7 +53,7 @@ func (ctx *PrivateContext) Err() error {
|
||||
return ctx.Base.Err()
|
||||
}
|
||||
|
||||
var privateContextKey interface{} = "default_private_context"
|
||||
var privateContextKey any = "default_private_context"
|
||||
|
||||
// GetPrivateContext returns a context for Private routes
|
||||
func GetPrivateContext(req *http.Request) *PrivateContext {
|
||||
|
||||
+37
-37
@@ -422,10 +422,10 @@ func RepoIDAssignment() func(ctx *Context) {
|
||||
}
|
||||
|
||||
// RepoAssignment returns a middleware to handle repository assignment
|
||||
func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
||||
log.Trace("RepoAssignment was exec already, skipping second call ...")
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.Data["repoAssignmentExecuted"] = true
|
||||
|
||||
@@ -453,7 +453,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
// https://github.com/golang/go/issues/19760
|
||||
if ctx.FormString("go-get") == "1" {
|
||||
EarlyResponseForGoGetMeta(ctx)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil {
|
||||
@@ -466,7 +466,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
} else {
|
||||
ctx.ServerError("GetUserByName", err)
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
ctx.Repo.Owner = owner
|
||||
@@ -490,7 +490,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
redirectPath += "?" + ctx.Req.URL.RawQuery
|
||||
}
|
||||
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get repository.
|
||||
@@ -503,7 +503,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||
if ctx.FormString("go-get") == "1" {
|
||||
EarlyResponseForGoGetMeta(ctx)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.NotFound("GetRepositoryByName", nil)
|
||||
} else {
|
||||
@@ -512,13 +512,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
} else {
|
||||
ctx.ServerError("GetRepositoryByName", err)
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
repo.Owner = owner
|
||||
|
||||
repoAssignment(ctx, repo)
|
||||
if ctx.Written() {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.Repo.RepoLink = repo.Link()
|
||||
@@ -542,12 +542,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetReleaseCountByRepoID", err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetReleaseCountByRepoID", err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
||||
@@ -563,14 +563,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
ctx.ServerError("CanUserForkRepo", err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.Data["CanSignedUserFork"] = canSignedUserFork
|
||||
|
||||
userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetForksByUserAndOrgs", err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.Data["UserAndOrgForks"] = userAndOrgForks
|
||||
|
||||
@@ -604,14 +604,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
if repo.IsFork {
|
||||
RetrieveBaseRepo(ctx, repo)
|
||||
if ctx.Written() {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if repo.IsGenerated() {
|
||||
RetrieveTemplateRepo(ctx, repo)
|
||||
if ctx.Written() {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
if !isHomeOrSettings {
|
||||
ctx.Redirect(ctx.Repo.RepoLink)
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName))
|
||||
@@ -636,10 +636,10 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
if !isHomeOrSettings {
|
||||
ctx.Redirect(ctx.Repo.RepoLink)
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
ctx.Repo.GitRepo.Close()
|
||||
@@ -647,7 +647,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
ctx.Repo.GitRepo = gitRepo
|
||||
|
||||
// We opened it, we should close it
|
||||
cancel = func() {
|
||||
cancel := func() {
|
||||
// If it's been set to nil then assume someone else has closed it.
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
ctx.Repo.GitRepo.Close()
|
||||
@@ -657,13 +657,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
// Stop at this point when the repo is empty.
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetTagNamesByRepoID", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Data["Tags"] = tags
|
||||
|
||||
@@ -677,7 +677,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
branchesTotal, err := git_model.CountBranches(ctx, branchOpts)
|
||||
if err != nil {
|
||||
ctx.ServerError("CountBranches", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
// non empty repo should have at least 1 branch, so this repository's branches haven't been synced yet
|
||||
@@ -685,7 +685,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
branchesTotal, err = repo_module.SyncRepoBranches(ctx, ctx.Repo.Repository.ID, 0)
|
||||
if err != nil {
|
||||
ctx.ServerError("SyncRepoBranches", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,7 +694,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
brs, err := git_model.FindBranchNames(ctx, branchOpts)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranches", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
// always put default branch on the top
|
||||
ctx.Data["Branches"] = append(branchOpts.ExcludeBranchNames, brs...)
|
||||
@@ -741,12 +741,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
|
||||
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetPendingRepositoryTransfer", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
if err := repoTransfer.LoadAttributes(ctx); err != nil {
|
||||
ctx.ServerError("LoadRecipient", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
ctx.Data["RepoTransfer"] = repoTransfer
|
||||
@@ -894,7 +894,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.IsViewBranch = true
|
||||
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
|
||||
ctx.Data["TreePath"] = ""
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -907,7 +907,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath)
|
||||
if err != nil {
|
||||
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
// We opened it, we should close it
|
||||
cancel = func() {
|
||||
@@ -944,7 +944,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||
} else {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.IsViewBranch = true
|
||||
} else {
|
||||
@@ -956,7 +956,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
|
||||
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
|
||||
ctx.Redirect(link)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
@@ -966,7 +966,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
|
||||
@@ -978,10 +978,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound("GetTagCommit", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.ServerError("GetTagCommit", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if len(refName) >= 7 && len(refName) <= git.SHAFullLength {
|
||||
@@ -991,7 +991,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
|
||||
if err != nil {
|
||||
ctx.NotFound("GetCommit", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
// If short commit ID add canonical link header
|
||||
if len(refName) < git.SHAFullLength {
|
||||
@@ -1000,10 +1000,10 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
}
|
||||
} else {
|
||||
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
|
||||
if refType == RepoRefLegacy {
|
||||
@@ -1015,7 +1015,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
util.PathEscapeSegments(prefix),
|
||||
ctx.Repo.BranchNameSubURL(),
|
||||
util.PathEscapeSegments(ctx.Repo.TreePath)))
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1033,7 +1033,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
|
||||
if err != nil {
|
||||
ctx.ServerError("GetCommitsCount", err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
|
||||
ctx.Repo.GitRepo.LastCommitCache = git.NewLastCommitCache(ctx.Repo.CommitsCount, ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, cache.GetCache())
|
||||
|
||||
+30
-29
@@ -6,6 +6,7 @@ package doctor
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@@ -40,12 +41,12 @@ func parseBool16961(bs []byte) (bool, error) {
|
||||
func fixUnitConfig16961(bs []byte, cfg *repo_model.UnitConfig) (fixed bool, err error) {
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Handle #16961
|
||||
if string(bs) != "&{}" && len(bs) != 0 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
@@ -54,14 +55,14 @@ func fixUnitConfig16961(bs []byte, cfg *repo_model.UnitConfig) (fixed bool, err
|
||||
func fixExternalWikiConfig16961(bs []byte, cfg *repo_model.ExternalWikiConfig) (fixed bool, err error) {
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if len(bs) < 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
cfg.ExternalWikiURL = string(bs[2 : len(bs)-1])
|
||||
return true, nil
|
||||
@@ -70,20 +71,20 @@ func fixExternalWikiConfig16961(bs []byte, cfg *repo_model.ExternalWikiConfig) (
|
||||
func fixExternalTrackerConfig16961(bs []byte, cfg *repo_model.ExternalTrackerConfig) (fixed bool, err error) {
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return
|
||||
return false, nil
|
||||
}
|
||||
// Handle #16961
|
||||
if len(bs) < 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||
if len(parts) != 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
cfg.ExternalTrackerURL = string(bytes.Join(parts[:len(parts)-2], []byte{' '}))
|
||||
@@ -95,16 +96,16 @@ func fixExternalTrackerConfig16961(bs []byte, cfg *repo_model.ExternalTrackerCon
|
||||
func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (fixed bool, err error) {
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Handle #16961
|
||||
if len(bs) < 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
// PullRequestsConfig was the following in 1.14
|
||||
@@ -123,37 +124,37 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
|
||||
// DefaultMergeStyle MergeStyle
|
||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||
if len(parts) < 7 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
var parseErr error
|
||||
cfg.IgnoreWhitespaceConflicts, parseErr = parseBool16961(parts[0])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowMerge, parseErr = parseBool16961(parts[1])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowRebase, parseErr = parseBool16961(parts[2])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowRebaseMerge, parseErr = parseBool16961(parts[3])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowSquash, parseErr = parseBool16961(parts[4])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowManualMerge, parseErr = parseBool16961(parts[5])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AutodetectManualMerge, parseErr = parseBool16961(parts[6])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
|
||||
// 1.14 unit
|
||||
@@ -162,12 +163,12 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
|
||||
}
|
||||
|
||||
if len(parts) < 9 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
cfg.DefaultDeleteBranchAfterMerge, parseErr = parseBool16961(parts[7])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
|
||||
cfg.DefaultMergeStyle = repo_model.MergeStyle(string(bytes.Join(parts[8:], []byte{' '})))
|
||||
@@ -177,34 +178,34 @@ func fixPullRequestsConfig16961(bs []byte, cfg *repo_model.PullRequestsConfig) (
|
||||
func fixIssuesConfig16961(bs []byte, cfg *repo_model.IssuesConfig) (fixed bool, err error) {
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Handle #16961
|
||||
if len(bs) < 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
if bs[0] != '&' || bs[1] != '{' || bs[len(bs)-1] != '}' {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
|
||||
parts := bytes.Split(bs[2:len(bs)-1], []byte{' '})
|
||||
if len(parts) != 3 {
|
||||
return
|
||||
return false, err
|
||||
}
|
||||
var parseErr error
|
||||
cfg.EnableTimetracker, parseErr = parseBool16961(parts[0])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.AllowOnlyContributorsToTrackTime, parseErr = parseBool16961(parts[1])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
cfg.EnableDependencies, parseErr = parseBool16961(parts[2])
|
||||
if parseErr != nil {
|
||||
return
|
||||
return false, errors.Join(err, parseErr)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ func garbageCollectLFSCheck(ctx context.Context, logger log.Logger, autofix bool
|
||||
}
|
||||
|
||||
if err := repository.GarbageCollectLFSMetaObjects(ctx, repository.GarbageCollectLFSMetaObjectsOptions{
|
||||
Logger: logger,
|
||||
AutoFix: autofix,
|
||||
LogDetail: logger.Info,
|
||||
AutoFix: autofix,
|
||||
// Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload
|
||||
// and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby
|
||||
// an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
||||
if len(value) == 0 {
|
||||
return
|
||||
return 0, nil
|
||||
}
|
||||
var n int
|
||||
last := 0
|
||||
@@ -23,24 +23,24 @@ func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
||||
n, err = w.Write(prefix)
|
||||
sum += int64(n)
|
||||
if err != nil {
|
||||
return
|
||||
return sum, err
|
||||
}
|
||||
n, err = w.Write(value[last : last+j+1])
|
||||
sum += int64(n)
|
||||
if err != nil {
|
||||
return
|
||||
return sum, err
|
||||
}
|
||||
last += j + 1
|
||||
}
|
||||
n, err = w.Write(prefix)
|
||||
sum += int64(n)
|
||||
if err != nil {
|
||||
return
|
||||
return sum, err
|
||||
}
|
||||
n, err = w.Write(value[last:])
|
||||
sum += int64(n)
|
||||
if err != nil {
|
||||
return
|
||||
return sum, err
|
||||
}
|
||||
n, err = w.Write([]byte("\n"))
|
||||
sum += int64(n)
|
||||
@@ -51,8 +51,8 @@ func wrapNewlines(w io.Writer, prefix, value []byte) (sum int64, err error) {
|
||||
type Event struct {
|
||||
// Name represents the value of the event: tag in the stream
|
||||
Name string
|
||||
// Data is either JSONified []byte or interface{} that can be JSONd
|
||||
Data interface{}
|
||||
// Data is either JSONified []byte or any that can be JSONd
|
||||
Data any
|
||||
// ID represents the ID of an event
|
||||
ID string
|
||||
// Retry tells the receiver only to attempt to reconnect to the source after this time
|
||||
|
||||
@@ -148,27 +148,25 @@ func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
|
||||
func ReadBatchLine(rd *bufio.Reader) (sha []byte, typ string, size int64, err error) {
|
||||
typ, err = rd.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
return sha, typ, size, err
|
||||
}
|
||||
if len(typ) == 1 {
|
||||
typ, err = rd.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
return sha, typ, size, err
|
||||
}
|
||||
}
|
||||
idx := strings.IndexByte(typ, ' ')
|
||||
if idx < 0 {
|
||||
log.Debug("missing space typ: %s", typ)
|
||||
err = ErrNotExist{ID: string(sha)}
|
||||
return
|
||||
return sha, typ, size, ErrNotExist{ID: string(sha)}
|
||||
}
|
||||
sha = []byte(typ[:idx])
|
||||
typ = typ[idx+1:]
|
||||
|
||||
idx = strings.IndexByte(typ, ' ')
|
||||
if idx < 0 {
|
||||
err = ErrNotExist{ID: string(sha)}
|
||||
return
|
||||
return sha, typ, size, ErrNotExist{ID: string(sha)}
|
||||
}
|
||||
|
||||
sizeStr := typ[idx+1 : len(typ)-1]
|
||||
@@ -285,14 +283,12 @@ func ParseTreeLine(rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fn
|
||||
// Read the Mode & fname
|
||||
readBytes, err = rd.ReadSlice('\x00')
|
||||
if err != nil {
|
||||
return
|
||||
return mode, fname, sha, n, err
|
||||
}
|
||||
idx := bytes.IndexByte(readBytes, ' ')
|
||||
if idx < 0 {
|
||||
log.Debug("missing space in readBytes ParseTreeLine: %s", readBytes)
|
||||
|
||||
err = &ErrNotExist{}
|
||||
return
|
||||
return mode, fname, sha, n, &ErrNotExist{}
|
||||
}
|
||||
|
||||
n += idx + 1
|
||||
@@ -319,7 +315,7 @@ func ParseTreeLine(rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fn
|
||||
}
|
||||
n += len(fnameBuf)
|
||||
if err != nil {
|
||||
return
|
||||
return mode, fname, sha, n, err
|
||||
}
|
||||
fnameBuf = fnameBuf[:len(fnameBuf)-1]
|
||||
fname = fnameBuf
|
||||
@@ -331,7 +327,7 @@ func ParseTreeLine(rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fn
|
||||
read, err = rd.Read(shaBuf[idx:20])
|
||||
n += read
|
||||
if err != nil {
|
||||
return
|
||||
return mode, fname, sha, n, err
|
||||
}
|
||||
idx += read
|
||||
}
|
||||
|
||||
@@ -301,6 +301,8 @@ func (c *Command) Run(opts *RunOpts) error {
|
||||
}
|
||||
defer finished()
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
cmd := exec.CommandContext(ctx, c.prog, c.args...)
|
||||
if opts.Env == nil {
|
||||
cmd.Env = os.Environ()
|
||||
@@ -327,7 +329,13 @@ func (c *Command) Run(opts *RunOpts) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil && ctx.Err() != context.DeadlineExceeded {
|
||||
err := cmd.Wait()
|
||||
elapsed := time.Since(startTime)
|
||||
if elapsed > time.Second {
|
||||
log.Debug("slow git.Command.Run: %s (%s)", c, elapsed)
|
||||
}
|
||||
|
||||
if err != nil && ctx.Err() != context.DeadlineExceeded {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -435,7 +435,7 @@ func (c *Commit) GetBranchName() (string, error) {
|
||||
// LoadBranchName load branch name for commit
|
||||
func (c *Commit) LoadBranchName() (err error) {
|
||||
if len(c.Branch) != 0 {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Branch, err = c.GetBranchName()
|
||||
|
||||
@@ -177,7 +177,7 @@ func GetLastCommitForPaths(ctx context.Context, cache *LastCommitCache, c cgobje
|
||||
refSha := c.ID().String()
|
||||
|
||||
// We do a tree traversal with nodes sorted by commit time
|
||||
heap := binaryheap.NewWith(func(a, b interface{}) int {
|
||||
heap := binaryheap.NewWith(func(a, b any) int {
|
||||
if a.(*commitAndPaths).commit.CommitTime().Before(b.(*commitAndPaths).commit.CommitTime()) {
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ func TestParser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func pretty(v interface{}) string {
|
||||
func pretty(v any) string {
|
||||
data, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
// shouldn't happen
|
||||
|
||||
+2
-3
@@ -114,7 +114,7 @@ func VersionInfo() string {
|
||||
return "(git not found)"
|
||||
}
|
||||
format := "%s"
|
||||
args := []interface{}{gitVersion.Original()}
|
||||
args := []any{gitVersion.Original()}
|
||||
// Since git wire protocol has been released from git v2.18
|
||||
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
|
||||
format += ", Wire Protocol %s Enabled"
|
||||
@@ -171,7 +171,7 @@ func InitFull(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
if err = InitSimple(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// when git works with gnupg (commit signing), there should be a stable home for gnupg commands
|
||||
@@ -188,7 +188,6 @@ func InitFull(ctx context.Context) (err error) {
|
||||
if CheckGitVersionAtLeast("2.9") == nil {
|
||||
globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=")
|
||||
}
|
||||
|
||||
SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
// Cache represents a caching interface
|
||||
type Cache interface {
|
||||
// Put puts value into cache with key and expire time.
|
||||
Put(key string, val interface{}, timeout int64) error
|
||||
Put(key string, val any, timeout int64) error
|
||||
// Get gets cached value by given key.
|
||||
Get(key string) interface{}
|
||||
Get(key string) any
|
||||
}
|
||||
|
||||
func getCacheKey(repoPath, commitID, entryPath string) string {
|
||||
|
||||
@@ -87,7 +87,7 @@ func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError
|
||||
// Close this repository, in particular close the underlying gogitStorage if this is not nil
|
||||
func (repo *Repository) Close() (err error) {
|
||||
if repo == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
if repo.batchCancel != nil {
|
||||
repo.batchCancel()
|
||||
|
||||
@@ -48,7 +48,7 @@ func (repo *Repository) readTreeToIndex(id SHA1, indexFilename ...string) error
|
||||
func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (filename, tmpDir string, cancel context.CancelFunc, err error) {
|
||||
tmpDir, err = os.MkdirTemp("", "index")
|
||||
if err != nil {
|
||||
return
|
||||
return filename, tmpDir, cancel, err
|
||||
}
|
||||
|
||||
filename = filepath.Join(tmpDir, ".tmp-index")
|
||||
|
||||
@@ -43,12 +43,13 @@ func (s *Signature) Decode(b []byte) {
|
||||
//
|
||||
// but without the "author " at the beginning (this method should)
|
||||
// be used for author and committer.
|
||||
// FIXME: there are a lot of "return sig, err" (but the err is also nil), that's the old behavior, to avoid breaking
|
||||
func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
|
||||
sig = new(Signature)
|
||||
emailStart := bytes.LastIndexByte(line, '<')
|
||||
emailEnd := bytes.LastIndexByte(line, '>')
|
||||
if emailStart == -1 || emailEnd == -1 || emailEnd < emailStart {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
|
||||
if emailStart > 0 { // Empty name has already occurred, even if it shouldn't
|
||||
@@ -58,7 +59,7 @@ func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
|
||||
|
||||
hasTime := emailEnd+2 < len(line)
|
||||
if !hasTime {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
|
||||
// Check date format.
|
||||
@@ -66,7 +67,7 @@ func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
|
||||
if firstChar >= 48 && firstChar <= 57 {
|
||||
idx := bytes.IndexByte(line[emailEnd+2:], ' ')
|
||||
if idx < 0 {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
|
||||
timestring := string(line[emailEnd+2 : emailEnd+2+idx])
|
||||
@@ -75,14 +76,14 @@ func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
|
||||
|
||||
idx += emailEnd + 3
|
||||
if idx >= len(line) || idx+5 > len(line) {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
|
||||
timezone := string(line[idx : idx+5])
|
||||
tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64)
|
||||
tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64)
|
||||
if err1 != nil || err2 != nil {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
if tzhours < 0 {
|
||||
tzmins *= -1
|
||||
@@ -92,7 +93,7 @@ func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
|
||||
} else {
|
||||
sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
|
||||
if err != nil {
|
||||
return
|
||||
return sig, err
|
||||
}
|
||||
}
|
||||
return sig, err
|
||||
|
||||
@@ -15,17 +15,17 @@ import (
|
||||
// ObjectCache provides thread-safe cache operations.
|
||||
type ObjectCache struct {
|
||||
lock sync.RWMutex
|
||||
cache map[string]interface{}
|
||||
cache map[string]any
|
||||
}
|
||||
|
||||
func newObjectCache() *ObjectCache {
|
||||
return &ObjectCache{
|
||||
cache: make(map[string]interface{}, 10),
|
||||
cache: make(map[string]any, 10),
|
||||
}
|
||||
}
|
||||
|
||||
// Set add obj to cache
|
||||
func (oc *ObjectCache) Set(id string, obj interface{}) {
|
||||
func (oc *ObjectCache) Set(id string, obj any) {
|
||||
oc.lock.Lock()
|
||||
defer oc.lock.Unlock()
|
||||
|
||||
@@ -33,7 +33,7 @@ func (oc *ObjectCache) Set(id string, obj interface{}) {
|
||||
}
|
||||
|
||||
// Get get cached obj by id
|
||||
func (oc *ObjectCache) Get(id string) (interface{}, bool) {
|
||||
func (oc *ObjectCache) Get(id string) (any, bool) {
|
||||
oc.lock.RLock()
|
||||
defer oc.lock.RUnlock()
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ func (g *Manager) Err() error {
|
||||
}
|
||||
|
||||
// Value allows the manager to be viewed as a context.Context done at Terminate
|
||||
func (g *Manager) Value(key interface{}) interface{} {
|
||||
func (g *Manager) Value(key any) any {
|
||||
return g.managerCtx.Value(key)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package html
|
||||
|
||||
// ParseSizeAndClass get size and class from string with default values
|
||||
// If present, "others" expects the new size first and then the classes to use
|
||||
func ParseSizeAndClass(defaultSize int, defaultClass string, others ...interface{}) (int, string) {
|
||||
func ParseSizeAndClass(defaultSize int, defaultClass string, others ...any) (int, string) {
|
||||
if len(others) == 0 {
|
||||
return defaultSize, defaultClass
|
||||
}
|
||||
|
||||
@@ -70,11 +70,11 @@ func checkIfNoneMatchIsValid(req *http.Request, etag string) bool {
|
||||
|
||||
// HandleGenericETagTimeCache handles ETag-based caching with Last-Modified caching for a HTTP request.
|
||||
// It returns true if the request was handled.
|
||||
func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag string, lastModified time.Time) (handled bool) {
|
||||
func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag string, lastModified *time.Time) (handled bool) {
|
||||
if len(etag) > 0 {
|
||||
w.Header().Set("Etag", etag)
|
||||
}
|
||||
if !lastModified.IsZero() {
|
||||
if lastModified != nil && !lastModified.IsZero() {
|
||||
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
|
||||
return true
|
||||
}
|
||||
}
|
||||
if !lastModified.IsZero() {
|
||||
if lastModified != nil && !lastModified.IsZero() {
|
||||
ifModifiedSince := req.Header.Get("If-Modified-Since")
|
||||
if ifModifiedSince != "" {
|
||||
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
|
||||
|
||||
@@ -101,7 +101,7 @@ func (r *Request) Param(key, value string) *Request {
|
||||
|
||||
// Body adds request raw body.
|
||||
// it supports string and []byte.
|
||||
func (r *Request) Body(data interface{}) *Request {
|
||||
func (r *Request) Body(data any) *Request {
|
||||
switch t := data.(type) {
|
||||
case string:
|
||||
bf := bytes.NewBufferString(t)
|
||||
|
||||
@@ -206,7 +206,7 @@ func ServeContentByReader(r *http.Request, w http.ResponseWriter, filePath strin
|
||||
_, _ = io.CopyN(w, reader, partialLength) // just like http.ServeContent, not necessary to handle the error
|
||||
}
|
||||
|
||||
func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath string, modTime time.Time, reader io.ReadSeeker) {
|
||||
func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath string, modTime *time.Time, reader io.ReadSeeker) {
|
||||
buf := make([]byte, mimeDetectionBufferLen)
|
||||
n, err := util.ReadAtMost(reader, buf)
|
||||
if err != nil {
|
||||
@@ -221,5 +221,8 @@ func ServeContentByReadSeeker(r *http.Request, w http.ResponseWriter, filePath s
|
||||
buf = buf[:n]
|
||||
}
|
||||
setServeHeadersByFile(r, w, filePath, buf)
|
||||
http.ServeContent(w, r, path.Base(filePath), modTime, reader)
|
||||
if modTime == nil {
|
||||
modTime = &time.Time{}
|
||||
}
|
||||
http.ServeContent(w, r, path.Base(filePath), *modTime, reader)
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -78,7 +77,7 @@ func TestServeContentByReadSeeker(t *testing.T) {
|
||||
defer seekReader.Close()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
ServeContentByReadSeeker(r, w, "test", time.Time{}, seekReader)
|
||||
ServeContentByReadSeeker(r, w, "test", nil, seekReader)
|
||||
assert.Equal(t, expectedStatusCode, w.Code)
|
||||
if expectedStatusCode == http.StatusPartialContent || expectedStatusCode == http.StatusOK {
|
||||
assert.Equal(t, fmt.Sprint(len(expectedContent)), w.Header().Get("Content-Length"))
|
||||
|
||||
@@ -51,7 +51,7 @@ func numericEqualityQuery(value int64, field string) *query.NumericRangeQuery {
|
||||
}
|
||||
|
||||
func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||
return m.AddCustomTokenFilter(unicodeNormalizeName, map[string]interface{}{
|
||||
return m.AddCustomTokenFilter(unicodeNormalizeName, map[string]any{
|
||||
"type": unicodenorm.Name,
|
||||
"form": unicodenorm.NFC,
|
||||
})
|
||||
@@ -101,7 +101,7 @@ func generateBleveIndexMapping() (mapping.IndexMapping, error) {
|
||||
mapping := bleve.NewIndexMapping()
|
||||
if err := addUnicodeNormalizeTokenFilter(mapping); err != nil {
|
||||
return nil, err
|
||||
} else if err := mapping.AddCustomAnalyzer(repoIndexerAnalyzer, map[string]interface{}{
|
||||
} else if err := mapping.AddCustomAnalyzer(repoIndexerAnalyzer, map[string]any{
|
||||
"type": analyzer_custom.Name,
|
||||
"char_filters": []string{},
|
||||
"tokenizer": unicode.Name,
|
||||
|
||||
@@ -133,7 +133,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro
|
||||
elastic.NewBulkIndexRequest().
|
||||
Index(b.inner.VersionedIndexName()).
|
||||
Id(id).
|
||||
Doc(map[string]interface{}{
|
||||
Doc(map[string]any{
|
||||
"repo_id": repo.ID,
|
||||
"content": string(charset.ToUTF8DropErrors(fileContents)),
|
||||
"commit_id": sha,
|
||||
@@ -234,7 +234,7 @@ func convertResult(searchResult *elastic.SearchResult, kw string, pageSize int)
|
||||
}
|
||||
|
||||
repoID, fileName := internal.ParseIndexerID(hit.Id)
|
||||
res := make(map[string]interface{})
|
||||
res := make(map[string]any)
|
||||
if err := json.Unmarshal(hit.Source, &res); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
@@ -285,7 +285,7 @@ func (b *Indexer) Search(ctx context.Context, repoIDs []int64, language, keyword
|
||||
query := elastic.NewBoolQuery()
|
||||
query = query.Must(kwQuery)
|
||||
if len(repoIDs) > 0 {
|
||||
repoStrs := make([]interface{}, 0, len(repoIDs))
|
||||
repoStrs := make([]any, 0, len(repoIDs))
|
||||
for _, repoID := range repoIDs {
|
||||
repoStrs = append(repoStrs, repoID)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewFlushingBatch(index bleve.Index, maxBatchSize int) *FlushingBatch {
|
||||
}
|
||||
|
||||
// Index add a new index to batch
|
||||
func (b *FlushingBatch) Index(id string, data interface{}) error {
|
||||
func (b *FlushingBatch) Index(id string, data any) error {
|
||||
if err := b.batch.Index(id, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
const (
|
||||
issueIndexerAnalyzer = "issueIndexer"
|
||||
issueIndexerDocType = "issueIndexerDocType"
|
||||
issueIndexerLatestVersion = 2
|
||||
issueIndexerLatestVersion = 3
|
||||
)
|
||||
|
||||
// numericEqualityQuery a numeric equality query for the given value and field
|
||||
@@ -45,7 +45,7 @@ func newMatchPhraseQuery(matchPhrase, field, analyzer string) *query.MatchPhrase
|
||||
const unicodeNormalizeName = "unicodeNormalize"
|
||||
|
||||
func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||
return m.AddCustomTokenFilter(unicodeNormalizeName, map[string]interface{}{
|
||||
return m.AddCustomTokenFilter(unicodeNormalizeName, map[string]any{
|
||||
"type": unicodenorm.Name,
|
||||
"form": unicodenorm.NFC,
|
||||
})
|
||||
@@ -67,19 +67,20 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
|
||||
docMapping := bleve.NewDocumentMapping()
|
||||
|
||||
numericFieldMapping := bleve.NewNumericFieldMapping()
|
||||
numericFieldMapping.Store = false
|
||||
numericFieldMapping.IncludeInAll = false
|
||||
docMapping.AddFieldMappingsAt("RepoID", numericFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("repo_id", numericFieldMapping)
|
||||
|
||||
textFieldMapping := bleve.NewTextFieldMapping()
|
||||
textFieldMapping.Store = false
|
||||
textFieldMapping.IncludeInAll = false
|
||||
docMapping.AddFieldMappingsAt("Title", textFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("Content", textFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("Comments", textFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("title", textFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("content", textFieldMapping)
|
||||
docMapping.AddFieldMappingsAt("comments", textFieldMapping)
|
||||
|
||||
if err := addUnicodeNormalizeTokenFilter(mapping); err != nil {
|
||||
return nil, err
|
||||
} else if err = mapping.AddCustomAnalyzer(issueIndexerAnalyzer, map[string]interface{}{
|
||||
} else if err = mapping.AddCustomAnalyzer(issueIndexerAnalyzer, map[string]any{
|
||||
"type": custom.Name,
|
||||
"char_filters": []string{},
|
||||
"tokenizer": unicode.Name,
|
||||
@@ -91,6 +92,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
|
||||
mapping.DefaultAnalyzer = issueIndexerAnalyzer
|
||||
mapping.AddDocumentMapping(issueIndexerDocType, docMapping)
|
||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||
mapping.DefaultMapping = bleve.NewDocumentDisabledMapping() // disable default mapping, avoid indexing unexpected structs
|
||||
|
||||
return mapping, nil
|
||||
}
|
||||
@@ -116,17 +118,7 @@ func NewIndexer(indexDir string) *Indexer {
|
||||
func (b *Indexer) Index(_ context.Context, issues []*internal.IndexerData) error {
|
||||
batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize)
|
||||
for _, issue := range issues {
|
||||
if err := batch.Index(indexer_internal.Base36(issue.ID), struct {
|
||||
RepoID int64
|
||||
Title string
|
||||
Content string
|
||||
Comments []string
|
||||
}{
|
||||
RepoID: issue.RepoID,
|
||||
Title: issue.Title,
|
||||
Content: issue.Content,
|
||||
Comments: issue.Comments,
|
||||
}); err != nil {
|
||||
if err := batch.Index(indexer_internal.Base36(issue.ID), (*IndexerData)(issue)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -146,10 +138,10 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
|
||||
|
||||
// Search searches for issues by given conditions.
|
||||
// Returns the matching issue IDs
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
|
||||
var repoQueriesP []*query.NumericRangeQuery
|
||||
for _, repoID := range repoIDs {
|
||||
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "RepoID"))
|
||||
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "repo_id"))
|
||||
}
|
||||
repoQueries := make([]query.Query, len(repoQueriesP))
|
||||
for i, v := range repoQueriesP {
|
||||
@@ -159,9 +151,9 @@ func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, l
|
||||
indexerQuery := bleve.NewConjunctionQuery(
|
||||
bleve.NewDisjunctionQuery(repoQueries...),
|
||||
bleve.NewDisjunctionQuery(
|
||||
newMatchPhraseQuery(keyword, "Title", issueIndexerAnalyzer),
|
||||
newMatchPhraseQuery(keyword, "Content", issueIndexerAnalyzer),
|
||||
newMatchPhraseQuery(keyword, "Comments", issueIndexerAnalyzer),
|
||||
newMatchPhraseQuery(keyword, "title", issueIndexerAnalyzer),
|
||||
newMatchPhraseQuery(keyword, "content", issueIndexerAnalyzer),
|
||||
newMatchPhraseQuery(keyword, "comments", issueIndexerAnalyzer),
|
||||
))
|
||||
search := bleve.NewSearchRequestOptions(indexerQuery, limit, start, false)
|
||||
search.SortBy([]string{"-_score"})
|
||||
|
||||
@@ -77,7 +77,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, kw := range keywords {
|
||||
res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0)
|
||||
res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0, "")
|
||||
assert.NoError(t, err)
|
||||
|
||||
ids := make([]int64, 0, len(res.Hits))
|
||||
|
||||
@@ -36,7 +36,7 @@ func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
|
||||
}
|
||||
|
||||
// Search searches for issues
|
||||
func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
|
||||
func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
|
||||
total, ids, err := issues_model.SearchIssueIDsByKeyword(ctx, kw, repoIDs, limit, start)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -76,7 +76,7 @@ func (b *Indexer) Index(ctx context.Context, issues []*internal.IndexerData) err
|
||||
_, err := b.inner.Client.Index().
|
||||
Index(b.inner.VersionedIndexName()).
|
||||
Id(fmt.Sprintf("%d", issue.ID)).
|
||||
BodyJson(map[string]interface{}{
|
||||
BodyJson(map[string]any{
|
||||
"id": issue.ID,
|
||||
"repo_id": issue.RepoID,
|
||||
"title": issue.Title,
|
||||
@@ -93,7 +93,7 @@ func (b *Indexer) Index(ctx context.Context, issues []*internal.IndexerData) err
|
||||
elastic.NewBulkIndexRequest().
|
||||
Index(b.inner.VersionedIndexName()).
|
||||
Id(fmt.Sprintf("%d", issue.ID)).
|
||||
Doc(map[string]interface{}{
|
||||
Doc(map[string]any{
|
||||
"id": issue.ID,
|
||||
"repo_id": issue.RepoID,
|
||||
"title": issue.Title,
|
||||
@@ -140,12 +140,12 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
|
||||
|
||||
// Search searches for issues by given conditions.
|
||||
// Returns the matching issue IDs
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
|
||||
kwQuery := elastic.NewMultiMatchQuery(keyword, "title", "content", "comments")
|
||||
query := elastic.NewBoolQuery()
|
||||
query = query.Must(kwQuery)
|
||||
if len(repoIDs) > 0 {
|
||||
repoStrs := make([]interface{}, 0, len(repoIDs))
|
||||
repoStrs := make([]any, 0, len(repoIDs))
|
||||
for _, repoID := range repoIDs {
|
||||
repoStrs = append(repoStrs, repoID)
|
||||
}
|
||||
|
||||
@@ -242,12 +242,18 @@ func UpdateIssueIndexer(issue *issues_model.Issue) {
|
||||
comments = append(comments, comment.Content)
|
||||
}
|
||||
}
|
||||
issueType := "issue"
|
||||
if issue.IsPull {
|
||||
issueType = "pull"
|
||||
}
|
||||
indexerData := &internal.IndexerData{
|
||||
ID: issue.ID,
|
||||
RepoID: issue.RepoID,
|
||||
Title: issue.Title,
|
||||
Content: issue.Content,
|
||||
Comments: comments,
|
||||
ID: issue.ID,
|
||||
RepoID: issue.RepoID,
|
||||
State: string(issue.State()),
|
||||
IssueType: issueType,
|
||||
Title: issue.Title,
|
||||
Content: issue.Content,
|
||||
Comments: comments,
|
||||
}
|
||||
log.Debug("Adding to channel: %v", indexerData)
|
||||
if err := issueIndexerQueue.Push(indexerData); err != nil {
|
||||
@@ -278,10 +284,10 @@ func DeleteRepoIssueIndexer(ctx context.Context, repo *repo_model.Repository) {
|
||||
|
||||
// SearchIssuesByKeyword search issue ids by keywords and repo id
|
||||
// WARNNING: You have to ensure user have permission to visit repoIDs' issues
|
||||
func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword string) ([]int64, error) {
|
||||
func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword, state string) ([]int64, error) {
|
||||
var issueIDs []int64
|
||||
indexer := *globalIndexer.Load()
|
||||
res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0)
|
||||
res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -50,19 +50,19 @@ func TestBleveSearchIssues(t *testing.T) {
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
|
||||
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{2}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{1}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{1}, ids)
|
||||
}
|
||||
@@ -73,19 +73,19 @@ func TestDBSearchIssues(t *testing.T) {
|
||||
setting.Indexer.IssueType = "db"
|
||||
InitIssueIndexer(true)
|
||||
|
||||
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
|
||||
ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{2}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{1}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
|
||||
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
|
||||
ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, []int64{1}, ids)
|
||||
}
|
||||
@@ -15,7 +15,7 @@ type Indexer interface {
|
||||
internal.Indexer
|
||||
Index(ctx context.Context, issue []*IndexerData) error
|
||||
Delete(ctx context.Context, ids ...int64) error
|
||||
Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error)
|
||||
Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error)
|
||||
}
|
||||
|
||||
// NewDummyIndexer returns a dummy indexer
|
||||
@@ -37,6 +37,6 @@ func (d *dummyIndexer) Delete(ctx context.Context, ids ...int64) error {
|
||||
return fmt.Errorf("indexer is not ready")
|
||||
}
|
||||
|
||||
func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error) {
|
||||
func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error) {
|
||||
return nil, fmt.Errorf("indexer is not ready")
|
||||
}
|
||||
@@ -5,13 +5,15 @@ package internal
|
||||
|
||||
// IndexerData data stored in the issue indexer
|
||||
type IndexerData struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Comments []string `json:"comments"`
|
||||
IsDelete bool `json:"is_delete"`
|
||||
IDs []int64 `json:"ids"`
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
State string `json:"state"` // open, closed, all
|
||||
IssueType string `json:"type"` // issue or pull
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Comments []string `json:"comments"`
|
||||
IsDelete bool `json:"is_delete"`
|
||||
IDs []int64 `json:"ids"`
|
||||
}
|
||||
|
||||
// Match represents on search result
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
issueIndexerLatestVersion = 0
|
||||
issueIndexerLatestVersion = 1
|
||||
)
|
||||
|
||||
var _ internal.Indexer = &Indexer{}
|
||||
@@ -70,12 +70,19 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
|
||||
|
||||
// Search searches for issues by given conditions.
|
||||
// Returns the matching issue IDs
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
|
||||
func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
|
||||
repoFilters := make([]string, 0, len(repoIDs))
|
||||
for _, repoID := range repoIDs {
|
||||
repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
|
||||
}
|
||||
filter := strings.Join(repoFilters, " OR ")
|
||||
if state == "open" || state == "closed" {
|
||||
if filter != "" {
|
||||
filter = "(" + filter + ") AND state = " + state
|
||||
} else {
|
||||
filter = "state = " + state
|
||||
}
|
||||
}
|
||||
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
|
||||
Filter: filter,
|
||||
Limit: int64(limit),
|
||||
@@ -88,7 +95,7 @@ func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, l
|
||||
hits := make([]internal.Match, 0, len(searchRes.Hits))
|
||||
for _, hit := range searchRes.Hits {
|
||||
hits = append(hits, internal.Match{
|
||||
ID: int64(hit.(map[string]interface{})["id"].(float64)),
|
||||
ID: int64(hit.(map[string]any)["id"].(float64)),
|
||||
})
|
||||
}
|
||||
return &internal.SearchResult{
|
||||
|
||||
@@ -151,7 +151,7 @@ func validateOptions(field *api.IssueFormField, idx int) error {
|
||||
}
|
||||
position := newErrorPosition(idx, field.Type)
|
||||
|
||||
options, ok := field.Attributes["options"].([]interface{})
|
||||
options, ok := field.Attributes["options"].([]any)
|
||||
if !ok || len(options) == 0 {
|
||||
return position.Errorf("'options' is required and should be a array")
|
||||
}
|
||||
@@ -164,7 +164,7 @@ func validateOptions(field *api.IssueFormField, idx int) error {
|
||||
return position.Errorf("should be a string")
|
||||
}
|
||||
case api.IssueFormFieldTypeCheckboxes:
|
||||
opt, ok := option.(map[string]interface{})
|
||||
opt, ok := option.(map[string]any)
|
||||
if !ok {
|
||||
return position.Errorf("should be a dictionary")
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func validateOptions(field *api.IssueFormField, idx int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStringItem(position errorPosition, m map[string]interface{}, required bool, names ...string) error {
|
||||
func validateStringItem(position errorPosition, m map[string]any, required bool, names ...string) error {
|
||||
for _, name := range names {
|
||||
v, ok := m[name]
|
||||
if !ok {
|
||||
@@ -202,7 +202,7 @@ func validateStringItem(position errorPosition, m map[string]interface{}, requir
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBoolItem(position errorPosition, m map[string]interface{}, names ...string) error {
|
||||
func validateBoolItem(position errorPosition, m map[string]any, names ...string) error {
|
||||
for _, name := range names {
|
||||
v, ok := m[name]
|
||||
if !ok {
|
||||
@@ -217,7 +217,7 @@ func validateBoolItem(position errorPosition, m map[string]interface{}, names ..
|
||||
|
||||
type errorPosition string
|
||||
|
||||
func (p errorPosition) Errorf(format string, a ...interface{}) error {
|
||||
func (p errorPosition) Errorf(format string, a ...any) error {
|
||||
return fmt.Errorf(string(p)+": "+format, a...)
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ func (f *valuedField) Value() string {
|
||||
}
|
||||
|
||||
func (f *valuedField) Options() []*valuedOption {
|
||||
if options, ok := f.Attributes["options"].([]interface{}); ok {
|
||||
if options, ok := f.Attributes["options"].([]any); ok {
|
||||
ret := make([]*valuedOption, 0, len(options))
|
||||
for i, option := range options {
|
||||
ret = append(ret, &valuedOption{
|
||||
@@ -348,7 +348,7 @@ func (f *valuedField) Options() []*valuedOption {
|
||||
|
||||
type valuedOption struct {
|
||||
index int
|
||||
data interface{}
|
||||
data any
|
||||
field *valuedField
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ func (o *valuedOption) Label() string {
|
||||
return label
|
||||
}
|
||||
case api.IssueFormFieldTypeCheckboxes:
|
||||
if vs, ok := o.data.(map[string]interface{}); ok {
|
||||
if vs, ok := o.data.(map[string]any); ok {
|
||||
if v, ok := vs["label"].(string); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -387,34 +387,34 @@ body:
|
||||
{
|
||||
Type: "markdown",
|
||||
ID: "id1",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"value": "Value of the markdown",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "textarea",
|
||||
ID: "id2",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"label": "Label of textarea",
|
||||
"description": "Description of textarea",
|
||||
"placeholder": "Placeholder of textarea",
|
||||
"value": "Value of textarea",
|
||||
"render": "bash",
|
||||
},
|
||||
Validations: map[string]interface{}{
|
||||
Validations: map[string]any{
|
||||
"required": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "input",
|
||||
ID: "id3",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"label": "Label of input",
|
||||
"description": "Description of input",
|
||||
"placeholder": "Placeholder of input",
|
||||
"value": "Value of input",
|
||||
},
|
||||
Validations: map[string]interface{}{
|
||||
Validations: map[string]any{
|
||||
"required": true,
|
||||
"is_number": true,
|
||||
"regex": "[a-zA-Z0-9]+",
|
||||
@@ -423,30 +423,30 @@ body:
|
||||
{
|
||||
Type: "dropdown",
|
||||
ID: "id4",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"label": "Label of dropdown",
|
||||
"description": "Description of dropdown",
|
||||
"multiple": true,
|
||||
"options": []interface{}{
|
||||
"options": []any{
|
||||
"Option 1 of dropdown",
|
||||
"Option 2 of dropdown",
|
||||
"Option 3 of dropdown",
|
||||
},
|
||||
},
|
||||
Validations: map[string]interface{}{
|
||||
Validations: map[string]any{
|
||||
"required": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "checkboxes",
|
||||
ID: "id5",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"label": "Label of checkboxes",
|
||||
"description": "Description of checkboxes",
|
||||
"options": []interface{}{
|
||||
map[string]interface{}{"label": "Option 1 of checkboxes", "required": true},
|
||||
map[string]interface{}{"label": "Option 2 of checkboxes", "required": false},
|
||||
map[string]interface{}{"label": "Option 3 of checkboxes", "required": true},
|
||||
"options": []any{
|
||||
map[string]any{"label": "Option 1 of checkboxes", "required": true},
|
||||
map[string]any{"label": "Option 2 of checkboxes", "required": false},
|
||||
map[string]any{"label": "Option 3 of checkboxes", "required": true},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -479,7 +479,7 @@ body:
|
||||
{
|
||||
Type: "markdown",
|
||||
ID: "id1",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"value": "Value of the markdown",
|
||||
},
|
||||
},
|
||||
@@ -512,7 +512,7 @@ body:
|
||||
{
|
||||
Type: "markdown",
|
||||
ID: "id1",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"value": "Value of the markdown",
|
||||
},
|
||||
},
|
||||
@@ -545,7 +545,7 @@ body:
|
||||
{
|
||||
Type: "markdown",
|
||||
ID: "id1",
|
||||
Attributes: map[string]interface{}{
|
||||
Attributes: map[string]any{
|
||||
"value": "Value of the markdown",
|
||||
},
|
||||
},
|
||||
|
||||
+12
-12
@@ -15,18 +15,18 @@ import (
|
||||
|
||||
// Encoder represents an encoder for json
|
||||
type Encoder interface {
|
||||
Encode(v interface{}) error
|
||||
Encode(v any) error
|
||||
}
|
||||
|
||||
// Decoder represents a decoder for json
|
||||
type Decoder interface {
|
||||
Decode(v interface{}) error
|
||||
Decode(v any) error
|
||||
}
|
||||
|
||||
// Interface represents an interface to handle json data
|
||||
type Interface interface {
|
||||
Marshal(v interface{}) ([]byte, error)
|
||||
Unmarshal(data []byte, v interface{}) error
|
||||
Marshal(v any) ([]byte, error)
|
||||
Unmarshal(data []byte, v any) error
|
||||
NewEncoder(writer io.Writer) Encoder
|
||||
NewDecoder(reader io.Reader) Decoder
|
||||
Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
|
||||
@@ -44,12 +44,12 @@ var (
|
||||
type StdJSON struct{}
|
||||
|
||||
// Marshal implements Interface
|
||||
func (StdJSON) Marshal(v interface{}) ([]byte, error) {
|
||||
func (StdJSON) Marshal(v any) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
// Unmarshal implements Interface
|
||||
func (StdJSON) Unmarshal(data []byte, v interface{}) error {
|
||||
func (StdJSON) Unmarshal(data []byte, v any) error {
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
@@ -74,12 +74,12 @@ type JSONiter struct {
|
||||
}
|
||||
|
||||
// Marshal implements Interface
|
||||
func (j JSONiter) Marshal(v interface{}) ([]byte, error) {
|
||||
func (j JSONiter) Marshal(v any) ([]byte, error) {
|
||||
return j.API.Marshal(v)
|
||||
}
|
||||
|
||||
// Unmarshal implements Interface
|
||||
func (j JSONiter) Unmarshal(data []byte, v interface{}) error {
|
||||
func (j JSONiter) Unmarshal(data []byte, v any) error {
|
||||
return j.API.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
@@ -99,12 +99,12 @@ func (j JSONiter) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) e
|
||||
}
|
||||
|
||||
// Marshal converts object as bytes
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
func Marshal(v any) ([]byte, error) {
|
||||
return DefaultJSONHandler.Marshal(v)
|
||||
}
|
||||
|
||||
// Unmarshal decodes object from bytes
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
func Unmarshal(data []byte, v any) error {
|
||||
return DefaultJSONHandler.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
||||
}
|
||||
|
||||
// MarshalIndent copied from encoding/json
|
||||
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
|
||||
b, err := Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -144,7 +144,7 @@ func Valid(data []byte) bool {
|
||||
|
||||
// UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's
|
||||
// possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe.
|
||||
func UnmarshalHandleDoubleEncode(bs []byte, v interface{}) error {
|
||||
func UnmarshalHandleDoubleEncode(bs []byte, v any) error {
|
||||
err := json.Unmarshal(bs, v)
|
||||
if err != nil {
|
||||
ok := true
|
||||
|
||||
@@ -120,7 +120,7 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
|
||||
isExternal = true
|
||||
}
|
||||
|
||||
links := make([]interface{}, len(indices))
|
||||
links := make([]any, len(indices))
|
||||
for i, index := range indices {
|
||||
links[i] = numericIssueLink(util.URLJoin(TestRepoURL, path), "ref-issue", index, marker)
|
||||
}
|
||||
@@ -204,7 +204,7 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
|
||||
|
||||
// alphanumeric: render inputs with valid mentions
|
||||
test := func(s, expectedFmt string, names ...string) {
|
||||
links := make([]interface{}, len(names))
|
||||
links := make([]any, len(names))
|
||||
for i, name := range names {
|
||||
links[i] = externalIssueLink("https://someurl.com/someUser/someRepo/", "ref-issue ref-external-issue", name)
|
||||
}
|
||||
@@ -226,7 +226,7 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
|
||||
test := func(s, expectedFmt, pattern string, ids, names []string) {
|
||||
metas := regexpMetas
|
||||
metas["regexp"] = pattern
|
||||
links := make([]interface{}, len(ids))
|
||||
links := make([]any, len(ids))
|
||||
for i, id := range ids {
|
||||
links[i] = link(util.URLJoin("https://someurl.com/someUser/someRepo/", id), "ref-issue ref-external-issue", names[i])
|
||||
}
|
||||
|
||||
@@ -55,14 +55,14 @@ func isYAMLSeparator(line []byte) bool {
|
||||
|
||||
// ExtractMetadata consumes a markdown file, parses YAML frontmatter,
|
||||
// and returns the frontmatter metadata separated from the markdown content
|
||||
func ExtractMetadata(contents string, out interface{}) (string, error) {
|
||||
func ExtractMetadata(contents string, out any) (string, error) {
|
||||
body, err := ExtractMetadataBytes([]byte(contents), out)
|
||||
return string(body), err
|
||||
}
|
||||
|
||||
// ExtractMetadata consumes a markdown file, parses YAML frontmatter,
|
||||
// and returns the frontmatter metadata separated from the markdown content
|
||||
func ExtractMetadataBytes(contents []byte, out interface{}) ([]byte, error) {
|
||||
func ExtractMetadataBytes(contents []byte, out any) ([]byte, error) {
|
||||
var front, body []byte
|
||||
|
||||
start, end := 0, len(contents)
|
||||
|
||||
@@ -24,7 +24,7 @@ type Comment struct {
|
||||
Updated time.Time
|
||||
Content string
|
||||
Reactions []*Reaction
|
||||
Meta map[string]interface{} `yaml:"meta,omitempty"` // see models/issues/comment.go for fields in Comment struct
|
||||
Meta map[string]any `yaml:"meta,omitempty"` // see models/issues/comment.go for fields in Comment struct
|
||||
}
|
||||
|
||||
// GetExternalName ExternalUserMigrated interface
|
||||
|
||||
@@ -34,4 +34,4 @@ type DownloaderFactory interface {
|
||||
}
|
||||
|
||||
// DownloaderContext has opaque information only relevant to a given downloader
|
||||
type DownloaderContext interface{}
|
||||
type DownloaderContext any
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// Load project data from file, with optional validation
|
||||
func Load(filename string, data interface{}, validation bool) error {
|
||||
func Load(filename string, data any, validation bool) error {
|
||||
isJSON := strings.HasSuffix(filename, ".json")
|
||||
|
||||
bs, err := os.ReadFile(filename)
|
||||
@@ -34,7 +34,7 @@ func Load(filename string, data interface{}, validation bool) error {
|
||||
return unmarshal(bs, data, isJSON)
|
||||
}
|
||||
|
||||
func unmarshal(bs []byte, data interface{}, isJSON bool) error {
|
||||
func unmarshal(bs []byte, data any, isJSON bool) error {
|
||||
if isJSON {
|
||||
return json.Unmarshal(bs, data)
|
||||
}
|
||||
@@ -47,8 +47,8 @@ func getSchema(filename string) (*jsonschema.Schema, error) {
|
||||
return c.Compile(filename)
|
||||
}
|
||||
|
||||
func validate(bs []byte, datatype interface{}, isJSON bool) error {
|
||||
var v interface{}
|
||||
func validate(bs []byte, datatype any, isJSON bool) error {
|
||||
var v any
|
||||
err := unmarshal(bs, &v, isJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -81,11 +81,11 @@ func validate(bs []byte, datatype interface{}, isJSON bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func toStringKeys(val interface{}) (interface{}, error) {
|
||||
func toStringKeys(val any) (any, error) {
|
||||
var err error
|
||||
switch val := val.(type) {
|
||||
case map[string]interface{}:
|
||||
m := make(map[string]interface{})
|
||||
case map[string]any:
|
||||
m := make(map[string]any)
|
||||
for k, v := range val {
|
||||
m[k], err = toStringKeys(v)
|
||||
if err != nil {
|
||||
@@ -93,8 +93,8 @@ func toStringKeys(val interface{}) (interface{}, error) {
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
case []interface{}:
|
||||
l := make([]interface{}, len(val))
|
||||
case []any:
|
||||
l := make([]any, len(val))
|
||||
for i, v := range val {
|
||||
l[i], err = toStringKeys(v)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package migration
|
||||
|
||||
// Messenger is a formatting function similar to i18n.Tr
|
||||
type Messenger func(key string, args ...interface{})
|
||||
type Messenger func(key string, args ...any)
|
||||
|
||||
// NilMessenger represents an empty formatting function
|
||||
func NilMessenger(string, ...interface{}) {}
|
||||
func NilMessenger(string, ...any) {}
|
||||
@@ -71,7 +71,7 @@ func valToTimeDuration(vs []string) (result time.Duration) {
|
||||
result = time.Duration(val)
|
||||
}
|
||||
if err == nil {
|
||||
return
|
||||
return result
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
@@ -54,7 +54,7 @@ func (m *Manager) GetLevelDB(connection string) (db *leveldb.DB, err error) {
|
||||
// Because we want associate any goroutines created by this call to the main nosqldb context we need to
|
||||
// wrap this in a goroutine labelled with the nosqldb context
|
||||
done := make(chan struct{})
|
||||
var recovered interface{}
|
||||
var recovered any
|
||||
go func() {
|
||||
defer func() {
|
||||
recovered = recover()
|
||||
|
||||
@@ -47,7 +47,7 @@ func (m *Manager) GetRedisClient(connection string) (client redis.UniversalClien
|
||||
// Because we want associate any goroutines created by this call to the main nosqldb context we need to
|
||||
// wrap this in a goroutine labelled with the nosqldb context
|
||||
done := make(chan struct{})
|
||||
var recovered interface{}
|
||||
var recovered any
|
||||
go func() {
|
||||
defer func() {
|
||||
recovered = recover()
|
||||
|
||||
@@ -38,18 +38,18 @@ type Package struct {
|
||||
|
||||
// Metadata represents the metadata of a Composer package
|
||||
type Metadata struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
License Licenses `json:"license,omitempty"`
|
||||
Authors []Author `json:"authors,omitempty"`
|
||||
Autoload map[string]interface{} `json:"autoload,omitempty"`
|
||||
AutoloadDev map[string]interface{} `json:"autoload-dev,omitempty"`
|
||||
Extra map[string]interface{} `json:"extra,omitempty"`
|
||||
Require map[string]string `json:"require,omitempty"`
|
||||
RequireDev map[string]string `json:"require-dev,omitempty"`
|
||||
Suggest map[string]string `json:"suggest,omitempty"`
|
||||
Provide map[string]string `json:"provide,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
License Licenses `json:"license,omitempty"`
|
||||
Authors []Author `json:"authors,omitempty"`
|
||||
Autoload map[string]any `json:"autoload,omitempty"`
|
||||
AutoloadDev map[string]any `json:"autoload-dev,omitempty"`
|
||||
Extra map[string]any `json:"extra,omitempty"`
|
||||
Require map[string]string `json:"require,omitempty"`
|
||||
RequireDev map[string]string `json:"require-dev,omitempty"`
|
||||
Suggest map[string]string `json:"suggest,omitempty"`
|
||||
Provide map[string]string `json:"provide,omitempty"`
|
||||
}
|
||||
|
||||
// Licenses represents the licenses of a Composer package
|
||||
|
||||
@@ -5,9 +5,11 @@ package packages
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
@@ -31,6 +33,14 @@ func (s *ContentStore) Get(key BlobHash256Key) (storage.Object, error) {
|
||||
return s.store.Open(KeyToRelativePath(key))
|
||||
}
|
||||
|
||||
func (s *ContentStore) ShouldServeDirect() bool {
|
||||
return setting.Packages.Storage.MinioConfig.ServeDirect
|
||||
}
|
||||
|
||||
func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename string) (*url.URL, error) {
|
||||
return s.store.URL(KeyToRelativePath(key), filename)
|
||||
}
|
||||
|
||||
// FIXME: Workaround to be removed in v1.20
|
||||
// https://github.com/go-gitea/gitea/issues/19586
|
||||
func (s *ContentStore) Has(key BlobHash256Key) error {
|
||||
|
||||
@@ -55,14 +55,14 @@ type Maintainer struct {
|
||||
}
|
||||
|
||||
type Dependency struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
Repository string `json:"repository" yaml:"repository"`
|
||||
Condition string `json:"condition,omitempty" yaml:"condition,omitempty"`
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
|
||||
ImportValues []interface{} `json:"import_values,omitempty" yaml:"import-values,omitempty"`
|
||||
Alias string `json:"alias,omitempty" yaml:"alias,omitempty"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
Repository string `json:"repository" yaml:"repository"`
|
||||
Condition string `json:"condition,omitempty" yaml:"condition,omitempty"`
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`
|
||||
ImportValues []any `json:"import_values,omitempty" yaml:"import-values,omitempty"`
|
||||
Alias string `json:"alias,omitempty" yaml:"alias,omitempty"`
|
||||
}
|
||||
|
||||
// ParseChartArchive parses the metadata of a Helm archive
|
||||
|
||||
@@ -38,12 +38,12 @@ type Package struct {
|
||||
|
||||
// Metadata represents the metadata of a Pub package
|
||||
type Metadata struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
ProjectURL string `json:"project_url,omitempty"`
|
||||
RepositoryURL string `json:"repository_url,omitempty"`
|
||||
DocumentationURL string `json:"documentation_url,omitempty"`
|
||||
Readme string `json:"readme,omitempty"`
|
||||
Pubspec interface{} `json:"pubspec"`
|
||||
Description string `json:"description,omitempty"`
|
||||
ProjectURL string `json:"project_url,omitempty"`
|
||||
RepositoryURL string `json:"repository_url,omitempty"`
|
||||
DocumentationURL string `json:"documentation_url,omitempty"`
|
||||
Readme string `json:"readme,omitempty"`
|
||||
Pubspec any `json:"pubspec"`
|
||||
}
|
||||
|
||||
type pubspecPackage struct {
|
||||
@@ -134,7 +134,7 @@ func ParsePubspecMetadata(r io.Reader) (*Package, error) {
|
||||
p.Repository = ""
|
||||
}
|
||||
|
||||
var pubspec interface{}
|
||||
var pubspec any
|
||||
if err := yaml.Unmarshal(buf, &pubspec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -40,19 +40,19 @@ var (
|
||||
// RubyUserMarshal is a Ruby object that has a marshal_load function.
|
||||
type RubyUserMarshal struct {
|
||||
Name string
|
||||
Value interface{}
|
||||
Value any
|
||||
}
|
||||
|
||||
// RubyUserDef is a Ruby object that has a _load function.
|
||||
type RubyUserDef struct {
|
||||
Name string
|
||||
Value interface{}
|
||||
Value any
|
||||
}
|
||||
|
||||
// RubyObject is a default Ruby object.
|
||||
type RubyObject struct {
|
||||
Name string
|
||||
Member map[string]interface{}
|
||||
Member map[string]any
|
||||
}
|
||||
|
||||
// MarshalEncoder mimics Rubys Marshal class.
|
||||
@@ -71,7 +71,7 @@ func NewMarshalEncoder(w io.Writer) *MarshalEncoder {
|
||||
}
|
||||
|
||||
// Encode encodes the given type
|
||||
func (e *MarshalEncoder) Encode(v interface{}) error {
|
||||
func (e *MarshalEncoder) Encode(v any) error {
|
||||
if _, err := e.w.Write([]byte{majorVersion, minorVersion}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func (e *MarshalEncoder) Encode(v interface{}) error {
|
||||
return e.w.Flush()
|
||||
}
|
||||
|
||||
func (e *MarshalEncoder) marshal(v interface{}) error {
|
||||
func (e *MarshalEncoder) marshal(v any) error {
|
||||
if v == nil {
|
||||
return e.marshalNil()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func TestMinimalEncoder(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value interface{}
|
||||
Value any
|
||||
Expected []byte
|
||||
Error error
|
||||
}{
|
||||
@@ -73,7 +73,7 @@ func TestMinimalEncoder(t *testing.T) {
|
||||
{
|
||||
Value: &RubyObject{
|
||||
Name: "Test",
|
||||
Member: map[string]interface{}{
|
||||
Member: map[string]any{
|
||||
"test": 4,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -65,12 +65,12 @@ type gemspec struct {
|
||||
Version struct {
|
||||
Version string `yaml:"version"`
|
||||
} `yaml:"version"`
|
||||
Platform string `yaml:"platform"`
|
||||
Authors []string `yaml:"authors"`
|
||||
Autorequire interface{} `yaml:"autorequire"`
|
||||
Bindir string `yaml:"bindir"`
|
||||
CertChain []interface{} `yaml:"cert_chain"`
|
||||
Date string `yaml:"date"`
|
||||
Platform string `yaml:"platform"`
|
||||
Authors []string `yaml:"authors"`
|
||||
Autorequire any `yaml:"autorequire"`
|
||||
Bindir string `yaml:"bindir"`
|
||||
CertChain []any `yaml:"cert_chain"`
|
||||
Date string `yaml:"date"`
|
||||
Dependencies []struct {
|
||||
Name string `yaml:"name"`
|
||||
Requirement requirement `yaml:"requirement"`
|
||||
@@ -78,34 +78,34 @@ type gemspec struct {
|
||||
Prerelease bool `yaml:"prerelease"`
|
||||
VersionRequirements requirement `yaml:"version_requirements"`
|
||||
} `yaml:"dependencies"`
|
||||
Description string `yaml:"description"`
|
||||
Executables []string `yaml:"executables"`
|
||||
Extensions []interface{} `yaml:"extensions"`
|
||||
ExtraRdocFiles []string `yaml:"extra_rdoc_files"`
|
||||
Files []string `yaml:"files"`
|
||||
Homepage string `yaml:"homepage"`
|
||||
Licenses []string `yaml:"licenses"`
|
||||
Description string `yaml:"description"`
|
||||
Executables []string `yaml:"executables"`
|
||||
Extensions []any `yaml:"extensions"`
|
||||
ExtraRdocFiles []string `yaml:"extra_rdoc_files"`
|
||||
Files []string `yaml:"files"`
|
||||
Homepage string `yaml:"homepage"`
|
||||
Licenses []string `yaml:"licenses"`
|
||||
Metadata struct {
|
||||
BugTrackerURI string `yaml:"bug_tracker_uri"`
|
||||
ChangelogURI string `yaml:"changelog_uri"`
|
||||
DocumentationURI string `yaml:"documentation_uri"`
|
||||
SourceCodeURI string `yaml:"source_code_uri"`
|
||||
} `yaml:"metadata"`
|
||||
PostInstallMessage interface{} `yaml:"post_install_message"`
|
||||
RdocOptions []interface{} `yaml:"rdoc_options"`
|
||||
RequirePaths []string `yaml:"require_paths"`
|
||||
RequiredRubyVersion requirement `yaml:"required_ruby_version"`
|
||||
RequiredRubygemsVersion requirement `yaml:"required_rubygems_version"`
|
||||
Requirements []interface{} `yaml:"requirements"`
|
||||
RubygemsVersion string `yaml:"rubygems_version"`
|
||||
SigningKey interface{} `yaml:"signing_key"`
|
||||
SpecificationVersion int `yaml:"specification_version"`
|
||||
Summary string `yaml:"summary"`
|
||||
TestFiles []interface{} `yaml:"test_files"`
|
||||
PostInstallMessage any `yaml:"post_install_message"`
|
||||
RdocOptions []any `yaml:"rdoc_options"`
|
||||
RequirePaths []string `yaml:"require_paths"`
|
||||
RequiredRubyVersion requirement `yaml:"required_ruby_version"`
|
||||
RequiredRubygemsVersion requirement `yaml:"required_rubygems_version"`
|
||||
Requirements []any `yaml:"requirements"`
|
||||
RubygemsVersion string `yaml:"rubygems_version"`
|
||||
SigningKey any `yaml:"signing_key"`
|
||||
SpecificationVersion int `yaml:"specification_version"`
|
||||
Summary string `yaml:"summary"`
|
||||
TestFiles []any `yaml:"test_files"`
|
||||
}
|
||||
|
||||
type requirement struct {
|
||||
Requirements [][]interface{} `yaml:"requirements"`
|
||||
Requirements [][]any `yaml:"requirements"`
|
||||
}
|
||||
|
||||
// AsVersionRequirement converts into []VersionRequirement
|
||||
@@ -119,7 +119,7 @@ func (r requirement) AsVersionRequirement() []VersionRequirement {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
vm, ok := req[1].(map[string]interface{})
|
||||
vm, ok := req[1].(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ type LoggerOptions struct {
|
||||
Logger string
|
||||
Writer string
|
||||
Mode string
|
||||
Config map[string]interface{}
|
||||
Config map[string]any
|
||||
}
|
||||
|
||||
// AddLogger adds a logger
|
||||
func AddLogger(ctx context.Context, logger, writer, mode string, config map[string]interface{}) ResponseExtra {
|
||||
func AddLogger(ctx context.Context, logger, writer, mode string, config map[string]any) ResponseExtra {
|
||||
reqURL := setting.LocalURL + "api/internal/manager/add-logger"
|
||||
req := newInternalRequest(ctx, reqURL, "POST", LoggerOptions{
|
||||
Logger: logger,
|
||||
|
||||
@@ -24,7 +24,7 @@ func (c *Context) GetParent() *Context {
|
||||
}
|
||||
|
||||
// Value is part of the interface for context.Context. We mostly defer to the internal context - but we return this in response to the ProcessContextKey
|
||||
func (c *Context) Value(key interface{}) interface{} {
|
||||
func (c *Context) Value(key any) any {
|
||||
if key == ProcessContextKey {
|
||||
return c
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (c *Context) Value(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// ProcessContextKey is the key under which process contexts are stored
|
||||
var ProcessContextKey interface{} = "process-context"
|
||||
var ProcessContextKey any = "process-context"
|
||||
|
||||
// GetContext will return a process context if one exists
|
||||
func GetContext(ctx context.Context) *Context {
|
||||
|
||||
@@ -211,7 +211,7 @@ func (pm *Manager) nextPID() (start time.Time, pid IDType) {
|
||||
pid = IDType(strconv.FormatInt(start.Unix(), 16))
|
||||
|
||||
if pm.next == 1 {
|
||||
return
|
||||
return start, pid
|
||||
}
|
||||
pid = IDType(string(pid) + "-" + strconv.FormatInt(pm.next, 10))
|
||||
return start, pid
|
||||
|
||||
@@ -93,7 +93,7 @@ func (q *WorkerPoolQueue[T]) GetQueueItemNumber() int {
|
||||
|
||||
func (q *WorkerPoolQueue[T]) FlushWithContext(ctx context.Context, timeout time.Duration) (err error) {
|
||||
if q.isBaseQueueDummy() {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debug("Try to flush queue %q with timeout %v", q.GetName(), timeout)
|
||||
|
||||
@@ -77,9 +77,9 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
|
||||
RepoID: repo.ID,
|
||||
Name: branch,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.CommitMessage,
|
||||
CommitMessage: commit.Summary(),
|
||||
PusherID: doerID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Author.When.Unix()),
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
} else if commit.ID.String() != dbb.CommitID {
|
||||
toUpdate = append(toUpdate, &git_model.Branch{
|
||||
@@ -87,9 +87,9 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
|
||||
RepoID: repo.ID,
|
||||
Name: branch,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.CommitMessage,
|
||||
CommitMessage: commit.Summary(),
|
||||
PusherID: doerID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Author.When.Unix()),
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -17,11 +17,11 @@ import (
|
||||
type DBStore struct {
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
data map[any]any
|
||||
}
|
||||
|
||||
// NewDBStore creates and returns a DB session store.
|
||||
func NewDBStore(sid string, kv map[interface{}]interface{}) *DBStore {
|
||||
func NewDBStore(sid string, kv map[any]any) *DBStore {
|
||||
return &DBStore{
|
||||
sid: sid,
|
||||
data: kv,
|
||||
@@ -29,7 +29,7 @@ func NewDBStore(sid string, kv map[interface{}]interface{}) *DBStore {
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *DBStore) Set(key, val interface{}) error {
|
||||
func (s *DBStore) Set(key, val any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -38,7 +38,7 @@ func (s *DBStore) Set(key, val interface{}) error {
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *DBStore) Get(key interface{}) interface{} {
|
||||
func (s *DBStore) Get(key any) any {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
@@ -46,7 +46,7 @@ func (s *DBStore) Get(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *DBStore) Delete(key interface{}) error {
|
||||
func (s *DBStore) Delete(key any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -79,7 +79,7 @@ func (s *DBStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
s.data = make(map[any]any)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -102,9 +102,9 @@ func (p *DBProvider) Read(sid string) (session.RawStore, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
var kv map[any]any
|
||||
if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() {
|
||||
kv = make(map[interface{}]interface{})
|
||||
kv = make(map[any]any)
|
||||
} else {
|
||||
kv, err = session.DecodeGob(s.Data)
|
||||
if err != nil {
|
||||
@@ -136,9 +136,9 @@ func (p *DBProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
var kv map[any]any
|
||||
if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() {
|
||||
kv = make(map[interface{}]interface{})
|
||||
kv = make(map[any]any)
|
||||
} else {
|
||||
kv, err = session.DecodeGob(s.Data)
|
||||
if err != nil {
|
||||
|
||||
+10
-10
@@ -35,11 +35,11 @@ type RedisStore struct {
|
||||
prefix, sid string
|
||||
duration time.Duration
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
data map[any]any
|
||||
}
|
||||
|
||||
// NewRedisStore creates and returns a redis session store.
|
||||
func NewRedisStore(c redis.UniversalClient, prefix, sid string, dur time.Duration, kv map[interface{}]interface{}) *RedisStore {
|
||||
func NewRedisStore(c redis.UniversalClient, prefix, sid string, dur time.Duration, kv map[any]any) *RedisStore {
|
||||
return &RedisStore{
|
||||
c: c,
|
||||
prefix: prefix,
|
||||
@@ -50,7 +50,7 @@ func NewRedisStore(c redis.UniversalClient, prefix, sid string, dur time.Duratio
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *RedisStore) Set(key, val interface{}) error {
|
||||
func (s *RedisStore) Set(key, val any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *RedisStore) Set(key, val interface{}) error {
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *RedisStore) Get(key interface{}) interface{} {
|
||||
func (s *RedisStore) Get(key any) any {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
@@ -67,7 +67,7 @@ func (s *RedisStore) Get(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *RedisStore) Delete(key interface{}) error {
|
||||
func (s *RedisStore) Delete(key any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -100,7 +100,7 @@ func (s *RedisStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
s.data = make(map[any]any)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -141,13 +141,13 @@ func (p *RedisProvider) Read(sid string) (session.RawStore, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
var kv map[any]any
|
||||
kvs, err := p.c.Get(graceful.GetManager().HammerContext(), psid).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
kv = make(map[any]any)
|
||||
} else {
|
||||
kv, err = session.DecodeGob([]byte(kvs))
|
||||
if err != nil {
|
||||
@@ -197,9 +197,9 @@ func (p *RedisProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kv map[interface{}]interface{}
|
||||
var kv map[any]any
|
||||
if len(kvs) == 0 {
|
||||
kv = make(map[interface{}]interface{})
|
||||
kv = make(map[any]any)
|
||||
} else {
|
||||
kv, err = session.DecodeGob([]byte(kvs))
|
||||
if err != nil {
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
// Store represents a session store
|
||||
type Store interface {
|
||||
Get(interface{}) interface{}
|
||||
Set(interface{}, interface{}) error
|
||||
Delete(interface{}) error
|
||||
Get(any) any
|
||||
Set(any, any) error
|
||||
Delete(any) error
|
||||
}
|
||||
|
||||
// RegenerateSession regenerates the underlying session and returns the new store
|
||||
|
||||
@@ -62,7 +62,7 @@ func (o *VirtualSessionProvider) Read(sid string) (session.RawStore, error) {
|
||||
if o.provider.Exist(sid) {
|
||||
return o.provider.Read(sid)
|
||||
}
|
||||
kv := make(map[interface{}]interface{})
|
||||
kv := make(map[any]any)
|
||||
kv["_old_uid"] = "0"
|
||||
return NewVirtualStore(o, sid, kv), nil
|
||||
}
|
||||
@@ -107,12 +107,12 @@ type VirtualStore struct {
|
||||
p *VirtualSessionProvider
|
||||
sid string
|
||||
lock sync.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
data map[any]any
|
||||
released bool
|
||||
}
|
||||
|
||||
// NewVirtualStore creates and returns a virtual session store.
|
||||
func NewVirtualStore(p *VirtualSessionProvider, sid string, kv map[interface{}]interface{}) *VirtualStore {
|
||||
func NewVirtualStore(p *VirtualSessionProvider, sid string, kv map[any]any) *VirtualStore {
|
||||
return &VirtualStore{
|
||||
p: p,
|
||||
sid: sid,
|
||||
@@ -121,7 +121,7 @@ func NewVirtualStore(p *VirtualSessionProvider, sid string, kv map[interface{}]i
|
||||
}
|
||||
|
||||
// Set sets value to given key in session.
|
||||
func (s *VirtualStore) Set(key, val interface{}) error {
|
||||
func (s *VirtualStore) Set(key, val any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -130,7 +130,7 @@ func (s *VirtualStore) Set(key, val interface{}) error {
|
||||
}
|
||||
|
||||
// Get gets value by given key in session.
|
||||
func (s *VirtualStore) Get(key interface{}) interface{} {
|
||||
func (s *VirtualStore) Get(key any) any {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
@@ -138,7 +138,7 @@ func (s *VirtualStore) Get(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// Delete delete a key from session.
|
||||
func (s *VirtualStore) Delete(key interface{}) error {
|
||||
func (s *VirtualStore) Delete(key any) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
@@ -192,6 +192,6 @@ func (s *VirtualStore) Flush() error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.data = make(map[interface{}]interface{})
|
||||
s.data = make(map[any]any)
|
||||
return nil
|
||||
}
|
||||
@@ -5,6 +5,9 @@ package setting
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
// Actions settings
|
||||
@@ -13,13 +16,36 @@ var (
|
||||
LogStorage *Storage // how the created logs should be stored
|
||||
ArtifactStorage *Storage // how the created artifacts should be stored
|
||||
Enabled bool
|
||||
DefaultActionsURL string `ini:"DEFAULT_ACTIONS_URL"`
|
||||
DefaultActionsURL defaultActionsURL `ini:"DEFAULT_ACTIONS_URL"`
|
||||
}{
|
||||
Enabled: false,
|
||||
DefaultActionsURL: "https://gitea.com",
|
||||
DefaultActionsURL: defaultActionsURLGitHub,
|
||||
}
|
||||
)
|
||||
|
||||
type defaultActionsURL string
|
||||
|
||||
func (url defaultActionsURL) URL() string {
|
||||
switch url {
|
||||
case defaultActionsURLGitHub:
|
||||
return "https://github.com"
|
||||
case defaultActionsURLSelf:
|
||||
return strings.TrimSuffix(AppURL, "/")
|
||||
default:
|
||||
// This should never happen, but just in case, use GitHub as fallback
|
||||
return "https://github.com"
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
defaultActionsURLGitHub = "github" // https://github.com
|
||||
defaultActionsURLSelf = "self" // the root URL of the self-hosted Gitea instance
|
||||
// DefaultActionsURL only supports GitHub and the self-hosted Gitea.
|
||||
// It's intentionally not supported more, so please be cautious before adding more like "gitea" or "gitlab".
|
||||
// If you get some trouble with `uses: username/action_name@version` in your workflow,
|
||||
// please consider to use `uses: https://the_url_you_want_to_use/username/action_name@version` instead.
|
||||
)
|
||||
|
||||
func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||
sec := rootCfg.Section("actions")
|
||||
err := sec.MapTo(&Actions)
|
||||
@@ -27,6 +53,19 @@ func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||
return fmt.Errorf("failed to map Actions settings: %v", err)
|
||||
}
|
||||
|
||||
if urls := string(Actions.DefaultActionsURL); urls != defaultActionsURLGitHub && urls != defaultActionsURLSelf {
|
||||
url := strings.Split(urls, ",")[0]
|
||||
if strings.HasPrefix(url, "https://") || strings.HasPrefix(url, "http://") {
|
||||
log.Error("[actions] DEFAULT_ACTIONS_URL does not support %q as custom URL any longer, fallback to %q",
|
||||
urls,
|
||||
defaultActionsURLGitHub,
|
||||
)
|
||||
Actions.DefaultActionsURL = defaultActionsURLGitHub
|
||||
} else {
|
||||
return fmt.Errorf("unsupported [actions] DEFAULT_ACTIONS_URL: %q", urls)
|
||||
}
|
||||
}
|
||||
|
||||
// don't support to read configuration from [actions]
|
||||
Actions.LogStorage, err = getStorage(rootCfg, "actions_log", "", nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_getStorageInheritNameSectionTypeForActions(t *testing.T) {
|
||||
@@ -95,3 +96,86 @@ STORAGE_TYPE = minio
|
||||
assert.EqualValues(t, "local", Actions.ArtifactStorage.Type)
|
||||
assert.EqualValues(t, "actions_artifacts", filepath.Base(Actions.ArtifactStorage.Path))
|
||||
}
|
||||
|
||||
func Test_getDefaultActionsURLForActions(t *testing.T) {
|
||||
oldActions := Actions
|
||||
oldAppURL := AppURL
|
||||
defer func() {
|
||||
Actions = oldActions
|
||||
AppURL = oldAppURL
|
||||
}()
|
||||
|
||||
AppURL = "http://test_get_default_actions_url_for_actions:3000/"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
iniStr string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
wantURL string
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
iniStr: `
|
||||
[actions]
|
||||
`,
|
||||
wantErr: assert.NoError,
|
||||
wantURL: "https://github.com",
|
||||
},
|
||||
{
|
||||
name: "github",
|
||||
iniStr: `
|
||||
[actions]
|
||||
DEFAULT_ACTIONS_URL = github
|
||||
`,
|
||||
wantErr: assert.NoError,
|
||||
wantURL: "https://github.com",
|
||||
},
|
||||
{
|
||||
name: "self",
|
||||
iniStr: `
|
||||
[actions]
|
||||
DEFAULT_ACTIONS_URL = self
|
||||
`,
|
||||
wantErr: assert.NoError,
|
||||
wantURL: "http://test_get_default_actions_url_for_actions:3000",
|
||||
},
|
||||
{
|
||||
name: "custom url",
|
||||
iniStr: `
|
||||
[actions]
|
||||
DEFAULT_ACTIONS_URL = https://gitea.com
|
||||
`,
|
||||
wantErr: assert.NoError,
|
||||
wantURL: "https://github.com",
|
||||
},
|
||||
{
|
||||
name: "custom urls",
|
||||
iniStr: `
|
||||
[actions]
|
||||
DEFAULT_ACTIONS_URL = https://gitea.com,https://github.com
|
||||
`,
|
||||
wantErr: assert.NoError,
|
||||
wantURL: "https://github.com",
|
||||
},
|
||||
{
|
||||
name: "invalid",
|
||||
iniStr: `
|
||||
[actions]
|
||||
DEFAULT_ACTIONS_URL = gitea
|
||||
`,
|
||||
wantErr: assert.Error,
|
||||
wantURL: "https://github.com",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg, err := NewConfigProviderFromData(tt.iniStr)
|
||||
require.NoError(t, err)
|
||||
if !tt.wantErr(t, loadActionsFrom(cfg)) {
|
||||
return
|
||||
}
|
||||
assert.EqualValues(t, tt.wantURL, Actions.DefaultActionsURL.URL())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,31 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
const (
|
||||
EnvConfigKeyPrefixGitea = "GITEA__"
|
||||
EnvConfigKeySuffixFile = "__FILE"
|
||||
)
|
||||
|
||||
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
|
||||
|
||||
var escapeRegex = regexp.MustCompile(escapeRegexpString)
|
||||
|
||||
func CollectEnvConfigKeys() (keys []string) {
|
||||
for _, env := range os.Environ() {
|
||||
if strings.HasPrefix(env, EnvConfigKeyPrefixGitea) {
|
||||
k, _, _ := strings.Cut(env, "=")
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func ClearEnvConfigKeys() {
|
||||
for _, k := range CollectEnvConfigKeys() {
|
||||
_ = os.Unsetenv(k)
|
||||
}
|
||||
}
|
||||
|
||||
// decodeEnvSectionKey will decode a portable string encoded Section__Key pair
|
||||
// Portable strings are considered to be of the form [A-Z0-9_]*
|
||||
// We will encode a disallowed value as the UTF8 byte string preceded by _0X and
|
||||
@@ -87,7 +108,7 @@ func decodeEnvironmentKey(prefixGitea, suffixFile, envKey string) (ok bool, sect
|
||||
return ok, section, key, useFileValue
|
||||
}
|
||||
|
||||
func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) {
|
||||
func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
|
||||
for _, kv := range envs {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
@@ -97,7 +118,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env
|
||||
// parse the environment variable to config section name and key name
|
||||
envKey := kv[:idx]
|
||||
envValue := kv[idx+1:]
|
||||
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey)
|
||||
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(EnvConfigKeyPrefixGitea, EnvConfigKeySuffixFile, envKey)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func TestDecodeEnvironmentKey(t *testing.T) {
|
||||
func TestEnvironmentToConfig(t *testing.T) {
|
||||
cfg, _ := NewConfigProviderFromData("")
|
||||
|
||||
changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil)
|
||||
changed := EnvironmentToConfig(cfg, nil)
|
||||
assert.False(t, changed)
|
||||
|
||||
cfg, err := NewConfigProviderFromData(`
|
||||
@@ -81,16 +81,16 @@ key = old
|
||||
`)
|
||||
assert.NoError(t, err)
|
||||
|
||||
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
|
||||
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
|
||||
assert.True(t, changed)
|
||||
assert.Equal(t, "new", cfg.Section("sec").Key("key").String())
|
||||
|
||||
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
|
||||
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
|
||||
assert.False(t, changed)
|
||||
|
||||
tmpFile := t.TempDir() + "/the-file"
|
||||
_ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644)
|
||||
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
|
||||
assert.True(t, changed)
|
||||
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
|
||||
}
|
||||
@@ -6,11 +6,11 @@ package setting
|
||||
import "reflect"
|
||||
|
||||
// GetCronSettings maps the cron subsection to the provided config
|
||||
func GetCronSettings(name string, config interface{}) (interface{}, error) {
|
||||
func GetCronSettings(name string, config any) (any, error) {
|
||||
return getCronSettings(CfgProvider, name, config)
|
||||
}
|
||||
|
||||
func getCronSettings(rootCfg ConfigProvider, name string, config interface{}) (interface{}, error) {
|
||||
func getCronSettings(rootCfg ConfigProvider, name string, config any) (any, error) {
|
||||
if err := rootCfg.Section("cron." + name).MapTo(config); err != nil {
|
||||
return config, err
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func initLoggersByConfig(t *testing.T, config string) (*log.LoggerManager, func(
|
||||
return manager, manager.Close
|
||||
}
|
||||
|
||||
func toJSON(v interface{}) string {
|
||||
func toJSON(v any) string {
|
||||
b, _ := json.MarshalIndent(v, "", "\t")
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -171,6 +171,9 @@ func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkP
|
||||
|
||||
// only read the config but do not load/init anything more, because the AppWorkPath and CustomPath are not ready
|
||||
InitCfgProvider(tmpCustomConf.Value)
|
||||
if HasInstallLock(CfgProvider) {
|
||||
ClearEnvConfigKeys() // if the instance has been installed, do not pass the environment variables to sub-processes
|
||||
}
|
||||
configWorkPath := ConfigSectionKeyString(CfgProvider.Section(""), "WORK_PATH")
|
||||
if configWorkPath != "" {
|
||||
if !filepath.IsAbs(configWorkPath) {
|
||||
|
||||
@@ -102,7 +102,7 @@ func generateSaveInternalToken(rootCfg ConfigProvider) {
|
||||
|
||||
func loadSecurityFrom(rootCfg ConfigProvider) {
|
||||
sec := rootCfg.Section("security")
|
||||
InstallLock = sec.Key("INSTALL_LOCK").MustBool(false)
|
||||
InstallLock = HasInstallLock(rootCfg)
|
||||
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7)
|
||||
CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome")
|
||||
SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY")
|
||||
|
||||
@@ -183,10 +183,14 @@ func loadRunModeFrom(rootCfg ConfigProvider) {
|
||||
}
|
||||
}
|
||||
|
||||
// HasInstallLock checks the install-lock in ConfigProvider directly, because sometimes the config file is not loaded into setting variables yet.
|
||||
func HasInstallLock(rootCfg ConfigProvider) bool {
|
||||
return rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false)
|
||||
}
|
||||
|
||||
func mustCurrentRunUserMatch(rootCfg ConfigProvider) {
|
||||
// Does not check run user when the "InstallLock" is off.
|
||||
installLock := rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false)
|
||||
if installLock {
|
||||
if HasInstallLock(rootCfg) {
|
||||
currentUser, match := IsRunUserMatchCurrentUser(RunUser)
|
||||
if !match {
|
||||
log.Fatal("Expect user '%s' but current user is: %s", RunUser, currentUser)
|
||||
|
||||
@@ -173,7 +173,7 @@ func loadSSHFrom(rootCfg ConfigProvider) {
|
||||
}
|
||||
}
|
||||
|
||||
SSH.AuthorizedKeysBackup = sec.Key("SSH_AUTHORIZED_KEYS_BACKUP").MustBool(true)
|
||||
SSH.AuthorizedKeysBackup = sec.Key("SSH_AUTHORIZED_KEYS_BACKUP").MustBool(false)
|
||||
SSH.CreateAuthorizedKeysFile = sec.Key("SSH_CREATE_AUTHORIZED_KEYS_FILE").MustBool(true)
|
||||
|
||||
SSH.AuthorizedPrincipalsBackup = false
|
||||
|
||||
@@ -173,7 +173,7 @@ func (m minioFileInfo) Mode() os.FileMode {
|
||||
return os.ModePerm
|
||||
}
|
||||
|
||||
func (m minioFileInfo) Sys() interface{} {
|
||||
func (m minioFileInfo) Sys() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ var ErrURLNotSupported = errors.New("url method not supported")
|
||||
|
||||
// ErrInvalidConfiguration is called when there is invalid configuration for a storage
|
||||
type ErrInvalidConfiguration struct {
|
||||
cfg interface{}
|
||||
cfg any
|
||||
err error
|
||||
}
|
||||
|
||||
|
||||
@@ -140,10 +140,10 @@ const (
|
||||
// IssueFormField represents a form field
|
||||
// swagger:model
|
||||
type IssueFormField struct {
|
||||
Type IssueFormFieldType `json:"type" yaml:"type"`
|
||||
ID string `json:"id" yaml:"id"`
|
||||
Attributes map[string]interface{} `json:"attributes" yaml:"attributes"`
|
||||
Validations map[string]interface{} `json:"validations" yaml:"validations"`
|
||||
Type IssueFormFieldType `json:"type" yaml:"type"`
|
||||
ID string `json:"id" yaml:"id"`
|
||||
Attributes map[string]any `json:"attributes" yaml:"attributes"`
|
||||
Validations map[string]any `json:"validations" yaml:"validations"`
|
||||
}
|
||||
|
||||
// IssueTemplate represents an issue template for a repository
|
||||
|
||||
@@ -166,7 +166,7 @@ type FilesResponse struct {
|
||||
|
||||
// FileDeleteResponse contains information about a repo's file that was deleted
|
||||
type FileDeleteResponse struct {
|
||||
Content interface{} `json:"content"` // to be set to nil
|
||||
Content any `json:"content"` // to be set to nil
|
||||
Commit *FileCommitResponse `json:"commit"`
|
||||
Verification *PayloadCommitVerification `json:"verification"`
|
||||
}
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
|
||||
// WatchInfo represents an API watch status of one repository
|
||||
type WatchInfo struct {
|
||||
Subscribed bool `json:"subscribed"`
|
||||
Ignored bool `json:"ignored"`
|
||||
Reason interface{} `json:"reason"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
URL string `json:"url"`
|
||||
RepositoryURL string `json:"repository_url"`
|
||||
Subscribed bool `json:"subscribed"`
|
||||
Ignored bool `json:"ignored"`
|
||||
Reason any `json:"reason"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
URL string `json:"url"`
|
||||
RepositoryURL string `json:"repository_url"`
|
||||
}
|
||||
+1
-1
@@ -49,7 +49,7 @@ func Init() error {
|
||||
}
|
||||
|
||||
// RenderHTML renders icons - arguments icon name (string), size (int), class (string)
|
||||
func RenderHTML(icon string, others ...interface{}) template.HTML {
|
||||
func RenderHTML(icon string, others ...any) template.HTML {
|
||||
size, class := html.ParseSizeAndClass(defaultSize, "", others...)
|
||||
|
||||
if svgStr, ok := SVGs[icon]; ok {
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
|
||||
// NewFuncMap returns functions for injecting to templates
|
||||
func NewFuncMap() template.FuncMap {
|
||||
return map[string]interface{}{
|
||||
return map[string]any{
|
||||
"DumpVar": dumpVar,
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -142,8 +142,8 @@ func NewFuncMap() template.FuncMap {
|
||||
"DefaultTheme": func() string {
|
||||
return setting.UI.DefaultTheme
|
||||
},
|
||||
"NotificationSettings": func() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"NotificationSettings": func() map[string]any {
|
||||
return map[string]any{
|
||||
"MinTimeout": int(setting.UI.Notification.MinTimeout / time.Millisecond),
|
||||
"TimeoutStep": int(setting.UI.Notification.TimeoutStep / time.Millisecond),
|
||||
"MaxTimeout": int(setting.UI.Notification.MaxTimeout / time.Millisecond),
|
||||
|
||||
Loaded 100 of 555 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user