From ab458ce10be59669c810ba43af41f2ba2e72ea5b Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Sat, 1 Jun 2024 04:49:42 -0700 Subject: [PATCH 01/46] Return an empty string when a repo has no avatar in the repo API (#31187) Resolves #31167. https://github.com/go-gitea/gitea/pull/30885 changed the behavior of `repo.AvatarLink()` where it can now take the empty string and append it to the app data URL. This does not point to a valid avatar image URL, and, as the issue mentions, previous Gitea versions returned the empty string. --------- Co-authored-by: wxiaoguang --- models/repo/avatar.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/models/repo/avatar.go b/models/repo/avatar.go index 8395b8c2b7..ccfac12cad 100644 --- a/models/repo/avatar.go +++ b/models/repo/avatar.go @@ -84,7 +84,13 @@ func (repo *Repository) relAvatarLink(ctx context.Context) string { return setting.AppSubURL + "/repo-avatars/" + url.PathEscape(repo.Avatar) } -// AvatarLink returns the full avatar url with http host. TODO: refactor it to a relative URL, but it is still used in API response at the moment +// AvatarLink returns the full avatar url with http host or the empty string if the repo doesn't have an avatar. +// +// TODO: refactor it to a relative URL, but it is still used in API response at the moment func (repo *Repository) AvatarLink(ctx context.Context) string { - return httplib.MakeAbsoluteURL(ctx, repo.relAvatarLink(ctx)) + relLink := repo.relAvatarLink(ctx) + if relLink != "" { + return httplib.MakeAbsoluteURL(ctx, relLink) + } + return "" } From 3cc7f763c3c22ae4c3b5331f8b72b7009c5b11ea Mon Sep 17 00:00:00 2001 From: Max Wipfli Date: Sun, 2 Jun 2024 04:32:20 +0200 Subject: [PATCH 02/46] Only update poster in issue/comment list if it has been loaded (#31216) Previously, all posters were updated, even if they were not part of posterMaps. In that case, a ghost user was erroneously inserted. Fixes #31213. --- models/issues/comment_list.go | 4 +++- models/issues/issue_list.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 6b4ad80eed..61ac1c8f56 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -32,7 +32,9 @@ func (comments CommentList) LoadPosters(ctx context.Context) error { } for _, comment := range comments { - comment.Poster = getPoster(comment.PosterID, posterMaps) + if comment.Poster == nil { + comment.Poster = getPoster(comment.PosterID, posterMaps) + } } return nil } diff --git a/models/issues/issue_list.go b/models/issues/issue_list.go index 0dd37a04df..2c007c72ec 100644 --- a/models/issues/issue_list.go +++ b/models/issues/issue_list.go @@ -87,7 +87,9 @@ func (issues IssueList) LoadPosters(ctx context.Context) error { } for _, issue := range issues { - issue.Poster = getPoster(issue.PosterID, posterMaps) + if issue.Poster == nil { + issue.Poster = getPoster(issue.PosterID, posterMaps) + } } return nil } From 98a61040b1c83790b0e0e977188842f967ae357e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 2 Jun 2024 11:01:08 +0800 Subject: [PATCH 03/46] Fix the possible migration failure on 286 with postgres 16 (#31209) Try to fix #31205 --- models/migrations/v1_22/v286.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/migrations/v1_22/v286.go b/models/migrations/v1_22/v286.go index e11d16f8de..6ad669f27c 100644 --- a/models/migrations/v1_22/v286.go +++ b/models/migrations/v1_22/v286.go @@ -92,7 +92,7 @@ func addObjectFormatNameToRepository(x *xorm.Engine) error { // Here to catch weird edge-cases where column constraints above are // not applied by the DB backend - _, err := x.Exec("UPDATE repository set object_format_name = 'sha1' WHERE object_format_name = '' or object_format_name IS NULL") + _, err := x.Exec("UPDATE `repository` set `object_format_name` = 'sha1' WHERE `object_format_name` = '' or `object_format_name` IS NULL") return err } From 2788a7ca270c8ac2927af021910fad4e1a7b2c7b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 3 Jun 2024 06:45:21 +0800 Subject: [PATCH 04/46] Fix agit checkout command line hint & fix ShowMergeInstructions checking (#31219) --- routers/web/repo/issue.go | 15 ++++++++------- .../view_content/pull_merge_instruction.tmpl | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 18f975b4a6..e7ad02c0c2 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1794,6 +1794,7 @@ func ViewIssue(ctx *context.Context) { pull.Issue = issue canDelete := false allowMerge := false + canWriteToHeadRepo := false if ctx.IsSigned { if err := pull.LoadHeadRepo(ctx); err != nil { @@ -1814,7 +1815,7 @@ func ViewIssue(ctx *context.Context) { ctx.Data["DeleteBranchLink"] = issue.Link() + "/cleanup" } } - ctx.Data["CanWriteToHeadRepo"] = true + canWriteToHeadRepo = true } } @@ -1826,6 +1827,9 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("GetUserRepoPermission", err) return } + if !canWriteToHeadRepo { // maintainers maybe allowed to push to head repo even if they can't write to it + canWriteToHeadRepo = pull.AllowMaintainerEdit && perm.CanWrite(unit.TypeCode) + } allowMerge, err = pull_service.IsUserAllowedToMerge(ctx, pull, perm, ctx.Doer) if err != nil { ctx.ServerError("IsUserAllowedToMerge", err) @@ -1838,6 +1842,8 @@ func ViewIssue(ctx *context.Context) { } } + ctx.Data["CanWriteToHeadRepo"] = canWriteToHeadRepo + ctx.Data["ShowMergeInstructions"] = canWriteToHeadRepo ctx.Data["AllowMerge"] = allowMerge prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests) @@ -1892,13 +1898,9 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("LoadProtectedBranch", err) return } - ctx.Data["ShowMergeInstructions"] = true + if pb != nil { pb.Repo = pull.BaseRepo - var showMergeInstructions bool - if ctx.Doer != nil { - showMergeInstructions = pb.CanUserPush(ctx, ctx.Doer) - } ctx.Data["ProtectedBranch"] = pb ctx.Data["IsBlockedByApprovals"] = !issues_model.HasEnoughApprovals(ctx, pb, pull) ctx.Data["IsBlockedByRejection"] = issues_model.MergeBlockedByRejectedReview(ctx, pb, pull) @@ -1909,7 +1911,6 @@ func ViewIssue(ctx *context.Context) { ctx.Data["ChangedProtectedFiles"] = pull.ChangedProtectedFiles ctx.Data["IsBlockedByChangedProtectedFiles"] = len(pull.ChangedProtectedFiles) != 0 ctx.Data["ChangedProtectedFilesNum"] = len(pull.ChangedProtectedFiles) - ctx.Data["ShowMergeInstructions"] = showMergeInstructions } ctx.Data["WillSign"] = false if ctx.Doer != nil { diff --git a/templates/repo/issue/view_content/pull_merge_instruction.tmpl b/templates/repo/issue/view_content/pull_merge_instruction.tmpl index d585d36574..bb59b49719 100644 --- a/templates/repo/issue/view_content/pull_merge_instruction.tmpl +++ b/templates/repo/issue/view_content/pull_merge_instruction.tmpl @@ -9,10 +9,10 @@
{{if eq .PullRequest.Flow 0}}
git fetch -u {{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}}{{else}}origin{{end}} {{.PullRequest.HeadBranch}}:{{$localBranch}}
-
git checkout {{$localBranch}}
{{else}} -
git fetch -u origin {{.GetGitRefName}}:{{$localBranch}}
+
git fetch -u origin {{.PullRequest.GetGitRefName}}:{{$localBranch}}
{{end}} +
git checkout {{$localBranch}}
{{if .ShowMergeInstructions}}

{{ctx.Locale.Tr "repo.pulls.cmd_instruction_merge_title"}}

{{ctx.Locale.Tr "repo.pulls.cmd_instruction_merge_desc"}}
From 9b05bfb173795ba2a2267402d2669715cd4a64e4 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 3 Jun 2024 02:09:51 +0200 Subject: [PATCH 05/46] Fix overflow in issue card (#31203) Before: Screenshot 2024-06-01 at 01 31 26 After: Screenshot 2024-06-01 at 01 31 32 --- templates/repo/issue/card.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl index 526f6dd5db..4c22c28329 100644 --- a/templates/repo/issue/card.tmpl +++ b/templates/repo/issue/card.tmpl @@ -14,7 +14,7 @@
{{template "shared/issueicon" .}}
- {{.Title | RenderEmoji ctx | RenderCodeBlock}} + {{.Title | RenderEmoji ctx | RenderCodeBlock}} {{if and $.isPinnedIssueCard $.Page.IsRepoAdmin}} {{svg "octicon-x" 16}} From c6854202be9eb8358f046871d4eb0e4fd74639ff Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 3 Jun 2024 00:27:17 +0000 Subject: [PATCH 06/46] [skip ci] Updated licenses and gitignores --- options/gitignore/Alteryx | 44 ++++++++++++++++++++++++++++++++++ options/gitignore/Archives | 2 ++ options/gitignore/Ballerina | 11 +++++++++ options/gitignore/CMake | 1 + options/gitignore/Delphi | 12 ++++++++++ options/gitignore/GitHubPages | 18 ++++++++++++++ options/gitignore/Go | 3 +++ options/gitignore/Objective-C | 17 ------------- options/gitignore/Rust | 7 ++++++ options/gitignore/Swift | 28 ---------------------- options/gitignore/TeX | 5 ++++ options/gitignore/Terraform | 6 +++++ options/gitignore/UiPath | 11 +++++++++ options/gitignore/UnrealEngine | 4 ++-- options/gitignore/Xcode | 4 ---- 15 files changed, 122 insertions(+), 51 deletions(-) create mode 100644 options/gitignore/Alteryx create mode 100644 options/gitignore/Ballerina create mode 100644 options/gitignore/GitHubPages create mode 100644 options/gitignore/UiPath diff --git a/options/gitignore/Alteryx b/options/gitignore/Alteryx new file mode 100644 index 0000000000..a8e1341ffe --- /dev/null +++ b/options/gitignore/Alteryx @@ -0,0 +1,44 @@ +# gitignore template for Alteryx Designer +# website: https://www.alteryx.com/ +# website: https://help.alteryx.com/current/designer/alteryx-file-types + +# Alteryx Data Files +*.yxdb +*.cydb +*.cyidx +*.rptx +*.vvf +*.aws + +# Alteryx Special Files +*.yxwv +*.yxft +*.yxbe +*.bak +*.pcxml +*.log +*.bin +*.yxlang +CASS.ini + +# Alteryx License Files +*.yxlc +*.slc +*.cylc +*.alc +*.gzlc + +## gitignore reference sites +# https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files +# https://git-scm.com/docs/gitignore +# https://help.github.com/articles/ignoring-files/ + +## Useful knowledge from stackoverflow +# Even if you haven't tracked the files so far, git seems to be able to "know" about them even after you add them to .gitignore. +# WARNING: First commit your current changes, or you will lose them. +# Then run the following commands from the top folder of your git repo: +# git rm -r --cached . +# git add . +# git commit -m "fixed untracked files" + +# author: Kacper Ksieski \ No newline at end of file diff --git a/options/gitignore/Archives b/options/gitignore/Archives index 4ed9ab8350..8c92521b4c 100644 --- a/options/gitignore/Archives +++ b/options/gitignore/Archives @@ -14,6 +14,8 @@ *.lzma *.cab *.xar +*.zst +*.tzst # Packing-only formats *.iso diff --git a/options/gitignore/Ballerina b/options/gitignore/Ballerina new file mode 100644 index 0000000000..030a350fbf --- /dev/null +++ b/options/gitignore/Ballerina @@ -0,0 +1,11 @@ +# generated files +target/ +generated/ + +# dependencies +Dependencies.toml + +# config files +Config.toml +# the config files used for testing, Uncomment the following line if you want to commit the test config files +#!**/tests/Config.toml diff --git a/options/gitignore/CMake b/options/gitignore/CMake index 46f42f8f3c..11c76431e1 100644 --- a/options/gitignore/CMake +++ b/options/gitignore/CMake @@ -9,3 +9,4 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps +CMakeUserPresets.json diff --git a/options/gitignore/Delphi b/options/gitignore/Delphi index 9532800ba2..8df99b676b 100644 --- a/options/gitignore/Delphi +++ b/options/gitignore/Delphi @@ -26,6 +26,18 @@ #*.obj # +# Default Delphi compiler directories +# Content of this directories are generated with each Compile/Construct of a project. +# Most of the time, files here have not there place in a code repository. +#Win32/ +#Win64/ +#OSX64/ +#OSXARM64/ +#Android/ +#Android64/ +#iOSDevice64/ +#Linux64/ + # Delphi compiler-generated binaries (safe to delete) *.exe *.dll diff --git a/options/gitignore/GitHubPages b/options/gitignore/GitHubPages new file mode 100644 index 0000000000..493e69ba39 --- /dev/null +++ b/options/gitignore/GitHubPages @@ -0,0 +1,18 @@ +# This .gitignore is appropriate for repositories deployed to GitHub Pages and using +# a Gemfile as specified at https://github.com/github/pages-gem#conventional + +# Basic Jekyll gitignores (synchronize to Jekyll.gitignore) +_site/ +.sass-cache/ +.jekyll-cache/ +.jekyll-metadata + +# Additional Ruby/bundler ignore for when you run: bundle install +/vendor + +# Specific ignore for GitHub Pages +# GitHub Pages will always use its own deployed version of pages-gem +# This means GitHub Pages will NOT use your Gemfile.lock and therefore it is +# counterproductive to check this file into the repository. +# Details at https://github.com/github/pages-gem/issues/768 +Gemfile.lock diff --git a/options/gitignore/Go b/options/gitignore/Go index 6f6f5e6adc..6f72f89261 100644 --- a/options/gitignore/Go +++ b/options/gitignore/Go @@ -20,3 +20,6 @@ # Go workspace file go.work go.work.sum + +# env file +.env diff --git a/options/gitignore/Objective-C b/options/gitignore/Objective-C index 7801c93000..9b8cd0706f 100644 --- a/options/gitignore/Objective-C +++ b/options/gitignore/Objective-C @@ -5,23 +5,6 @@ ## User settings xcuserdata/ -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) -*.xcscmblueprint -*.xccheckout - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) -build/ -DerivedData/ -*.moved-aside -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 - ## Obj-C/Swift specific *.hmap diff --git a/options/gitignore/Rust b/options/gitignore/Rust index 6985cf1bd0..d01bd1a990 100644 --- a/options/gitignore/Rust +++ b/options/gitignore/Rust @@ -12,3 +12,10 @@ Cargo.lock # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/options/gitignore/Swift b/options/gitignore/Swift index 330d1674f3..52fe2f7102 100644 --- a/options/gitignore/Swift +++ b/options/gitignore/Swift @@ -5,23 +5,6 @@ ## User settings xcuserdata/ -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) -*.xcscmblueprint -*.xccheckout - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) -build/ -DerivedData/ -*.moved-aside -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 - ## Obj-C/Swift specific *.hmap @@ -66,10 +49,6 @@ playground.xcworkspace Carthage/Build/ -# Accio dependency management -Dependencies/ -.accio/ - # fastlane # # It is recommended to not store the screenshots in the git repo. @@ -81,10 +60,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/TeX b/options/gitignore/TeX index e964244133..a1f5212090 100644 --- a/options/gitignore/TeX +++ b/options/gitignore/TeX @@ -39,6 +39,8 @@ *.synctex.gz *.synctex.gz(busy) *.pdfsync +*.rubbercache +rubber.cache ## Build tool directories for auxiliary files # latexrun @@ -138,6 +140,9 @@ acs-*.bib *.trc *.xref +# hypdoc +*.hd + # hyperref *.brf diff --git a/options/gitignore/Terraform b/options/gitignore/Terraform index 9b8a46e692..15073ca88b 100644 --- a/options/gitignore/Terraform +++ b/options/gitignore/Terraform @@ -23,6 +23,9 @@ override.tf.json *_override.tf *_override.tf.json +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + # Include override files you do wish to add to version control using negated pattern # !example_override.tf @@ -32,3 +35,6 @@ override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc + +# Ignore hcl file +.terraform.lock.hcl diff --git a/options/gitignore/UiPath b/options/gitignore/UiPath new file mode 100644 index 0000000000..f0c2267b89 --- /dev/null +++ b/options/gitignore/UiPath @@ -0,0 +1,11 @@ +# gitignore template for RPA development using UiPath Studio +# website: https://www.uipath.com/product/studio +# +# Recommended: n/a + +# Ignore folders that could cause issues if accidentally tracked +**/.local/** +**/.settings/** +**/.objects/** +**/.tmh/** +**/*.log diff --git a/options/gitignore/UnrealEngine b/options/gitignore/UnrealEngine index 6582eaf9a1..6e0d95fb31 100644 --- a/options/gitignore/UnrealEngine +++ b/options/gitignore/UnrealEngine @@ -47,7 +47,7 @@ SourceArt/**/*.tga # Binary Files Binaries/* -Plugins/*/Binaries/* +Plugins/**/Binaries/* # Builds Build/* @@ -68,7 +68,7 @@ Saved/* # Compiled source files for the engine to use Intermediate/* -Plugins/*/Intermediate/* +Plugins/**/Intermediate/* # Cache files for the editor to use DerivedDataCache/* diff --git a/options/gitignore/Xcode b/options/gitignore/Xcode index f87d2f2e74..5073505e08 100644 --- a/options/gitignore/Xcode +++ b/options/gitignore/Xcode @@ -1,6 +1,2 @@ ## User settings xcuserdata/ - -## Xcode 8 and earlier -*.xcscmblueprint -*.xccheckout From 4b20b51f8260cb012581493d1143033dd3936aa6 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 3 Jun 2024 09:04:35 +0200 Subject: [PATCH 07/46] Update golangci-lint to v1.59.0 (#31221) One new error regarding `fmt.Fscanf` error return in `gitdiff.go` but I'm not touching that further right now as handling the error would introduce a behaviour difference. --- Makefile | 2 +- services/gitdiff/gitdiff.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 80efcbe46d..f273cac3a8 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ XGO_VERSION := go-1.22.x AIR_PACKAGE ?= github.com/cosmtrek/air@v1 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285 diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 063c995d52..0ddd5a48e2 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -1061,7 +1061,7 @@ func readFileName(rd *strings.Reader) (string, bool) { char, _ := rd.ReadByte() _ = rd.UnreadByte() if char == '"' { - fmt.Fscanf(rd, "%q ", &name) + _, _ = fmt.Fscanf(rd, "%q ", &name) if len(name) == 0 { log.Error("Reader has no file name: reader=%+v", rd) return "", true @@ -1073,12 +1073,12 @@ func readFileName(rd *strings.Reader) (string, bool) { } else { // This technique is potentially ambiguous it may not be possible to uniquely identify the filenames from the diff line alone ambiguity = true - fmt.Fscanf(rd, "%s ", &name) + _, _ = fmt.Fscanf(rd, "%s ", &name) char, _ := rd.ReadByte() _ = rd.UnreadByte() for !(char == 0 || char == '"' || char == 'b') { var suffix string - fmt.Fscanf(rd, "%s ", &suffix) + _, _ = fmt.Fscanf(rd, "%s ", &suffix) name += " " + suffix char, _ = rd.ReadByte() _ = rd.UnreadByte() From fc641b3a28300e13c822140556eca8d00f2b5196 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Mon, 3 Jun 2024 19:41:29 +0900 Subject: [PATCH 08/46] Remove sqlite-viewer and using database client (#31223) sqlite-viewer can not edit sqlite. database client can connect to almost all common databases, which is very useful I think. Of cause, it can edit sqlite. https://marketplace.visualstudio.com/items?itemName=cweijan.vscode-database-client2 And for using sqlite, sqlite3 is required. So also added a new feature: https://github.com/warrenbuckley/codespace-features found from: https://containers.dev/features --- .devcontainer/devcontainer.json | 5 +++-- .gitpod.yml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c32c5da82c..1b0255d198 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,7 +10,8 @@ "ghcr.io/devcontainers-contrib/features/poetry:2": {}, "ghcr.io/devcontainers/features/python:1": { "version": "3.12" - } + }, + "ghcr.io/warrenbuckley/codespace-features/sqlite:1": {} }, "customizations": { "vscode": { @@ -25,7 +26,7 @@ "Vue.volar", "ms-azuretools.vscode-docker", "vitest.explorer", - "qwtel.sqlite-viewer", + "cweijan.vscode-database-client2", "GitHub.vscode-pull-request-github", "Azurite.azurite" ] diff --git a/.gitpod.yml b/.gitpod.yml index f573d55a76..8671edc47c 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -43,7 +43,7 @@ vscode: - Vue.volar - ms-azuretools.vscode-docker - vitest.explorer - - qwtel.sqlite-viewer + - cweijan.vscode-database-client2 - GitHub.vscode-pull-request-github ports: From cb27c438a82fec9f2476f6058bc5dcda2617aab5 Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Mon, 3 Jun 2024 06:40:48 -0700 Subject: [PATCH 09/46] Document possible action types for the user activity feed API (#31196) Resolves #31131. It uses the the go-swagger `enum` property to document the activity action types. --- modules/structs/activity.go | 7 +++++-- templates/swagger/v1_json.tmpl | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/modules/structs/activity.go b/modules/structs/activity.go index 6d2ee56b08..ea27fbfd77 100644 --- a/modules/structs/activity.go +++ b/modules/structs/activity.go @@ -6,8 +6,11 @@ package structs import "time" type Activity struct { - ID int64 `json:"id"` - UserID int64 `json:"user_id"` // Receiver user + ID int64 `json:"id"` + UserID int64 `json:"user_id"` // Receiver user + // the type of action + // + // enum: create_repo,rename_repo,star_repo,watch_repo,commit_repo,create_issue,create_pull_request,transfer_repo,push_tag,comment_issue,merge_pull_request,close_issue,reopen_issue,close_pull_request,reopen_pull_request,delete_tag,delete_branch,mirror_sync_push,mirror_sync_create,mirror_sync_delete,approve_pull_request,reject_pull_request,comment_pull,publish_release,pull_review_dismissed,pull_request_ready_for_review,auto_merge_pull_request OpType string `json:"op_type"` ActUserID int64 `json:"act_user_id"` ActUser *User `json:"act_user"` diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index c552e48346..34f09f0587 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -18178,7 +18178,37 @@ "x-go-name": "IsPrivate" }, "op_type": { + "description": "the type of action", "type": "string", + "enum": [ + "create_repo", + "rename_repo", + "star_repo", + "watch_repo", + "commit_repo", + "create_issue", + "create_pull_request", + "transfer_repo", + "push_tag", + "comment_issue", + "merge_pull_request", + "close_issue", + "reopen_issue", + "close_pull_request", + "reopen_pull_request", + "delete_tag", + "delete_branch", + "mirror_sync_push", + "mirror_sync_create", + "mirror_sync_delete", + "approve_pull_request", + "reject_pull_request", + "comment_pull", + "publish_release", + "pull_review_dismissed", + "pull_request_ready_for_review", + "auto_merge_pull_request" + ], "x-go-name": "OpType" }, "ref_name": { From 0f0db6a14fd10a493ba73f211e2e627c3884d114 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 3 Jun 2024 19:21:45 +0200 Subject: [PATCH 10/46] Remove unnecessary inline style for tab-size (#31224) Move the rule to the parent node. `tab-size` is inherited so will work just as before. --- routers/web/repo/issue_content_history.go | 2 +- web_src/css/repo.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go index bf3571c835..a7362113e3 100644 --- a/routers/web/repo/issue_content_history.go +++ b/routers/web/repo/issue_content_history.go @@ -156,7 +156,7 @@ func GetContentHistoryDetail(ctx *context.Context) { // use chroma to render the diff html diffHTMLBuf := bytes.Buffer{} - diffHTMLBuf.WriteString("
")
+	diffHTMLBuf.WriteString("
")
 	for _, it := range diff {
 		if it.Type == diffmatchpatch.DiffInsert {
 			diffHTMLBuf.WriteString("")
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index d3036744fe..e44bc9811b 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -2322,6 +2322,7 @@ tbody.commit-list {
   min-height: 12em;
   max-height: calc(100vh - 10.5rem);
   overflow-y: auto;
+  tab-size: 4;
 }
 
 .comment-diff-data pre {

From 8c68c5e436805848197d98313e9ee77e8d540a83 Mon Sep 17 00:00:00 2001
From: silverwind 
Date: Mon, 3 Jun 2024 20:21:28 +0200
Subject: [PATCH 11/46] Move custom `tw-` helpers to tailwind plugin (#31184)

Move the previous custom `tw-` classes to be defined in a tailwind
plugin. I think it's cleaner that way and I also verified double-class
works as expected:

Screenshot 2024-05-30 at 19 06 24
---
 tailwind.config.js      | 23 +++++++++++++++++++++++
 web_src/css/helpers.css | 16 ----------------
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/tailwind.config.js b/tailwind.config.js
index 94dfdbced4..8f3e8c8251 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,6 +1,7 @@
 import {readFileSync} from 'node:fs';
 import {env} from 'node:process';
 import {parse} from 'postcss';
+import plugin from 'tailwindcss/plugin.js';
 
 const isProduction = env.NODE_ENV !== 'development';
 
@@ -98,4 +99,26 @@ export default {
       })),
     },
   },
+  plugins: [
+    plugin(({addUtilities}) => {
+      addUtilities({
+        // tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
+        // do not use:
+        // * "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
+        // * ".hidden" class: it has been polluted by Fomantic UI in many cases
+        // * inline style="display: none": it's difficult to tweak
+        // * jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
+        // only use:
+        // * this ".tw-hidden" class
+        // * showElem/hideElem/toggleElem functions in "utils/dom.js"
+        '.hidden.hidden': {
+          'display': 'none',
+        },
+        // proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128
+        '.break-anywhere': {
+          'overflow-wrap': 'anywhere',
+        },
+      });
+    }),
+  ],
 };
diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css
index 60ecd7db72..15df9f3a45 100644
--- a/web_src/css/helpers.css
+++ b/web_src/css/helpers.css
@@ -35,22 +35,6 @@ Gitea's private styles use `g-` prefix.
 .interact-bg:hover { background: var(--color-hover) !important; }
 .interact-bg:active { background: var(--color-active) !important; }
 
-/*
-tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
-do not use:
-* "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
-* ".hidden" class: it has been polluted by Fomantic UI in many cases
-* inline style="display: none": it's difficult to tweak
-* jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
-only use:
-* this ".tw-hidden" class
-* showElem/hideElem/toggleElem functions in "utils/dom.js"
-*/
-.tw-hidden.tw-hidden { display: none !important; }
-
-/* proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128 */
-.tw-break-anywhere { overflow-wrap: anywhere !important; }
-
 @media (max-width: 767.98px) {
   /* double selector so it wins over .tw-flex (old .gt-df) etc */
   .not-mobile.not-mobile {

From aace3bccc3290446637cac30b121b94b5d03075f Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Mon, 3 Jun 2024 20:42:52 +0200
Subject: [PATCH 12/46] Add option for mailer to override mail headers (#27860)

Add option to override headers of mails, gitea send out

---
*Sponsored by Kithara Software GmbH*
---
 custom/conf/app.example.ini                   | 10 +++
 .../config-cheat-sheet.en-us.md               | 19 ++++-
 modules/setting/mailer.go                     | 23 ++++--
 services/mailer/mailer.go                     | 10 ++-
 services/mailer/mailer_test.go                | 76 +++++++++++++++++++
 5 files changed, 128 insertions(+), 10 deletions(-)

diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index be5d632f54..7677168d83 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1687,6 +1687,16 @@ LEVEL = Info
 ;; convert \r\n to \n for Sendmail
 ;SENDMAIL_CONVERT_CRLF = true
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;[mailer.override_header]
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; This is empty by default, use it only if you know what you need it for.
+;Reply-To = test@example.com, test2@example.com
+;Content-Type = text/html; charset=utf-8
+;In-Reply-To =
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;[email.incoming]
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index aabf1b20d8..0c15a866b6 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -724,11 +724,13 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
 
 ## Mailer (`mailer`)
 
-⚠️ This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
+:::warning
+This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
 please refer to
 [Gitea 1.17 app.ini example](https://github.com/go-gitea/gitea/blob/release/v1.17/custom/conf/app.example.ini)
 and
 [Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md)
+:::
 
 - `ENABLED`: **false**: Enable to use a mail service.
 - `PROTOCOL`: **_empty_**: Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._
@@ -761,6 +763,21 @@ and
 - `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
 - `SEND_AS_PLAIN_TEXT`: **false**: Send mails only in plain text, without HTML alternative.
 
+## Override Email Headers (`mailer.override_header`)
+
+:::warning
+This is empty by default, use it only if you know what you need it for.
+:::
+
+examples would be:
+
+```ini
+[mailer.override_header]
+Reply-To = test@example.com, test2@example.com
+Content-Type = text/html; charset=utf-8
+In-Reply-To =
+```
+
 ## Incoming Email (`email.incoming`)
 
 - `ENABLED`: **false**: Enable handling of incoming emails.
diff --git a/modules/setting/mailer.go b/modules/setting/mailer.go
index a2bc2df444..58bfd67bfb 100644
--- a/modules/setting/mailer.go
+++ b/modules/setting/mailer.go
@@ -18,14 +18,15 @@ import (
 // Mailer represents mail service.
 type Mailer struct {
 	// Mailer
-	Name                 string `ini:"NAME"`
-	From                 string `ini:"FROM"`
-	EnvelopeFrom         string `ini:"ENVELOPE_FROM"`
-	OverrideEnvelopeFrom bool   `ini:"-"`
-	FromName             string `ini:"-"`
-	FromEmail            string `ini:"-"`
-	SendAsPlainText      bool   `ini:"SEND_AS_PLAIN_TEXT"`
-	SubjectPrefix        string `ini:"SUBJECT_PREFIX"`
+	Name                 string              `ini:"NAME"`
+	From                 string              `ini:"FROM"`
+	EnvelopeFrom         string              `ini:"ENVELOPE_FROM"`
+	OverrideEnvelopeFrom bool                `ini:"-"`
+	FromName             string              `ini:"-"`
+	FromEmail            string              `ini:"-"`
+	SendAsPlainText      bool                `ini:"SEND_AS_PLAIN_TEXT"`
+	SubjectPrefix        string              `ini:"SUBJECT_PREFIX"`
+	OverrideHeader       map[string][]string `ini:"-"`
 
 	// SMTP sender
 	Protocol             string `ini:"PROTOCOL"`
@@ -151,6 +152,12 @@ func loadMailerFrom(rootCfg ConfigProvider) {
 		log.Fatal("Unable to map [mailer] section on to MailService. Error: %v", err)
 	}
 
+	overrideHeader := rootCfg.Section("mailer.override_header").Keys()
+	MailService.OverrideHeader = make(map[string][]string)
+	for _, key := range overrideHeader {
+		MailService.OverrideHeader[key.Name()] = key.Strings(",")
+	}
+
 	// Infer SMTPPort if not set
 	if MailService.SMTPPort == "" {
 		switch MailService.Protocol {
diff --git a/services/mailer/mailer.go b/services/mailer/mailer.go
index 5e8e3dbb38..c5846e6104 100644
--- a/services/mailer/mailer.go
+++ b/services/mailer/mailer.go
@@ -57,7 +57,7 @@ func (m *Message) ToMessage() *gomail.Message {
 		msg.SetHeader(header, m.Headers[header]...)
 	}
 
-	if len(setting.MailService.SubjectPrefix) > 0 {
+	if setting.MailService.SubjectPrefix != "" {
 		msg.SetHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject)
 	} else {
 		msg.SetHeader("Subject", m.Subject)
@@ -79,6 +79,14 @@ func (m *Message) ToMessage() *gomail.Message {
 	if len(msg.GetHeader("Message-ID")) == 0 {
 		msg.SetHeader("Message-ID", m.generateAutoMessageID())
 	}
+
+	for k, v := range setting.MailService.OverrideHeader {
+		if len(msg.GetHeader(k)) != 0 {
+			log.Debug("Mailer override header '%s' as per config", k)
+		}
+		msg.SetHeader(k, v...)
+	}
+
 	return msg
 }
 
diff --git a/services/mailer/mailer_test.go b/services/mailer/mailer_test.go
index 375ca35daa..6d7c44f40c 100644
--- a/services/mailer/mailer_test.go
+++ b/services/mailer/mailer_test.go
@@ -4,6 +4,7 @@
 package mailer
 
 import (
+	"strings"
 	"testing"
 	"time"
 
@@ -36,3 +37,78 @@ func TestGenerateMessageID(t *testing.T) {
 	gm = m.ToMessage()
 	assert.Equal(t, "", gm.GetHeader("Message-ID")[0])
 }
+
+func TestToMessage(t *testing.T) {
+	oldConf := *setting.MailService
+	defer func() {
+		setting.MailService = &oldConf
+	}()
+	setting.MailService.From = "test@gitea.com"
+
+	m1 := Message{
+		Info:            "info",
+		FromAddress:     "test@gitea.com",
+		FromDisplayName: "Test Gitea",
+		To:              "a@b.com",
+		Subject:         "Issue X Closed",
+		Body:            "Some Issue got closed by Y-Man",
+	}
+
+	buf := &strings.Builder{}
+	_, err := m1.ToMessage().WriteTo(buf)
+	assert.NoError(t, err)
+	header, _ := extractMailHeaderAndContent(t, buf.String())
+	assert.EqualValues(t, map[string]string{
+		"Content-Type":             "multipart/alternative;",
+		"Date":                     "Mon, 01 Jan 0001 00:00:00 +0000",
+		"From":                     "\"Test Gitea\" ",
+		"Message-ID":               "",
+		"Mime-Version":             "1.0",
+		"Subject":                  "Issue X Closed",
+		"To":                       "a@b.com",
+		"X-Auto-Response-Suppress": "All",
+	}, header)
+
+	setting.MailService.OverrideHeader = map[string][]string{
+		"Message-ID":     {""},               // delete message id
+		"Auto-Submitted": {"auto-generated"}, // suppress auto replay
+	}
+
+	buf = &strings.Builder{}
+	_, err = m1.ToMessage().WriteTo(buf)
+	assert.NoError(t, err)
+	header, _ = extractMailHeaderAndContent(t, buf.String())
+	assert.EqualValues(t, map[string]string{
+		"Content-Type":             "multipart/alternative;",
+		"Date":                     "Mon, 01 Jan 0001 00:00:00 +0000",
+		"From":                     "\"Test Gitea\" ",
+		"Message-ID":               "",
+		"Mime-Version":             "1.0",
+		"Subject":                  "Issue X Closed",
+		"To":                       "a@b.com",
+		"X-Auto-Response-Suppress": "All",
+		"Auto-Submitted":           "auto-generated",
+	}, header)
+}
+
+func extractMailHeaderAndContent(t *testing.T, mail string) (map[string]string, string) {
+	header := make(map[string]string)
+
+	parts := strings.SplitN(mail, "boundary=", 2)
+	if !assert.Len(t, parts, 2) {
+		return nil, ""
+	}
+	content := strings.TrimSpace("boundary=" + parts[1])
+
+	hParts := strings.Split(parts[0], "\n")
+
+	for _, hPart := range hParts {
+		parts := strings.SplitN(hPart, ":", 2)
+		hk := strings.TrimSpace(parts[0])
+		if hk != "" {
+			header[hk] = strings.TrimSpace(parts[1])
+		}
+	}
+
+	return header, content
+}

From 433963e52ccbe2f469c83a0252ea4cab9b34a467 Mon Sep 17 00:00:00 2001
From: Yarden Shoham 
Date: Tue, 4 Jun 2024 06:01:06 +0300
Subject: [PATCH 13/46] Bump `@github/relative-time-element` to v4.4.1 (#31232)

I tested and all timestamps work as before.

Signed-off-by: Yarden Shoham 
---
 package-lock.json | 8 ++++----
 package.json      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 90cedd63d5..8b1ba766d5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
         "@citation-js/plugin-csl": "0.7.11",
         "@citation-js/plugin-software-formats": "0.6.1",
         "@github/markdown-toolbar-element": "2.2.3",
-        "@github/relative-time-element": "4.4.0",
+        "@github/relative-time-element": "4.4.1",
         "@github/text-expander-element": "2.6.1",
         "@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
         "@primer/octicons": "19.9.0",
@@ -1028,9 +1028,9 @@
       "integrity": "sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A=="
     },
     "node_modules/@github/relative-time-element": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.0.tgz",
-      "integrity": "sha512-CrI6oAecoahG7PF5dsgjdvlF5kCtusVMjg810EULD81TvnDsP+k/FRi/ClFubWLgBo4EGpr2EfvmumtqQFo7ow=="
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.1.tgz",
+      "integrity": "sha512-E2vRcIgDj8AHv/iHpQMLJ/RqKOJ704OXkKw6+Zdhk3X+kVQhOf3Wj8KVz4DfCQ1eOJR8XxY6XVv73yd+pjMfXA=="
     },
     "node_modules/@github/text-expander-element": {
       "version": "2.6.1",
diff --git a/package.json b/package.json
index d7588e093f..5add488bb6 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
     "@citation-js/plugin-csl": "0.7.11",
     "@citation-js/plugin-software-formats": "0.6.1",
     "@github/markdown-toolbar-element": "2.2.3",
-    "@github/relative-time-element": "4.4.0",
+    "@github/relative-time-element": "4.4.1",
     "@github/text-expander-element": "2.6.1",
     "@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
     "@primer/octicons": "19.9.0",

From 93570de4968b7ea843f669b173c373c6fbd1c64a Mon Sep 17 00:00:00 2001
From: yp05327 <576951401@qq.com>
Date: Tue, 4 Jun 2024 14:00:44 +0900
Subject: [PATCH 14/46] Update air package path (#31233)

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index f273cac3a8..e9dc945206 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ COMMA := ,
 
 XGO_VERSION := go-1.22.x
 
-AIR_PACKAGE ?= github.com/cosmtrek/air@v1
+AIR_PACKAGE ?= github.com/air-verse/air@v1
 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0

From a7557494cad5aa850536e17cdaf93988f7daa56e Mon Sep 17 00:00:00 2001
From: silverwind 
Date: Tue, 4 Jun 2024 07:34:34 +0200
Subject: [PATCH 15/46] Update chroma to v2.14.0 (#31177)

https://github.com/alecthomas/chroma/releases/tag/v2.14.0

Tested it with a typescript file.
---
 go.mod | 2 +-
 go.sum | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/go.mod b/go.mod
index 87f2b00e6a..6f739ed6e9 100644
--- a/go.mod
+++ b/go.mod
@@ -20,7 +20,7 @@ require (
 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
 	github.com/ProtonMail/go-crypto v1.0.0
 	github.com/PuerkitoBio/goquery v1.9.1
-	github.com/alecthomas/chroma/v2 v2.13.0
+	github.com/alecthomas/chroma/v2 v2.14.0
 	github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
 	github.com/blevesearch/bleve/v2 v2.3.10
 	github.com/buildkite/terminal-to-html/v3 v3.11.0
diff --git a/go.sum b/go.sum
index 84f7121908..543bd70866 100644
--- a/go.sum
+++ b/go.sum
@@ -82,11 +82,11 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
 github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
 github.com/RoaringBitmap/roaring v1.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE=
 github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
-github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
-github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
+github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
 github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
-github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
-github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
+github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
+github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
 github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
 github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
 github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=

From 4f9b8b397c1acb6f6d26c55e224aafcb5474a85b Mon Sep 17 00:00:00 2001
From: silverwind 
Date: Tue, 4 Jun 2024 08:10:04 +0200
Subject: [PATCH 16/46] Fix overflow on notifications (#31178)

Fixes https://github.com/go-gitea/gitea/issues/31170.

image
---
 templates/user/notification/notification_div.tmpl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/templates/user/notification/notification_div.tmpl b/templates/user/notification/notification_div.tmpl
index bf3b51ee3b..9790a7087a 100644
--- a/templates/user/notification/notification_div.tmpl
+++ b/templates/user/notification/notification_div.tmpl
@@ -44,14 +44,14 @@
 								{{end}}
 							
 							
-								
+
{{.Repository.FullName}} {{if .Issue}}#{{.Issue.Index}}{{end}} {{if eq .Status 3}} {{svg "octicon-pin" 13 "text blue tw-mt-0.5 tw-ml-1"}} {{end}}
- + {{if .Issue}} {{.Issue.Title | RenderEmoji $.Context | RenderCodeBlock}} {{else}} From c888c933a930ee2ba4e7bb0bf6678aaf45a9778a Mon Sep 17 00:00:00 2001 From: Thomas Desveaux Date: Tue, 4 Jun 2024 08:45:56 +0200 Subject: [PATCH 17/46] Fix NuGet Package API for $filter with Id equality (#31188) Fixes issue when running `choco info pkgname` where `pkgname` is also a substring of another package Id. Relates to #31168 --- This might fix the issue linked, but I'd like to test it with more choco commands before closing the issue in case I find other problems if that's ok. --------- Co-authored-by: KN4CK3R --- routers/api/packages/nuget/nuget.go | 48 +++++---- tests/integration/api_packages_nuget_test.go | 102 ++++++++++++++++--- 2 files changed, 115 insertions(+), 35 deletions(-) diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index 26b0ae226e..3633d0d007 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -96,20 +96,34 @@ func FeedCapabilityResource(ctx *context.Context) { xmlResponse(ctx, http.StatusOK, Metadata) } -var searchTermExtract = regexp.MustCompile(`'([^']+)'`) +var ( + searchTermExtract = regexp.MustCompile(`'([^']+)'`) + searchTermExact = regexp.MustCompile(`\s+eq\s+'`) +) -func getSearchTerm(ctx *context.Context) string { +func getSearchTerm(ctx *context.Context) packages_model.SearchValue { searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'") - if searchTerm == "" { - // $filter contains a query like: - // (((Id ne null) and substringof('microsoft',tolower(Id))) - // We don't support these queries, just extract the search term. - match := searchTermExtract.FindStringSubmatch(ctx.FormTrim("$filter")) - if len(match) == 2 { - searchTerm = strings.TrimSpace(match[1]) + if searchTerm != "" { + return packages_model.SearchValue{ + Value: searchTerm, + ExactMatch: false, } } - return searchTerm + + // $filter contains a query like: + // (((Id ne null) and substringof('microsoft',tolower(Id))) + // https://www.odata.org/documentation/odata-version-2-0/uri-conventions/ section 4.5 + // We don't support these queries, just extract the search term. + filter := ctx.FormTrim("$filter") + match := searchTermExtract.FindStringSubmatch(filter) + if len(match) == 2 { + return packages_model.SearchValue{ + Value: strings.TrimSpace(match[1]), + ExactMatch: searchTermExact.MatchString(filter), + } + } + + return packages_model.SearchValue{} } // https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs @@ -118,11 +132,9 @@ func SearchServiceV2(ctx *context.Context) { paginator := db.NewAbsoluteListOptions(skip, take) pvs, total, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{ - OwnerID: ctx.Package.Owner.ID, - Type: packages_model.TypeNuGet, - Name: packages_model.SearchValue{ - Value: getSearchTerm(ctx), - }, + OwnerID: ctx.Package.Owner.ID, + Type: packages_model.TypeNuGet, + Name: getSearchTerm(ctx), IsInternal: optional.Some(false), Paginator: paginator, }) @@ -169,10 +181,8 @@ func SearchServiceV2(ctx *context.Context) { // http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351 func SearchServiceV2Count(ctx *context.Context) { count, err := nuget_model.CountPackages(ctx, &packages_model.PackageSearchOptions{ - OwnerID: ctx.Package.Owner.ID, - Name: packages_model.SearchValue{ - Value: getSearchTerm(ctx), - }, + OwnerID: ctx.Package.Owner.ID, + Name: getSearchTerm(ctx), IsInternal: optional.Some(false), }) if err != nil { diff --git a/tests/integration/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go index 83947ff967..630b4de3f9 100644 --- a/tests/integration/api_packages_nuget_test.go +++ b/tests/integration/api_packages_nuget_test.go @@ -429,22 +429,33 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) t.Run("SearchService", func(t *testing.T) { cases := []struct { - Query string - Skip int - Take int - ExpectedTotal int64 - ExpectedResults int + Query string + Skip int + Take int + ExpectedTotal int64 + ExpectedResults int + ExpectedExactMatch bool }{ - {"", 0, 0, 1, 1}, - {"", 0, 10, 1, 1}, - {"gitea", 0, 10, 0, 0}, - {"test", 0, 10, 1, 1}, - {"test", 1, 10, 1, 0}, + {"", 0, 0, 4, 4, false}, + {"", 0, 10, 4, 4, false}, + {"gitea", 0, 10, 0, 0, false}, + {"test", 0, 10, 1, 1, false}, + {"test", 1, 10, 1, 0, false}, + {"almost.similar", 0, 0, 3, 3, true}, } - req := NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")). - AddBasicAuth(user.Name) - MakeRequest(t, req, http.StatusCreated) + fakePackages := []string{ + packageName, + "almost.similar.dependency", + "almost.similar", + "almost.similar.dependant", + } + + for _, fakePackageName := range fakePackages { + req := NewRequestWithBody(t, "PUT", url, createPackage(fakePackageName, "1.0.99")). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusCreated) + } t.Run("v2", func(t *testing.T) { t.Run("Search()", func(t *testing.T) { @@ -491,6 +502,63 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) } }) + t.Run("Packages()", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + t.Run("substringof", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + for i, c := range cases { + req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). + AddBasicAuth(user.Name) + resp := MakeRequest(t, req, http.StatusOK) + + var result FeedResponse + decodeXML(t, resp, &result) + + assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i) + assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). + AddBasicAuth(user.Name) + resp = MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i) + } + }) + + t.Run("IdEq", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + for i, c := range cases { + if c.Query == "" { + // Ignore the `tolower(Id) eq ''` as it's unlikely to happen + continue + } + req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). + AddBasicAuth(user.Name) + resp := MakeRequest(t, req, http.StatusOK) + + var result FeedResponse + decodeXML(t, resp, &result) + + expectedCount := 0 + if c.ExpectedExactMatch { + expectedCount = 1 + } + + assert.Equal(t, int64(expectedCount), result.Count, "case %d: unexpected total hits", i) + assert.Len(t, result.Entries, expectedCount, "case %d: unexpected result count", i) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)). + AddBasicAuth(user.Name) + resp = MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, strconv.FormatInt(int64(expectedCount), 10), resp.Body.String(), "case %d: unexpected total hits", i) + } + }) + }) + t.Run("Next", func(t *testing.T) { req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='test'&$skip=0&$top=1", url)). AddBasicAuth(user.Name) @@ -548,9 +616,11 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) }) }) - req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")). - AddBasicAuth(user.Name) - MakeRequest(t, req, http.StatusNoContent) + for _, fakePackageName := range fakePackages { + req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, fakePackageName, "1.0.99")). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusNoContent) + } }) t.Run("RegistrationService", func(t *testing.T) { From 1f8ac27b31b52791396f198b665a1d6bbdcfd8b3 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 4 Jun 2024 09:14:24 +0200 Subject: [PATCH 18/46] Fix overflow on push notification (#31179) Fixes: https://github.com/go-gitea/gitea/issues/30063 Screenshot 2024-05-30 at 14 43 24 --- templates/repo/code/recently_pushed_new_branches.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/repo/code/recently_pushed_new_branches.tmpl b/templates/repo/code/recently_pushed_new_branches.tmpl index 7f613fcba7..025cc1a403 100644 --- a/templates/repo/code/recently_pushed_new_branches.tmpl +++ b/templates/repo/code/recently_pushed_new_branches.tmpl @@ -1,6 +1,6 @@ {{range .RecentlyPushedNewBranches}} -
-
+
+
{{$timeSince := TimeSince .CommitTime.AsTime ctx.Locale}} {{$branchLink := HTMLFormat `%s` .BranchLink .BranchDisplayName}} {{ctx.Locale.Tr "repo.pulls.recently_pushed_new_branches" $branchLink $timeSince}} From 4ca65fabdad75e39f9948b9a2a18e32edc98ec02 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 4 Jun 2024 09:46:05 +0200 Subject: [PATCH 19/46] Remove .segment from .project-column (#31204) Using `.segment` on the project columns is a major abuse of that class, so remove it and instead set the border-radius directly on it. Fixes: https://github.com/go-gitea/gitea/issues/31129 --- templates/projects/view.tmpl | 2 +- web_src/css/features/projects.css | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 45c8461218..6d331caba7 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -66,7 +66,7 @@
{{range .Columns}} -
+
{{.NumIssues ctx}} diff --git a/web_src/css/features/projects.css b/web_src/css/features/projects.css index e25182051a..151b0a23d9 100644 --- a/web_src/css/features/projects.css +++ b/web_src/css/features/projects.css @@ -9,6 +9,7 @@ .project-column { background-color: var(--color-project-column-bg) !important; border: 1px solid var(--color-secondary) !important; + border-radius: var(--border-radius); margin: 0 0.5rem !important; padding: 0.5rem !important; width: 320px; From 90008111181b874ac018455d8d7a2f8bfe6bc71e Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 4 Jun 2024 20:19:41 +0800 Subject: [PATCH 20/46] Make pasted "img" tag has the same behavior as markdown image (#31235) Fix #31230 --------- Co-authored-by: Lunny Xiao --- modules/markup/html.go | 60 ++++++++++++++++++++-------- modules/markup/html_internal_test.go | 19 +++++---- modules/markup/html_test.go | 51 ++++++++++------------- modules/markup/renderer.go | 2 +- web_src/js/features/comp/Paste.js | 6 ++- 5 files changed, 79 insertions(+), 59 deletions(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index 0af74d2680..8dbc958299 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -372,7 +372,42 @@ func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output return nil } -func visitNode(ctx *RenderContext, procs []processor, node *html.Node) { +func handleNodeImg(ctx *RenderContext, img *html.Node) { + for i, attr := range img.Attr { + if attr.Key != "src" { + continue + } + + if attr.Val != "" && !IsFullURLString(attr.Val) && !strings.HasPrefix(attr.Val, "/") { + attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsWiki), attr.Val) + + // By default, the "" tag should also be clickable, + // because frontend use `` to paste the re-scaled image into the markdown, + // so it must match the default markdown image behavior. + hasParentAnchor := false + for p := img.Parent; p != nil; p = p.Parent { + if hasParentAnchor = p.Type == html.ElementNode && p.Data == "a"; hasParentAnchor { + break + } + } + if !hasParentAnchor { + imgA := &html.Node{Type: html.ElementNode, Data: "a", Attr: []html.Attribute{ + {Key: "href", Val: attr.Val}, + {Key: "target", Val: "_blank"}, + }} + parent := img.Parent + imgNext := img.NextSibling + parent.RemoveChild(img) + parent.InsertBefore(imgA, imgNext) + imgA.AppendChild(img) + } + } + attr.Val = camoHandleLink(attr.Val) + img.Attr[i] = attr + } +} + +func visitNode(ctx *RenderContext, procs []processor, node *html.Node) *html.Node { // Add user-content- to IDs and "#" links if they don't already have them for idx, attr := range node.Attr { val := strings.TrimPrefix(attr.Val, "#") @@ -397,21 +432,14 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) { textNode(ctx, procs, node) case html.ElementNode: if node.Data == "img" { - for i, attr := range node.Attr { - if attr.Key != "src" { - continue - } - if len(attr.Val) > 0 && !IsFullURLString(attr.Val) && !strings.HasPrefix(attr.Val, "data:image/") { - attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsWiki), attr.Val) - } - attr.Val = camoHandleLink(attr.Val) - node.Attr[i] = attr - } + next := node.NextSibling + handleNodeImg(ctx, node) + return next } else if node.Data == "a" { // Restrict text in links to emojis procs = emojiProcessors } else if node.Data == "code" || node.Data == "pre" { - return + return node.NextSibling } else if node.Data == "i" { for _, attr := range node.Attr { if attr.Key != "class" { @@ -434,11 +462,11 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) { } } } - for n := node.FirstChild; n != nil; n = n.NextSibling { - visitNode(ctx, procs, n) + for n := node.FirstChild; n != nil; { + n = visitNode(ctx, procs, n) } } - // ignore everything else + return node.NextSibling } // textNode runs the passed node through various processors, in order to handle @@ -851,7 +879,7 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) { // FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered? // The "mode" approach should be refactored to some other more clear&reliable way. - crossLinkOnly := (ctx.Metas["mode"] == "document" && !ctx.IsWiki) + crossLinkOnly := ctx.Metas["mode"] == "document" && !ctx.IsWiki var ( found bool diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index 3ff0597851..9aa9c22d70 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -18,8 +18,7 @@ import ( const ( TestAppURL = "http://localhost:3000/" - TestOrgRepo = "gogits/gogs" - TestRepoURL = TestAppURL + TestOrgRepo + "/" + TestRepoURL = TestAppURL + "test-owner/test-repo/" ) // externalIssueLink an HTML link to an alphanumeric-style issue @@ -64,8 +63,8 @@ var regexpMetas = map[string]string{ // these values should match the TestOrgRepo const above var localMetas = map[string]string{ - "user": "gogits", - "repo": "gogs", + "user": "test-owner", + "repo": "test-repo", } func TestRender_IssueIndexPattern(t *testing.T) { @@ -362,12 +361,12 @@ func TestRender_FullIssueURLs(t *testing.T) { `Look here person/repo#4`) test("http://localhost:3000/person/repo/issues/4#issuecomment-1234", `person/repo#4 (comment)`) - test("http://localhost:3000/gogits/gogs/issues/4", - `#4`) - test("http://localhost:3000/gogits/gogs/issues/4 test", - `#4 test`) - test("http://localhost:3000/gogits/gogs/issues/4?a=1&b=2#comment-123 test", - `#4 (comment) test`) + test("http://localhost:3000/test-owner/test-repo/issues/4", + `#4`) + test("http://localhost:3000/test-owner/test-repo/issues/4 test", + `#4 test`) + test("http://localhost:3000/test-owner/test-repo/issues/4?a=1&b=2#comment-123 test", + `#4 (comment) test`) test("http://localhost:3000/testOrg/testOrgRepo/pulls/2/files#issuecomment-24", "http://localhost:3000/testOrg/testOrgRepo/pulls/2/files#issuecomment-24") test("http://localhost:3000/testOrg/testOrgRepo/pulls/2/files", diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index e2d08692e4..df3c2609ef 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -120,8 +120,8 @@ func TestRender_CrossReferences(t *testing.T) { } test( - "gogits/gogs#12345", - `

gogits/gogs#12345

`) + "test-owner/test-repo#12345", + `

test-owner/test-repo#12345

`) test( "go-gitea/gitea#12345", `

go-gitea/gitea#12345

`) @@ -530,43 +530,31 @@ func TestRender_ShortLinks(t *testing.T) { } func TestRender_RelativeImages(t *testing.T) { - setting.AppURL = markup.TestAppURL - - test := func(input, expected, expectedWiki string) { + render := func(input string, isWiki bool, links markup.Links) string { buffer, err := markdown.RenderString(&markup.RenderContext{ - Ctx: git.DefaultContext, - Links: markup.Links{ - Base: markup.TestRepoURL, - BranchPath: "master", - }, - Metas: localMetas, - }, input) - assert.NoError(t, err) - assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) - buffer, err = markdown.RenderString(&markup.RenderContext{ - Ctx: git.DefaultContext, - Links: markup.Links{ - Base: markup.TestRepoURL, - }, + Ctx: git.DefaultContext, + Links: links, Metas: localMetas, - IsWiki: true, + IsWiki: isWiki, }, input) assert.NoError(t, err) - assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) + return strings.TrimSpace(string(buffer)) } - rawwiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw") - mediatree := util.URLJoin(markup.TestRepoURL, "media", "master") + out := render(``, false, markup.Links{Base: "/test-owner/test-repo"}) + assert.Equal(t, ``, out) - test( - ``, - ``, - ``) + out = render(``, true, markup.Links{Base: "/test-owner/test-repo"}) + assert.Equal(t, ``, out) - test( - ``, - ``, - ``) + out = render(``, false, markup.Links{Base: "/test-owner/test-repo", BranchPath: "test-branch"}) + assert.Equal(t, ``, out) + + out = render(``, true, markup.Links{Base: "/test-owner/test-repo", BranchPath: "test-branch"}) + assert.Equal(t, ``, out) + + out = render(``, true, markup.Links{Base: "/test-owner/test-repo", BranchPath: "test-branch"}) + assert.Equal(t, ``, out) } func Test_ParseClusterFuzz(t *testing.T) { @@ -719,5 +707,6 @@ func TestIssue18471(t *testing.T) { func TestIsFullURL(t *testing.T) { assert.True(t, markup.IsFullURLString("https://example.com")) assert.True(t, markup.IsFullURLString("mailto:test@example.com")) + assert.True(t, markup.IsFullURLString("data:image/11111")) assert.False(t, markup.IsFullURLString("/foo:bar")) } diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go index 44dedf638b..66e8cf611d 100644 --- a/modules/markup/renderer.go +++ b/modules/markup/renderer.go @@ -74,7 +74,7 @@ type RenderContext struct { Type string IsWiki bool Links Links - Metas map[string]string + Metas map[string]string // user, repo, mode(comment/document) DefaultLink string GitRepo *git.Repository Repo gitrepo.Repository diff --git a/web_src/js/features/comp/Paste.js b/web_src/js/features/comp/Paste.js index b26296d1fc..35a7ceaef8 100644 --- a/web_src/js/features/comp/Paste.js +++ b/web_src/js/features/comp/Paste.js @@ -100,13 +100,17 @@ async function handleClipboardImages(editor, dropzone, images, e) { const {uuid} = await uploadFile(img, uploadUrl); const {width, dppx} = await imageInfo(img); - const url = `/attachments/${uuid}`; let text; if (width > 0 && dppx > 1) { // Scale down images from HiDPI monitors. This uses the tag because it's the only // method to change image size in Markdown that is supported by all implementations. + // Make the image link relative to the repo path, then the final URL is "/sub-path/owner/repo/attachments/{uuid}" + const url = `attachments/${uuid}`; text = `${htmlEscape(name)}`; } else { + // Markdown always renders the image with a relative path, so the final URL is "/sub-path/owner/repo/attachments/{uuid}" + // TODO: it should also use relative path for consistency, because absolute is ambiguous for "/sub-path/attachments" or "/attachments" + const url = `/attachments/${uuid}`; text = `![${name}](${url})`; } editor.replacePlaceholder(placeholder, text); From 138e946c3d8e2731f11a3e3b6876889694822f46 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 4 Jun 2024 15:57:11 +0200 Subject: [PATCH 21/46] Replace `gt-word-break` with `tw-break-anywhere` (#31183) `overflow-wrap: anywhere` is a superior alternative to `word-wrap: break-word` and we were already setting it in the class. I tested a few cases, all look good. --- docs/content/contributing/guidelines-frontend.en-us.md | 2 +- docs/content/contributing/guidelines-frontend.zh-cn.md | 2 +- templates/admin/repo/list.tmpl | 4 ++-- templates/package/content/container.tmpl | 4 ++-- templates/package/settings.tmpl | 2 +- templates/projects/view.tmpl | 2 +- templates/repo/home.tmpl | 2 +- templates/repo/issue/list.tmpl | 2 +- templates/repo/issue/view_content/conversation.tmpl | 2 +- templates/repo/release/list.tmpl | 2 +- templates/repo/settings/options.tmpl | 2 +- templates/repo/wiki/revision.tmpl | 2 +- templates/shared/user/org_profile_avatar.tmpl | 2 +- templates/shared/user/profile_big_avatar.tmpl | 4 ++-- web_src/css/helpers.css | 5 ----- web_src/js/features/repo-issue.js | 2 +- 16 files changed, 18 insertions(+), 23 deletions(-) diff --git a/docs/content/contributing/guidelines-frontend.en-us.md b/docs/content/contributing/guidelines-frontend.en-us.md index efeaf38bb2..a08098a931 100644 --- a/docs/content/contributing/guidelines-frontend.en-us.md +++ b/docs/content/contributing/guidelines-frontend.en-us.md @@ -47,7 +47,7 @@ We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/h 9. Avoid unnecessary `!important` in CSS, add comments to explain why it's necessary if it can't be avoided. 10. Avoid mixing different events in one event listener, prefer to use individual event listeners for every event. 11. Custom event names are recommended to use `ce-` prefix. -12. Prefer using Tailwind CSS which is available via `tw-` prefix, e.g. `tw-relative`. Gitea's helper CSS classes use `gt-` prefix (`gt-word-break`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). +12. Prefer using Tailwind CSS which is available via `tw-` prefix, e.g. `tw-relative`. Gitea's helper CSS classes use `gt-` prefix (`gt-ellipsis`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). 13. Avoid inline scripts & styles as much as possible, it's recommended to put JS code into JS files and use CSS classes. If inline scripts & styles are unavoidable, explain the reason why it can't be avoided. ### Accessibility / ARIA diff --git a/docs/content/contributing/guidelines-frontend.zh-cn.md b/docs/content/contributing/guidelines-frontend.zh-cn.md index 394097b259..198e1227e5 100644 --- a/docs/content/contributing/guidelines-frontend.zh-cn.md +++ b/docs/content/contributing/guidelines-frontend.zh-cn.md @@ -47,7 +47,7 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。 9. 避免在 CSS 中使用不必要的`!important`,如果无法避免,添加注释解释为什么需要它。 10. 避免在一个事件监听器中混合不同的事件,优先为每个事件使用独立的事件监听器。 11. 推荐使用自定义事件名称前缀`ce-`。 -12. 建议使用 Tailwind CSS,它可以通过 `tw-` 前缀获得,例如 `tw-relative`. Gitea 自身的助手类 CSS 使用 `gt-` 前缀(`gt-word-break`),Gitea 自身的私有框架级 CSS 类使用 `g-` 前缀(`g-modal-confirm`)。 +12. 建议使用 Tailwind CSS,它可以通过 `tw-` 前缀获得,例如 `tw-relative`. Gitea 自身的助手类 CSS 使用 `gt-` 前缀(`gt-ellipsis`),Gitea 自身的私有框架级 CSS 类使用 `g-` 前缀(`g-modal-confirm`)。 13. 尽量避免内联脚本和样式,建议将JS代码放入JS文件中并使用CSS类。如果内联脚本和样式不可避免,请解释无法避免的原因。 ### 可访问性 / ARIA diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 4b27d87a45..69031e42eb 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -47,13 +47,13 @@ {{.ID}} - {{.Owner.Name}} + {{.Owner.Name}} {{if .Owner.Visibility.IsPrivate}} {{svg "octicon-lock"}} {{end}} - {{.Name}} + {{.Name}} {{if .IsArchived}} {{ctx.Locale.Tr "repo.desc.archived"}} {{end}} diff --git a/templates/package/content/container.tmpl b/templates/package/content/container.tmpl index fe393f4388..138fedecb3 100644 --- a/templates/package/content/container.tmpl +++ b/templates/package/content/container.tmpl @@ -54,7 +54,7 @@ {{end}} {{if .PackageDescriptor.Metadata.ImageLayers}}

{{ctx.Locale.Tr "packages.container.layers"}}

-
+
{{range .PackageDescriptor.Metadata.ImageLayers}} @@ -80,7 +80,7 @@ {{range $key, $value := .PackageDescriptor.Metadata.Labels}} - + {{end}} diff --git a/templates/package/settings.tmpl b/templates/package/settings.tmpl index 9424baf493..4b8773477b 100644 --- a/templates/package/settings.tmpl +++ b/templates/package/settings.tmpl @@ -59,7 +59,7 @@ {{ctx.Locale.Tr "packages.settings.delete"}}
-
+
{{ctx.Locale.Tr "packages.settings.delete.notice" .PackageDescriptor.Package.Name .PackageDescriptor.Version.Version}}
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 6d331caba7..584462d2a2 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -152,7 +152,7 @@
{{range (index $.IssuesMap .ID)}} -
+
{{template "repo/issue/card" (dict "Issue" . "Page" $)}}
{{end}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index ef76f3ed5d..ff82f2ca80 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -5,7 +5,7 @@ {{template "base/alert" .}} {{template "repo/code/recently_pushed_new_branches" .}} {{if and (not .HideRepoInfo) (not .IsBlame)}} -
+
{{- $description := .Repository.DescriptionHTML ctx -}} {{if $description}}{{$description | RenderCodeBlock}}{{end}} {{if .Repository.Website}}{{.Repository.Website}}{{end}} diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 30edf825f1..01b610b39d 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -7,7 +7,7 @@ {{if .PinnedIssues}}
{{range .PinnedIssues}} -
+
{{template "repo/issue/card" (dict "Issue" . "Page" $ "isPinnedIssueCard" true)}}
{{end}} diff --git a/templates/repo/issue/view_content/conversation.tmpl b/templates/repo/issue/view_content/conversation.tmpl index 43ec9d75c4..ccea9b690d 100644 --- a/templates/repo/issue/view_content/conversation.tmpl +++ b/templates/repo/issue/view_content/conversation.tmpl @@ -8,7 +8,7 @@
- {{$comment.TreePath}} + {{$comment.TreePath}} {{if $invalid}} {{ctx.Locale.Tr "repo.issues.review.outdated"}} diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index 34548672b5..e5bf23faac 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -17,7 +17,7 @@
-

+

{{if $.PageIsSingleTag}}{{$release.Title}}{{else}}{{$release.Title}}{{end}} {{template "repo/commit_statuses" dict "Status" $info.CommitStatus "Statuses" $info.CommitStatuses "AdditionalClasses" "tw-flex"}} {{if $release.IsDraft}} diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 6c49f00094..4f98133df3 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -217,7 +217,7 @@

{{range .PushMirrors}} - + - From e728fd741be7848d476663eec1c9caaf34b46e61 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 6 Jun 2024 10:28:33 +0800 Subject: [PATCH 27/46] Fix Activity Page Contributors dropdown (#31264) Fix #31261 --- routers/web/repo/contributors.go | 6 ------ templates/repo/contributors.tmpl | 1 + web_src/js/components/RepoContributors.vue | 21 ++++++++++----------- web_src/js/features/contributors.js | 1 + 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/routers/web/repo/contributors.go b/routers/web/repo/contributors.go index 5fda17469e..762fbf9379 100644 --- a/routers/web/repo/contributors.go +++ b/routers/web/repo/contributors.go @@ -19,14 +19,8 @@ const ( // Contributors render the page to show repository contributors graph func Contributors(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.activity.navbar.contributors") - ctx.Data["PageIsActivity"] = true ctx.Data["PageIsContributors"] = true - - ctx.PageData["contributionType"] = "commits" - - ctx.PageData["repoLink"] = ctx.Repo.RepoLink - ctx.HTML(http.StatusOK, tplContributors) } diff --git a/templates/repo/contributors.tmpl b/templates/repo/contributors.tmpl index 54e3e426a2..6b8a63fe99 100644 --- a/templates/repo/contributors.tmpl +++ b/templates/repo/contributors.tmpl @@ -1,5 +1,6 @@ {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
{ @@ -59,14 +57,17 @@ export default { type: Object, required: true, }, + repoLink: { + type: String, + required: true, + }, }, data: () => ({ isLoading: false, errorText: '', totalStats: {}, sortedContributors: {}, - repoLink: pageData.repoLink || [], - type: pageData.contributionType, + type: 'commits', contributorsStats: [], xAxisStart: null, xAxisEnd: null, @@ -333,19 +334,17 @@ export default {
{{$key}}{{$value}}{{$value}}
{{.RemoteAddress}}{{.RemoteAddress}} {{ctx.Locale.Tr "repo.settings.mirror_settings.direction.push"}} {{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} {{if .LastError}}
{{ctx.Locale.Tr "error"}}
{{end}}
diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl index 8e0060d4b3..7fca703843 100644 --- a/templates/repo/wiki/revision.tmpl +++ b/templates/repo/wiki/revision.tmpl @@ -8,7 +8,7 @@
{{.revision}} {{svg "octicon-home"}} {{$title}} -
+
{{$timeSince := TimeSince .Author.When ctx.Locale}} {{ctx.Locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince}}
diff --git a/templates/shared/user/org_profile_avatar.tmpl b/templates/shared/user/org_profile_avatar.tmpl index d67f133abf..c0abcabff1 100644 --- a/templates/shared/user/org_profile_avatar.tmpl +++ b/templates/shared/user/org_profile_avatar.tmpl @@ -2,7 +2,7 @@
-
+
{{ctx.AvatarUtils.Avatar . 100}} {{.DisplayName}} diff --git a/templates/shared/user/profile_big_avatar.tmpl b/templates/shared/user/profile_big_avatar.tmpl index 868f8d5a13..29c6eb0eb0 100644 --- a/templates/shared/user/profile_big_avatar.tmpl +++ b/templates/shared/user/profile_big_avatar.tmpl @@ -11,7 +11,7 @@ {{end}}
-
+
{{if .ContextUser.FullName}}{{.ContextUser.FullName}}{{end}} {{.ContextUser.Name}} {{if .IsAdmin}} @@ -25,7 +25,7 @@ {{end}}
-
+
    {{if .UserBlocking}}
  • {{svg "octicon-circle-slash"}} {{ctx.Locale.Tr "user.block.blocked"}}
  • diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index 15df9f3a45..42d06e2e66 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -3,11 +3,6 @@ Gitea's tailwind-style CSS helper classes have `gt-` prefix. Gitea's private styles use `g-` prefix. */ -.gt-word-break { - word-wrap: break-word !important; - overflow-wrap: anywhere; -} - .gt-ellipsis { overflow: hidden !important; white-space: nowrap !important; diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 519db34934..95910e34bc 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -125,7 +125,7 @@ export function initRepoIssueSidebarList() { } filteredResponse.results.push({ name: `
    #${issue.number} ${htmlEscape(issue.title)}
    -
    ${htmlEscape(issue.repository.full_name)}
    `, +
    ${htmlEscape(issue.repository.full_name)}
    `, value: issue.id, }); }); From fcc061ae4435f251d14a6750a0f5713800dca637 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 4 Jun 2024 23:06:21 +0800 Subject: [PATCH 22/46] Fix admin oauth2 custom URL settings (#31246) Fix #31244 --- web_src/js/features/admin/common.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/web_src/js/features/admin/common.js b/web_src/js/features/admin/common.js index b35502d52f..3c90b546b8 100644 --- a/web_src/js/features/admin/common.js +++ b/web_src/js/features/admin/common.js @@ -67,39 +67,44 @@ export function initAdminCommon() { input.removeAttribute('required'); } - const provider = document.getElementById('oauth2_provider')?.value; + const provider = document.getElementById('oauth2_provider').value; switch (provider) { case 'openidConnect': - for (const input of document.querySelectorAll('.open_id_connect_auto_discovery_url input')) { - input.setAttribute('required', 'required'); - } + document.querySelector('.open_id_connect_auto_discovery_url input').setAttribute('required', 'required'); showElem('.open_id_connect_auto_discovery_url'); break; - default: - if (document.getElementById(`#${provider}_customURLSettings`)?.getAttribute('data-required')) { - document.getElementById('oauth2_use_custom_url')?.setAttribute('checked', 'checked'); + default: { + const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); + if (!elProviderCustomUrlSettings) break; // some providers do not have custom URL settings + const couldChangeCustomURLs = elProviderCustomUrlSettings.getAttribute('data-available') === 'true'; + const mustProvideCustomURLs = elProviderCustomUrlSettings.getAttribute('data-required') === 'true'; + if (couldChangeCustomURLs) { + showElem('.oauth2_use_custom_url'); // show the checkbox } - if (document.getElementById(`#${provider}_customURLSettings`)?.getAttribute('data-available')) { - showElem('.oauth2_use_custom_url'); + if (mustProvideCustomURLs) { + document.querySelector('#oauth2_use_custom_url').checked = true; // make the checkbox checked } + break; + } } onOAuth2UseCustomURLChange(applyDefaultValues); } function onOAuth2UseCustomURLChange(applyDefaultValues) { - const provider = document.getElementById('oauth2_provider')?.value; + const provider = document.getElementById('oauth2_provider').value; hideElem('.oauth2_use_custom_url_field'); for (const input of document.querySelectorAll('.oauth2_use_custom_url_field input[required]')) { input.removeAttribute('required'); } - if (document.getElementById('oauth2_use_custom_url')?.checked) { + const elProviderCustomUrlSettings = document.querySelector(`#${provider}_customURLSettings`); + if (elProviderCustomUrlSettings && document.getElementById('oauth2_use_custom_url').checked) { for (const custom of ['token_url', 'auth_url', 'profile_url', 'email_url', 'tenant']) { if (applyDefaultValues) { document.getElementById(`oauth2_${custom}`).value = document.getElementById(`${provider}_${custom}`).value; } const customInput = document.getElementById(`${provider}_${custom}`); - if (customInput && customInput.getAttribute('data-available')) { + if (customInput && customInput.getAttribute('data-available') === 'true') { for (const input of document.querySelectorAll(`.oauth2_${custom} input`)) { input.setAttribute('required', 'required'); } From bd80225ec3688cfa89767cc352835d8d5093f764 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 4 Jun 2024 23:35:29 +0800 Subject: [PATCH 23/46] Make blockquote attention recognize more syntaxes (#31240) Fix #31214 --- modules/markup/markdown/markdown_test.go | 6 ++ modules/markup/markdown/math/block_parser.go | 10 +- .../markup/markdown/transform_blockquote.go | 91 +++++++++++++++---- 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index b4a7efa8dd..8c41ec12e3 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -1019,4 +1019,10 @@ func TestAttention(t *testing.T) { test(`> [!important]`, renderAttention("important", "octicon-report")+"\n") test(`> [!warning]`, renderAttention("warning", "octicon-alert")+"\n") test(`> [!caution]`, renderAttention("caution", "octicon-stop")+"\n") + + // escaped by mdformat + test(`> \[!NOTE\]`, renderAttention("note", "octicon-info")+"\n") + + // legacy GitHub style + test(`> **warning**`, renderAttention("warning", "octicon-alert")+"\n") } diff --git a/modules/markup/markdown/math/block_parser.go b/modules/markup/markdown/math/block_parser.go index 7f714d7239..37f6caf11c 100644 --- a/modules/markup/markdown/math/block_parser.go +++ b/modules/markup/markdown/math/block_parser.go @@ -31,10 +31,16 @@ func (b *blockParser) Open(parent ast.Node, reader text.Reader, pc parser.Contex return nil, parser.NoChildren } - dollars := false + var dollars bool if b.parseDollars && line[pos] == '$' && line[pos+1] == '$' { dollars = true - } else if line[pos] != '\\' || line[pos+1] != '[' { + } else if line[pos] == '\\' && line[pos+1] == '[' { + if len(line[pos:]) >= 3 && line[pos+2] == '!' && bytes.Contains(line[pos:], []byte(`\]`)) { + // do not process escaped attention block: "> \[!NOTE\]" + return nil, parser.NoChildren + } + dollars = false + } else { return nil, parser.NoChildren } diff --git a/modules/markup/markdown/transform_blockquote.go b/modules/markup/markdown/transform_blockquote.go index 933f0e5c59..d2dc025052 100644 --- a/modules/markup/markdown/transform_blockquote.go +++ b/modules/markup/markdown/transform_blockquote.go @@ -15,7 +15,7 @@ import ( "golang.org/x/text/language" ) -// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg +// renderAttention renders a quote marked with i.e. "> **Note**" or "> [!Warning]" with a corresponding svg func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { if entering { n := node.(*Attention) @@ -37,38 +37,93 @@ func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast return ast.WalkContinue, nil } -func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) { - // We only want attention blockquotes when the AST looks like: - // > Text("[") Text("!TYPE") Text("]") +func (g *ASTTransformer) extractBlockquoteAttentionEmphasis(firstParagraph ast.Node, reader text.Reader) (string, []ast.Node) { + if firstParagraph.ChildCount() < 1 { + return "", nil + } + node1, ok := firstParagraph.FirstChild().(*ast.Emphasis) + if !ok { + return "", nil + } + val1 := string(node1.Text(reader.Source())) + attentionType := strings.ToLower(val1) + if g.attentionTypes.Contains(attentionType) { + return attentionType, []ast.Node{node1} + } + return "", nil +} - // grab these nodes and make sure we adhere to the attention blockquote structure - firstParagraph := v.FirstChild() - g.applyElementDir(firstParagraph) - if firstParagraph.ChildCount() < 3 { - return ast.WalkContinue, nil +func (g *ASTTransformer) extractBlockquoteAttention2(firstParagraph ast.Node, reader text.Reader) (string, []ast.Node) { + if firstParagraph.ChildCount() < 2 { + return "", nil } node1, ok := firstParagraph.FirstChild().(*ast.Text) if !ok { - return ast.WalkContinue, nil + return "", nil } node2, ok := node1.NextSibling().(*ast.Text) if !ok { - return ast.WalkContinue, nil + return "", nil + } + val1 := string(node1.Segment.Value(reader.Source())) + val2 := string(node2.Segment.Value(reader.Source())) + if strings.HasPrefix(val1, `\[!`) && val2 == `\]` { + attentionType := strings.ToLower(val1[3:]) + if g.attentionTypes.Contains(attentionType) { + return attentionType, []ast.Node{node1, node2} + } + } + return "", nil +} + +func (g *ASTTransformer) extractBlockquoteAttention3(firstParagraph ast.Node, reader text.Reader) (string, []ast.Node) { + if firstParagraph.ChildCount() < 3 { + return "", nil + } + node1, ok := firstParagraph.FirstChild().(*ast.Text) + if !ok { + return "", nil + } + node2, ok := node1.NextSibling().(*ast.Text) + if !ok { + return "", nil } node3, ok := node2.NextSibling().(*ast.Text) if !ok { - return ast.WalkContinue, nil + return "", nil } val1 := string(node1.Segment.Value(reader.Source())) val2 := string(node2.Segment.Value(reader.Source())) val3 := string(node3.Segment.Value(reader.Source())) if val1 != "[" || val3 != "]" || !strings.HasPrefix(val2, "!") { - return ast.WalkContinue, nil + return "", nil } - // grab attention type from markdown source attentionType := strings.ToLower(val2[1:]) - if !g.attentionTypes.Contains(attentionType) { + if g.attentionTypes.Contains(attentionType) { + return attentionType, []ast.Node{node1, node2, node3} + } + return "", nil +} + +func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Reader) (ast.WalkStatus, error) { + // We only want attention blockquotes when the AST looks like: + // > Text("[") Text("!TYPE") Text("]") + // > Text("\[!TYPE") TEXT("\]") + // > Text("**TYPE**") + + // grab these nodes and make sure we adhere to the attention blockquote structure + firstParagraph := v.FirstChild() + g.applyElementDir(firstParagraph) + + attentionType, processedNodes := g.extractBlockquoteAttentionEmphasis(firstParagraph, reader) + if attentionType == "" { + attentionType, processedNodes = g.extractBlockquoteAttention2(firstParagraph, reader) + } + if attentionType == "" { + attentionType, processedNodes = g.extractBlockquoteAttention3(firstParagraph, reader) + } + if attentionType == "" { return ast.WalkContinue, nil } @@ -88,9 +143,9 @@ func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Read attentionParagraph.AppendChild(attentionParagraph, NewAttention(attentionType)) attentionParagraph.AppendChild(attentionParagraph, emphasis) firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph) - firstParagraph.RemoveChild(firstParagraph, node1) - firstParagraph.RemoveChild(firstParagraph, node2) - firstParagraph.RemoveChild(firstParagraph, node3) + for _, processed := range processedNodes { + firstParagraph.RemoveChild(firstParagraph, processed) + } if firstParagraph.ChildCount() == 0 { firstParagraph.Parent().RemoveChild(firstParagraph.Parent(), firstParagraph) } From 816222243af523316041692622be6f48ef068693 Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 5 Jun 2024 03:22:38 +0200 Subject: [PATCH 24/46] Add `lint-go-gopls` (#30729) Uses `gopls check ` as a linter. Tested locally and brings up 149 errors currently for me. I don't think I want to fix them in this PR, but I would like at least to get this analysis running on CI. List of errors: ``` modules/indexer/code/indexer.go:181:11: impossible condition: nil != nil routers/private/hook_post_receive.go:120:15: tautological condition: nil == nil services/auth/source/oauth2/providers.go:185:9: tautological condition: nil == nil services/convert/issue.go:216:11: tautological condition: non-nil != nil tests/integration/git_test.go:332:9: impossible condition: nil != nil services/migrations/migrate.go:179:24-43: unused parameter: ctx services/repository/transfer.go:288:48-69: unused parameter: doer tests/integration/api_repo_tags_test.go:75:41-61: unused parameter: session tests/integration/git_test.go:696:64-74: unused parameter: baseBranch tests/integration/gpg_git_test.go:265:27-39: unused parameter: t tests/integration/gpg_git_test.go:284:23-29: unused parameter: tmpDir tests/integration/gpg_git_test.go:284:31-35: unused parameter: name tests/integration/gpg_git_test.go:284:37-42: unused parameter: email ``` --- Makefile | 10 +++++++++- services/migrations/migrate.go | 2 +- services/repository/transfer.go | 4 ++-- tests/integration/api_repo_tags_test.go | 4 ++-- tests/integration/dump_restore_test.go | 2 +- tests/integration/gpg_git_test.go | 6 +++--- tools/lint-go-gopls.sh | 23 +++++++++++++++++++++++ 7 files changed, 41 insertions(+), 10 deletions(-) create mode 100755 tools/lint-go-gopls.sh diff --git a/Makefile b/Makefile index e9dc945206..d97360c9f4 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1 GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1 +GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.15.3 DOCKER_IMAGE ?= gitea/gitea DOCKER_TAG ?= latest @@ -213,6 +214,7 @@ help: @echo " - lint-go lint go files" @echo " - lint-go-fix lint go files and fix issues" @echo " - lint-go-vet lint go files with vet" + @echo " - lint-go-gopls lint go files with gopls" @echo " - lint-js lint js files" @echo " - lint-js-fix lint js files and fix issues" @echo " - lint-css lint css files" @@ -366,7 +368,7 @@ lint-frontend: lint-js lint-css lint-frontend-fix: lint-js-fix lint-css-fix .PHONY: lint-backend -lint-backend: lint-go lint-go-vet lint-editorconfig +lint-backend: lint-go lint-go-vet lint-go-gopls lint-editorconfig .PHONY: lint-backend-fix lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig @@ -424,6 +426,11 @@ lint-go-vet: @GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet @$(GO) vet -vettool=gitea-vet ./... +.PHONY: lint-go-gopls +lint-go-gopls: + @echo "Running gopls check..." + @GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA) + .PHONY: lint-editorconfig lint-editorconfig: @$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) $(EDITORCONFIG_FILES) @@ -864,6 +871,7 @@ deps-tools: $(GO) install $(GO_LICENSES_PACKAGE) $(GO) install $(GOVULNCHECK_PACKAGE) $(GO) install $(ACTIONLINT_PACKAGE) + $(GO) install $(GOPLS_PACKAGE) node_modules: package-lock.json npm install --no-save diff --git a/services/migrations/migrate.go b/services/migrations/migrate.go index 5bb3056161..21bdc68e73 100644 --- a/services/migrations/migrate.go +++ b/services/migrations/migrate.go @@ -176,7 +176,7 @@ func newDownloader(ctx context.Context, ownerName string, opts base.MigrateOptio // migrateRepository will download information and then upload it to Uploader, this is a simple // process for small repository. For a big repository, save all the data to disk // before upload is better -func migrateRepository(ctx context.Context, doer *user_model.User, downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions, messenger base.Messenger) error { +func migrateRepository(_ context.Context, doer *user_model.User, downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions, messenger base.Messenger) error { if messenger == nil { messenger = base.NilMessenger } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 3d0bce18d0..9e0ff7ae14 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -285,7 +285,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName } // changeRepositoryName changes all corresponding setting from old repository name to new one. -func changeRepositoryName(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, newRepoName string) (err error) { +func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newRepoName string) (err error) { oldRepoName := repo.Name newRepoName = strings.ToLower(newRepoName) if err = repo_model.IsUsableRepoName(newRepoName); err != nil { @@ -347,7 +347,7 @@ func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *repo // local copy's origin accordingly. repoWorkingPool.CheckIn(fmt.Sprint(repo.ID)) - if err := changeRepositoryName(ctx, doer, repo, newRepoName); err != nil { + if err := changeRepositoryName(ctx, repo, newRepoName); err != nil { repoWorkingPool.CheckOut(fmt.Sprint(repo.ID)) return err } diff --git a/tests/integration/api_repo_tags_test.go b/tests/integration/api_repo_tags_test.go index c6eeb404c0..a7f021ca4f 100644 --- a/tests/integration/api_repo_tags_test.go +++ b/tests/integration/api_repo_tags_test.go @@ -42,7 +42,7 @@ func TestAPIRepoTags(t *testing.T) { assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.zip", tags[0].ZipballURL) assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.tar.gz", tags[0].TarballURL) - newTag := createNewTagUsingAPI(t, session, token, user.Name, repoName, "gitea/22", "", "nice!\nand some text") + newTag := createNewTagUsingAPI(t, token, user.Name, repoName, "gitea/22", "", "nice!\nand some text") resp = MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &tags) assert.Len(t, tags, 2) @@ -72,7 +72,7 @@ func TestAPIRepoTags(t *testing.T) { MakeRequest(t, req, http.StatusNotFound) } -func createNewTagUsingAPI(t *testing.T, session *TestSession, token, ownerName, repoName, name, target, msg string) *api.Tag { +func createNewTagUsingAPI(t *testing.T, token, ownerName, repoName, name, target, msg string) *api.Tag { urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/tags", ownerName, repoName) req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateTagOption{ TagName: name, diff --git a/tests/integration/dump_restore_test.go b/tests/integration/dump_restore_test.go index bed2453054..47bb6f76e9 100644 --- a/tests/integration/dump_restore_test.go +++ b/tests/integration/dump_restore_test.go @@ -237,7 +237,7 @@ func (c *compareDump) assertLoadFiles(beforeFilename, afterFilename string, t re // // Given []Something{} create afterPtr, beforePtr []*Something{} // - sliceType := reflect.SliceOf(reflect.PtrTo(t.Elem())) + sliceType := reflect.SliceOf(reflect.PointerTo(t.Elem())) beforeSlice := reflect.MakeSlice(sliceType, 0, 10) beforePtr = reflect.New(beforeSlice.Type()) beforePtr.Elem().Set(beforeSlice) diff --git a/tests/integration/gpg_git_test.go b/tests/integration/gpg_git_test.go index 3ba4a5882c..047c049c7f 100644 --- a/tests/integration/gpg_git_test.go +++ b/tests/integration/gpg_git_test.go @@ -35,7 +35,7 @@ func TestGPGGit(t *testing.T) { defer os.Setenv("GNUPGHOME", oldGNUPGHome) // Need to create a root key - rootKeyPair, err := importTestingKey(tmpDir, "gitea", "gitea@fake.local") + rootKeyPair, err := importTestingKey() if !assert.NoError(t, err, "importTestingKey") { return } @@ -262,7 +262,7 @@ func TestGPGGit(t *testing.T) { }) } -func crudActionCreateFile(t *testing.T, ctx APITestContext, user *user_model.User, from, to, path string, callback ...func(*testing.T, api.FileResponse)) func(*testing.T) { +func crudActionCreateFile(_ *testing.T, ctx APITestContext, user *user_model.User, from, to, path string, callback ...func(*testing.T, api.FileResponse)) func(*testing.T) { return doAPICreateFile(ctx, path, &api.CreateFileOptions{ FileOptions: api.FileOptions{ BranchName: from, @@ -281,7 +281,7 @@ func crudActionCreateFile(t *testing.T, ctx APITestContext, user *user_model.Use }, callback...) } -func importTestingKey(tmpDir, name, email string) (*openpgp.Entity, error) { +func importTestingKey() (*openpgp.Entity, error) { if _, _, err := process.GetManager().Exec("gpg --import tests/integration/private-testing.key", "gpg", "--import", "tests/integration/private-testing.key"); err != nil { return nil, err } diff --git a/tools/lint-go-gopls.sh b/tools/lint-go-gopls.sh new file mode 100755 index 0000000000..4bb69f4c16 --- /dev/null +++ b/tools/lint-go-gopls.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -uo pipefail + +cd "$(dirname -- "${BASH_SOURCE[0]}")" && cd .. + +IGNORE_PATTERNS=( + "is deprecated" # TODO: fix these +) + +# lint all go files with 'gopls check' and look for lines starting with the +# current absolute path, indicating a error was found. This is neccessary +# because the tool does not set non-zero exit code when errors are found. +# ref: https://github.com/golang/go/issues/67078 +ERROR_LINES=$("$GO" run "$GOPLS_PACKAGE" check "$@" 2>/dev/null | grep -E "^$PWD" | grep -vFf <(printf '%s\n' "${IGNORE_PATTERNS[@]}")); +NUM_ERRORS=$(echo -n "$ERROR_LINES" | wc -l) + +if [ "$NUM_ERRORS" -eq "0" ]; then + exit 0; +else + echo "$ERROR_LINES" + echo "Found $NUM_ERRORS 'gopls check' errors" + exit 1; +fi From 8de8972baf5d82ff7b58ed77d78e8e1869e64eb5 Mon Sep 17 00:00:00 2001 From: Rowan Bohde Date: Tue, 4 Jun 2024 23:00:56 -0500 Subject: [PATCH 25/46] fix: allow actions artifacts storage migration to complete succesfully (#31251) Change the copy to use `ActionsArtifact.StoragePath` instead of the `ArtifactPath`. Skip artifacts that are expired, and don't error if the file to copy does not exist. --- When trying to migrate actions artifact storage from local to MinIO, we encountered errors that prevented the process from completing successfully: * The migration tries to copy the files using the per-run `ArtifactPath`, instead of the unique `StoragePath`. * Artifacts that have been marked expired and had their files deleted would throw an error * Artifacts that are pending, but don't have a file uploaded yet will throw an error. This PR addresses these cases, and allow the process to complete successfully. --- cmd/migrate_storage.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/migrate_storage.go b/cmd/migrate_storage.go index 1720b6fb53..6ece4bf661 100644 --- a/cmd/migrate_storage.go +++ b/cmd/migrate_storage.go @@ -5,7 +5,9 @@ package cmd import ( "context" + "errors" "fmt" + "io/fs" "strings" actions_model "code.gitea.io/gitea/models/actions" @@ -194,8 +196,20 @@ func migrateActionsLog(ctx context.Context, dstStorage storage.ObjectStorage) er func migrateActionsArtifacts(ctx context.Context, dstStorage storage.ObjectStorage) error { return db.Iterate(ctx, nil, func(ctx context.Context, artifact *actions_model.ActionArtifact) error { - _, err := storage.Copy(dstStorage, artifact.ArtifactPath, storage.ActionsArtifacts, artifact.ArtifactPath) - return err + if artifact.Status == int64(actions_model.ArtifactStatusExpired) { + return nil + } + + _, err := storage.Copy(dstStorage, artifact.StoragePath, storage.ActionsArtifacts, artifact.StoragePath) + if err != nil { + // ignore files that do not exist + if errors.Is(err, fs.ErrNotExist) { + return nil + } + return err + } + + return nil }) } From 06ebae7472aef4380602d2ecd64fdc9dddcb6037 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Wed, 5 Jun 2024 22:39:45 +0800 Subject: [PATCH 26/46] Optimize runner-tags layout to enhance visual experience (#31258) ![image](https://github.com/go-gitea/gitea/assets/3371163/b8199005-94f2-45be-8ca9-4fa1b3f221b2) --- templates/shared/actions/runner_list.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/shared/actions/runner_list.tmpl b/templates/shared/actions/runner_list.tmpl index 8163007993..d3a86fe3fa 100644 --- a/templates/shared/actions/runner_list.tmpl +++ b/templates/shared/actions/runner_list.tmpl @@ -70,7 +70,7 @@

{{.Name}}

{{if .Version}}{{.Version}}{{else}}{{ctx.Locale.Tr "unknown"}}{{end}} {{.BelongsToOwnerType.LocaleString ctx.Locale}} + {{range .AgentLabels}}{{.}}{{end}} {{if .LastOnline}}{{TimeSinceUnix .LastOnline ctx.Locale}}{{else}}{{ctx.Locale.Tr "never"}}{{end}}
`); err != nil { return err } - row := 1 + + row := 0 for { fields, err := rd.Read() - if err == io.EOF { + if err == io.EOF || (row >= maxRows && maxRows != 0) { break } if err != nil { continue } + if _, err := tmpBlock.WriteString(""); err != nil { return err } element := "td" - if row == 1 { + if row == 0 { element = "th" } - if err := writeField(tmpBlock, element, "line-num", strconv.Itoa(row)); err != nil { + if err := writeField(tmpBlock, element, "line-num", strconv.Itoa(row+1)); err != nil { return err } for _, field := range fields { @@ -174,8 +126,32 @@ func (Renderer) tableRender(ctx *markup.RenderContext, input io.Reader, tmpBlock row++ } + if _, err = tmpBlock.WriteString("
"); err != nil { return err } + + // Check if maxRows or maxSize is reached, and if true, warn. + if (row >= maxRows && maxRows != 0) || (rd.InputOffset() >= maxSize && maxSize != 0) { + warn := `
` + rawLink := ` ` + + // Try to get the user translation + if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok { + warn += locale.TrString("repo.file_too_large") + rawLink += locale.TrString("repo.file_view_raw") + } else { + warn += "The file is too large to be shown." + rawLink += "View Raw" + } + + warn += rawLink + `
` + + // Write the HTML string to the output + if _, err := tmpBlock.WriteString(warn); err != nil { + return err + } + } + return tmpBlock.Flush() } diff --git a/modules/markup/csv/csv_test.go b/modules/markup/csv/csv_test.go index 3d12be477c..8c07184b21 100644 --- a/modules/markup/csv/csv_test.go +++ b/modules/markup/csv/csv_test.go @@ -4,8 +4,6 @@ package markup import ( - "bufio" - "bytes" "strings" "testing" @@ -31,12 +29,4 @@ func TestRenderCSV(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, v, buf.String()) } - - t.Run("fallbackRender", func(t *testing.T) { - var buf bytes.Buffer - err := render.fallbackRender(strings.NewReader("1,\n2,"), bufio.NewWriter(&buf)) - assert.NoError(t, err) - want := "
1,<a>\n2,<b>
" - assert.Equal(t, want, buf.String()) - }) } diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 93855bca07..a8dc11d097 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -52,6 +52,7 @@ var UI = struct { CSV struct { MaxFileSize int64 + MaxRows int } `ini:"ui.csv"` Admin struct { @@ -107,8 +108,10 @@ var UI = struct { }, CSV: struct { MaxFileSize int64 + MaxRows int }{ MaxFileSize: 524288, + MaxRows: 2500, }, Admin: struct { UserPagingNum int From da4bbc42477ba04d175cc0775a0c5ec90c4c24fe Mon Sep 17 00:00:00 2001 From: Max Wipfli Date: Thu, 6 Jun 2024 10:35:04 +0200 Subject: [PATCH 31/46] Allow including `Reviewed-on`/`Reviewed-by` lines for custom merge messages (#31211) This PR introduces the `ReviewedOn` and `ReviewedBy` variables for the default merge message templates (e.g., `.gitea/default_merge_message/MERGE_TEMPLATE.md`). This allows customizing the default merge messages while retaining these trailers. This also moves the associated logic out of `pull.tmpl` into the relevant Go function. This is a first contribution towards #11077. --- For illustration, this allows to recreate the "default default" merge message with the following template: ``` .gitea/default_merge_message/MERGE_TEMPLATE.md Merge pull request '${PullRequestTitle}' (${PullRequestReference}) from ${HeadBranch} into ${BaseBranch} ${ReviewedOn} ${ReviewedBy} ``` --- .../usage/merge-message-templates.en-us.md | 2 ++ services/pull/merge.go | 18 ++++++++++++++---- templates/repo/issue/view_content/pull.tmpl | 6 ++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/content/usage/merge-message-templates.en-us.md b/docs/content/usage/merge-message-templates.en-us.md index fbdbd136f8..5116be3387 100644 --- a/docs/content/usage/merge-message-templates.en-us.md +++ b/docs/content/usage/merge-message-templates.en-us.md @@ -44,6 +44,8 @@ You can use the following variables enclosed in `${}` inside these templates whi - PullRequestIndex: Pull request's index number - PullRequestReference: Pull request's reference char with index number. i.e. #1, !2 - ClosingIssues: return a string contains all issues which will be closed by this pull request i.e. `close #1, close #2` +- ReviewedOn: Which pull request this commit belongs to. For example `Reviewed-on: https://gitea.com/foo/bar/pulls/1` +- ReviewedBy: Who approved the pull request before the merge. For example `Reviewed-by: Jane Doe ` ## Rebase diff --git a/services/pull/merge.go b/services/pull/merge.go index 20be7c5b5a..6b5e9ea330 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -46,6 +46,9 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue if err := pr.Issue.LoadPoster(ctx); err != nil { return "", "", err } + if err := pr.Issue.LoadRepo(ctx); err != nil { + return "", "", err + } isExternalTracker := pr.BaseRepo.UnitEnabled(ctx, unit.TypeExternalTracker) issueReference := "#" @@ -53,6 +56,9 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue issueReference = "!" } + reviewedOn := fmt.Sprintf("Reviewed-on: %s/%s", setting.AppURL, pr.Issue.Link()) + reviewedBy := pr.GetApprovers(ctx) + if mergeStyle != "" { templateFilepath := fmt.Sprintf(".gitea/default_merge_message/%s_TEMPLATE.md", strings.ToUpper(string(mergeStyle))) commit, err := baseGitRepo.GetBranchCommit(pr.BaseRepo.DefaultBranch) @@ -77,6 +83,8 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue "PullRequestPosterName": pr.Issue.Poster.Name, "PullRequestIndex": strconv.FormatInt(pr.Index, 10), "PullRequestReference": fmt.Sprintf("%s%d", issueReference, pr.Index), + "ReviewedOn": reviewedOn, + "ReviewedBy": reviewedBy, } if pr.HeadRepo != nil { vars["HeadRepoOwnerName"] = pr.HeadRepo.OwnerName @@ -116,20 +124,22 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue return "", "", nil } + body = fmt.Sprintf("%s\n%s", reviewedOn, reviewedBy) + // Squash merge has a different from other styles. if mergeStyle == repo_model.MergeStyleSquash { - return fmt.Sprintf("%s (%s%d)", pr.Issue.Title, issueReference, pr.Issue.Index), "", nil + return fmt.Sprintf("%s (%s%d)", pr.Issue.Title, issueReference, pr.Issue.Index), body, nil } if pr.BaseRepoID == pr.HeadRepoID { - return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), "", nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), body, nil } if pr.HeadRepo == nil { - return fmt.Sprintf("Merge pull request '%s' (%s%d) from :%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), "", nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from :%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), body, nil } - return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch), "", nil + return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch), body, nil } func expandDefaultMergeMessage(template string, vars map[string]string) (message, body string) { diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index 77378ef1bd..69e74da3a0 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -199,7 +199,6 @@ {{if .AllowMerge}} {{/* user is allowed to merge */}} {{$prUnit := .Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypePullRequests}} - {{$approvers := (.Issue.PullRequest.GetApprovers ctx)}} {{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowRebaseMerge $prUnit.PullRequestsConfig.AllowSquash $prUnit.PullRequestsConfig.AllowFastForwardOnly}} {{$hasPendingPullRequestMergeTip := ""}} {{if .HasPendingPullRequestMerge}} @@ -208,11 +207,10 @@ {{end}}