diff --git a/.air.toml b/.air.toml
index d506c19426..af182697fb 100644
--- a/.air.toml
+++ b/.air.toml
@@ -24,3 +24,6 @@ exclude_dir = [
]
exclude_regex = ["_test.go$", "_gen.go$"]
stop_on_error = true
+
+[log]
+main_only = true
diff --git a/.deadcode-out b/.deadcode-out
index 186e1ef4e9..e052892474 100644
--- a/.deadcode-out
+++ b/.deadcode-out
@@ -210,7 +210,6 @@ code.gitea.io/gitea/modules/json
StdJSON.Indent
code.gitea.io/gitea/modules/markup
- IsSameDomain
GetRendererByType
RenderString
IsMarkupFile
diff --git a/Dockerfile b/Dockerfile
index c5b472cbb9..eba2fb97d3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,11 +3,11 @@ FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.20 as build-env
ARG GOPROXY
-ENV GOPROXY ${GOPROXY:-direct}
+ENV GOPROXY=${GOPROXY:-direct}
ARG RELEASE_VERSION
ARG TAGS="sqlite sqlite_unlock_notify"
-ENV TAGS "bindata timetzdata $TAGS"
+ENV TAGS="bindata timetzdata $TAGS"
ARG CGO_EXTRA_CFLAGS
#
@@ -92,8 +92,8 @@ RUN addgroup \
git && \
echo "git:*" | chpasswd -e
-ENV USER git
-ENV GITEA_CUSTOM /data/gitea
+ENV USER=git
+ENV GITEA_CUSTOM=/data/gitea
VOLUME ["/data"]
diff --git a/Dockerfile.rootless b/Dockerfile.rootless
index 484711a932..e255328052 100644
--- a/Dockerfile.rootless
+++ b/Dockerfile.rootless
@@ -3,11 +3,11 @@ FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.20 as build-env
ARG GOPROXY
-ENV GOPROXY ${GOPROXY:-direct}
+ENV GOPROXY=${GOPROXY:-direct}
ARG RELEASE_VERSION
ARG TAGS="sqlite sqlite_unlock_notify"
-ENV TAGS "bindata timetzdata $TAGS"
+ENV TAGS="bindata timetzdata $TAGS"
ARG CGO_EXTRA_CFLAGS
#
@@ -95,17 +95,17 @@ COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_au
#git:git
USER 1000:1000
-ENV GITEA_WORK_DIR /var/lib/gitea
-ENV GITEA_CUSTOM /var/lib/gitea/custom
-ENV GITEA_TEMP /tmp/gitea
-ENV TMPDIR /tmp/gitea
+ENV GITEA_WORK_DIR=/var/lib/gitea
+ENV GITEA_CUSTOM=/var/lib/gitea/custom
+ENV GITEA_TEMP=/tmp/gitea
+ENV TMPDIR=/tmp/gitea
# Legacy config file for backwards compatibility
# TODO: remove on next major version release
-ENV GITEA_APP_INI_LEGACY /etc/gitea/app.ini
+ENV GITEA_APP_INI_LEGACY=/etc/gitea/app.ini
-ENV GITEA_APP_INI ${GITEA_CUSTOM}/conf/app.ini
-ENV HOME "/var/lib/gitea/git"
+ENV GITEA_APP_INI=${GITEA_CUSTOM}/conf/app.ini
+ENV HOME="/var/lib/gitea/git"
VOLUME ["/var/lib/gitea", "/etc/gitea"]
WORKDIR /var/lib/gitea
diff --git a/modules/cache/cache.go b/modules/cache/cache.go
index 09afc8b7f7..546c54dfe1 100644
--- a/modules/cache/cache.go
+++ b/modules/cache/cache.go
@@ -6,6 +6,7 @@ package cache
import (
"fmt"
"strconv"
+ "time"
"code.gitea.io/gitea/modules/setting"
@@ -40,6 +41,37 @@ func Init() error {
return err
}
+const (
+ testCacheKey = "DefaultCache.TestKey"
+ SlowCacheThreshold = 100 * time.Microsecond
+)
+
+func Test() (time.Duration, error) {
+ if conn == nil {
+ return 0, fmt.Errorf("default cache not initialized")
+ }
+
+ testData := fmt.Sprintf("%x", make([]byte, 500))
+
+ start := time.Now()
+
+ if err := conn.Delete(testCacheKey); err != nil {
+ return 0, fmt.Errorf("expect cache to delete data based on key if exist but got: %w", err)
+ }
+ if err := conn.Put(testCacheKey, testData, 10); err != nil {
+ return 0, fmt.Errorf("expect cache to store data but got: %w", err)
+ }
+ testVal := conn.Get(testCacheKey)
+ if testVal == nil {
+ return 0, fmt.Errorf("expect cache hit but got none")
+ }
+ if testVal != testData {
+ return 0, fmt.Errorf("expect cache to return same value as stored but got other")
+ }
+
+ return time.Since(start), nil
+}
+
// GetCache returns the currently configured cache
func GetCache() mc.Cache {
return conn
diff --git a/modules/cache/cache_test.go b/modules/cache/cache_test.go
index 3f65040924..0e7e7a647c 100644
--- a/modules/cache/cache_test.go
+++ b/modules/cache/cache_test.go
@@ -9,6 +9,7 @@ import (
"time"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
@@ -34,6 +35,18 @@ func TestNewContext(t *testing.T) {
assert.Nil(t, con)
}
+func TestTest(t *testing.T) {
+ defer test.MockVariableValue(&conn, nil)()
+ _, err := Test()
+ assert.Error(t, err)
+
+ createTestCache()
+ elapsed, err := Test()
+ assert.NoError(t, err)
+ // mem cache should take from 300ns up to 1ms on modern hardware ...
+ assert.Less(t, elapsed, SlowCacheThreshold)
+}
+
func TestGetCache(t *testing.T) {
createTestCache()
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 93c72fdcb4..b5c0e405ae 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -143,20 +143,6 @@ func CustomLinkURLSchemes(schemes []string) {
common.LinkRegex, _ = xurls.StrictMatchingScheme(strings.Join(withAuth, "|"))
}
-// IsSameDomain checks if given url string has the same hostname as current Gitea instance
-func IsSameDomain(s string) bool {
- if strings.HasPrefix(s, "/") {
- return true
- }
- if uapp, err := url.Parse(setting.AppURL); err == nil {
- if u, err := url.Parse(s); err == nil {
- return u.Host == uapp.Host
- }
- return false
- }
- return false
-}
-
type postProcessError struct {
context string
err error
@@ -393,7 +379,7 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) {
// We ignore code and pre.
switch node.Type {
case html.TextNode:
- textNode(ctx, procs, node)
+ processTextNodes(ctx, procs, node)
case html.ElementNode:
if node.Data == "img" {
for i, attr := range node.Attr {
@@ -436,15 +422,16 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) {
for n := node.FirstChild; n != nil; n = n.NextSibling {
visitNode(ctx, procs, n)
}
+ default:
}
// ignore everything else
}
-// textNode runs the passed node through various processors, in order to handle
+// processTextNodes runs the passed node through various processors, in order to handle
// all kinds of special links handled by the post-processing.
-func textNode(ctx *RenderContext, procs []processor, node *html.Node) {
- for _, processor := range procs {
- processor(ctx, node)
+func processTextNodes(ctx *RenderContext, procs []processor, node *html.Node) {
+ for _, p := range procs {
+ p(ctx, node)
}
}
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index cfd1a66a18..fa49e60a16 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -135,17 +135,6 @@ func TestRender_CrossReferences(t *testing.T) {
`
`+sha[:10]+`/README.md (L1-L5)
`)
}
-func TestMisc_IsSameDomain(t *testing.T) {
- setting.AppURL = markup.TestAppURL
-
- sha := "b6dd6210eaebc915fd5be5579c58cce4da2e2579"
- commit := util.URLJoin(markup.TestRepoURL, "commit", sha)
-
- assert.True(t, markup.IsSameDomain(commit))
- assert.False(t, markup.IsSameDomain("http://google.com/ncr"))
- assert.False(t, markup.IsSameDomain("favicon.ico"))
-}
-
func TestRender_links(t *testing.T) {
setting.AppURL = markup.TestAppURL
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 1e25df4320..68428552c4 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -548,6 +548,10 @@ func TestMathBlock(t *testing.T) {
`$$a`,
`$$a
` + nl,
},
+ {
+ "$a$ ($b$) [$c$] {$d$}",
+ `a
(b
) [$c$] {$d$}
` + nl,
+ },
}
for _, test := range testcases {
diff --git a/modules/markup/markdown/math/inline_parser.go b/modules/markup/markdown/math/inline_parser.go
index 862234e69b..614cf329af 100644
--- a/modules/markup/markdown/math/inline_parser.go
+++ b/modules/markup/markdown/math/inline_parser.go
@@ -45,6 +45,10 @@ func isPunctuation(b byte) bool {
return b == '.' || b == '!' || b == '?' || b == ',' || b == ';' || b == ':'
}
+func isBracket(b byte) bool {
+ return b == ')'
+}
+
func isAlphanumeric(b byte) bool {
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
}
@@ -84,7 +88,7 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
break
}
suceedingCharacter := line[pos]
- if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') {
+ if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') && !isBracket(suceedingCharacter) {
return nil
}
if line[ender-1] != '\\' {
diff --git a/modules/structs/org_team.go b/modules/structs/org_team.go
index 78dc4abaef..f8899b236b 100644
--- a/modules/structs/org_team.go
+++ b/modules/structs/org_team.go
@@ -24,7 +24,7 @@ type Team struct {
// CreateTeamOption options for creating a team
type CreateTeamOption struct {
// required: true
- Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: read,write,admin
@@ -40,7 +40,7 @@ type CreateTeamOption struct {
// EditTeamOption options for editing a team
type EditTeamOption struct {
// required: true
- Name string `json:"name" binding:"AlphaDashDot;MaxSize(30)"`
+ Name string `json:"name" binding:"AlphaDashDot;MaxSize(255)"`
Description *string `json:"description" binding:"MaxSize(255)"`
IncludesAllRepositories *bool `json:"includes_all_repositories"`
// enum: read,write,admin
diff --git a/options/gitignore/IAR b/options/gitignore/IAR
new file mode 100644
index 0000000000..e8938b31a4
--- /dev/null
+++ b/options/gitignore/IAR
@@ -0,0 +1,47 @@
+# Compiled binaries
+*.o
+*.bin
+*.elf
+*.hex
+*.map
+*.out
+*.obj
+
+# Trash
+*.bak
+thumbs.db
+*.~*
+
+# IAR Settings
+**/settings/*.crun
+**/settings/*.dbgdt
+**/settings/*.cspy
+**/settings/*.cspy.*
+**/settings/*.xcl
+**/settings/*.dni
+**/settings/*.wsdt
+**/settings/*.wspos
+
+# IAR Debug Exe
+**/Exe/*.sim
+
+# IAR Debug Obj
+**/Obj/*.pbd
+**/Obj/*.pbd.*
+**/Obj/*.pbi
+**/Obj/*.pbi.*
+
+# IAR project "Debug" directory
+Debug/
+
+# IAR project "Release" directory
+Release/
+
+# IAR project settings directory
+settings/
+
+# IAR backup files
+Backup*
+
+# IAR .dep files
+*.dep
\ No newline at end of file
diff --git a/options/gitignore/Objective-C b/options/gitignore/Objective-C
index 9b8cd0706f..2ebce16e6e 100644
--- a/options/gitignore/Objective-C
+++ b/options/gitignore/Objective-C
@@ -42,10 +42,3 @@ fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
-
-# Code Injection
-#
-# After new code Injection tools there's a generated folder /iOSInjectionProject
-# https://github.com/johnno1962/injectionforxcode
-
-iOSInjectionProject/
diff --git a/options/gitignore/Terraform b/options/gitignore/Terraform
index 15073ca88b..2faf43d0a1 100644
--- a/options/gitignore/Terraform
+++ b/options/gitignore/Terraform
@@ -35,6 +35,3 @@ override.tf.json
# Ignore CLI configuration files
.terraformrc
terraform.rc
-
-# Ignore hcl file
-.terraform.lock.hcl
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 7ef6b3f894..39c0a01930 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -93,6 +93,7 @@ remove_all = Remove all
remove_label_str = Remove item "%s"
edit = Edit
view = View
+test = Test
enabled = Enabled
disabled = Disabled
@@ -3322,6 +3323,11 @@ config.cache_interval = Cache interval
config.cache_conn = Cache connection
config.cache_item_ttl = Cache item TTL
+config.cache_test = Test Cache
+config.cache_test_failed = Failed to probe the cache: %v.
+config.cache_test_slow = Cache test successful, but response is slow: %s.
+config.cache_test_succeeded = Cache test successful, got a response in %s.
+
config.session_config = Session configuration
config.session_provider = Session provider
config.provider_config = Provider config
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index 6c778c686c..067203b28b 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -14,6 +14,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -211,6 +212,14 @@ func SelfCheck(ctx *context.Context) {
ctx.Data["DatabaseCheckHasProblems"] = hasProblem
}
+
+ elapsed, err := cache.Test()
+ if err != nil {
+ ctx.Data["CacheError"] = err
+ } else if elapsed > cache.SlowCacheThreshold {
+ ctx.Data["CacheSlow"] = fmt.Sprint(elapsed)
+ }
+
ctx.HTML(http.StatusOK, tplSelfCheck)
}
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index 22f260eded..09f332b447 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -12,6 +12,7 @@ import (
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
@@ -42,6 +43,22 @@ func SendTestMail(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/admin/config")
}
+// TestCache test the cache settings
+func TestCache(ctx *context.Context) {
+ elapsed, err := cache.Test()
+ if err != nil {
+ ctx.Flash.Error(ctx.Tr("admin.config.cache_test_failed", err))
+ } else {
+ if elapsed > cache.SlowCacheThreshold {
+ ctx.Flash.Warning(ctx.Tr("admin.config.cache_test_slow", elapsed))
+ } else {
+ ctx.Flash.Info(ctx.Tr("admin.config.cache_test_succeeded", elapsed))
+ }
+ }
+
+ ctx.Redirect(setting.AppSubURL + "/admin/config")
+}
+
func shadowPasswordKV(cfgItem, splitter string) string {
fields := strings.Split(cfgItem, splitter)
for i := 0; i < len(fields); i++ {
diff --git a/routers/web/web.go b/routers/web/web.go
index 34bfb8b60a..3781ffc058 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -665,6 +665,7 @@ func registerRoutes(m *web.Route) {
m.Get("", admin.Config)
m.Post("", admin.ChangeConfig)
m.Post("/test_mail", admin.SendTestMail)
+ m.Post("/test_cache", admin.TestCache)
m.Get("/settings", admin.ConfigSettings)
})
diff --git a/services/externalaccount/user.go b/services/externalaccount/user.go
index e2de41da18..3cfd8c81f9 100644
--- a/services/externalaccount/user.go
+++ b/services/externalaccount/user.go
@@ -5,6 +5,7 @@ package externalaccount
import (
"context"
+ "strconv"
"strings"
"code.gitea.io/gitea/models/auth"
@@ -82,6 +83,11 @@ func UpdateExternalUser(ctx context.Context, user *user_model.User, gothUser got
// UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID
func UpdateMigrationsByType(ctx context.Context, tp structs.GitServiceType, externalUserID string, userID int64) error {
+ // Skip update if externalUserID is not a valid numeric ID or exceeds int64
+ if _, err := strconv.ParseInt(externalUserID, 10, 64); err != nil {
+ return nil
+ }
+
if err := issues_model.UpdateIssuesMigrationsByType(ctx, tp, externalUserID, userID); err != nil {
return err
}
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index d4e5b326fd..8f2b1c12e3 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -233,8 +233,8 @@
{{ctx.Locale.Tr "admin.config.mailer_user"}}
{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}
- {{ctx.Locale.Tr "admin.config.send_test_mail"}}
-
+ {{ctx.Locale.Tr "admin.config.send_test_mail"}}
+