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"}}
+
{{.CsrfTokenHtml}}
@@ -264,6 +264,14 @@
{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}
{{.CacheItemTTL}}
{{end}} +
+
{{ctx.Locale.Tr "admin.config.cache_test"}}
+
+ + {{.CsrfTokenHtml}} + +
+
diff --git a/templates/admin/self_check.tmpl b/templates/admin/self_check.tmpl index 5c154ac0d5..afcd4cd640 100644 --- a/templates/admin/self_check.tmpl +++ b/templates/admin/self_check.tmpl @@ -28,6 +28,13 @@ {{else}}
{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}
{{end}} + + {{if .CacheError}} +
{{ctx.Locale.Tr "admin.config.cache_test_failed" .CacheError}}
+ {{end}} + {{if .CacheSlow}} +
{{ctx.Locale.Tr "admin.config.cache_test_slow" .CacheSlow}}
+ {{end}} diff --git a/templates/repo/blame.tmpl b/templates/repo/blame.tmpl index 01978dacf7..691f75dcad 100644 --- a/templates/repo/blame.tmpl +++ b/templates/repo/blame.tmpl @@ -2,7 +2,7 @@ {{$revsFileLink := URLJoin .RepoLink "src" .BranchNameSubURL "/.git-blame-ignore-revs"}} {{if .UsesIgnoreRevs}}
-

{{ctx.Locale.Tr "repo.blame.ignore_revs" $revsFileLink (print $revsFileLink "?bypass-blame-ignore=true")}}

+

{{ctx.Locale.Tr "repo.blame.ignore_revs" $revsFileLink "?bypass-blame-ignore=true"}}

{{else}}
diff --git a/templates/repo/diff/blob_excerpt.tmpl b/templates/repo/diff/blob_excerpt.tmpl index 8312b5d913..d6ab87fdc2 100644 --- a/templates/repo/diff/blob_excerpt.tmpl +++ b/templates/repo/diff/blob_excerpt.tmpl @@ -51,17 +51,17 @@
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5)}} - {{end}} {{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4)}} - {{end}} {{if eq $line.GetExpandDirection 2}} - {{end}} diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 4ca8148fb4..f52804ff23 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -79,6 +79,11 @@ white-space: nowrap; } +.repository .issue-content-right .filter.menu { + max-height: 500px; + overflow-x: auto; +} + .repository .filter.menu.labels .label-filter .menu .info { display: inline-block; padding: 0.5rem 0; @@ -581,11 +586,6 @@ td .commit-summary { font-size: 14px; } -.repository.new.issue .comment.form .issue-content-right .filter.menu { - max-height: 500px; - overflow-x: auto; -} - .repository.view.issue .instruct-toggle { display: inline-block; }