From 60c78658ef2dd3f63c8dab068d0326b2e11a9dc7 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 28 Apr 2024 16:27:14 +0200 Subject: [PATCH 01/99] add built js files to eslint ignore (#30737) For the rare case that some overzealous tooling wants to lint our output files. (cherry picked from commit d89bf3d3ec933c11f4ee7e4e714804d5815afa75) --- .eslintrc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 91019cde84..e553499691 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -4,6 +4,7 @@ reportUnusedDisableDirectives: true ignorePatterns: - /web_src/js/vendor - /web_src/fomantic + - /public/assets/js parserOptions: sourceType: module From 6a4dfc5ba4559652e1dae5500ad1d3c873066c1d Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 29 Apr 2024 00:25:01 +0000 Subject: [PATCH 02/99] [skip ci] Updated licenses and gitignores (cherry picked from commit e67141756d058045cf64a441255a2042425eda3b) --- options/license/Catharon | 121 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 options/license/Catharon diff --git a/options/license/Catharon b/options/license/Catharon new file mode 100644 index 0000000000..8d0ac128bc --- /dev/null +++ b/options/license/Catharon @@ -0,0 +1,121 @@ + The Catharon Open Source LICENSE + ---------------------------- + + 2000-Jul-04 + + Copyright (C) 2000 by Catharon Productions, Inc. + + + +Introduction +============ + + This license applies to source files distributed by Catharon + Productions, Inc. in several archive packages. This license + applies to all files found in such packages which do not fall + under their own explicit license. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + Catharon Code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering the packages distributed by + Catharon Productions, Inc. and assume no liability related to + their use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `Catharon Package', `package', + and `Catharon Code' refer to the set of files originally + distributed by Catharon Productions, Inc. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using one of the + Catharon Packages'. + + This license applies to all files distributed in the original + Catharon Package(s), including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The Catharon Packages are copyright (C) 2000 by Catharon + Productions, Inc. All rights reserved except as specified below. + +1. No Warranty +-------------- + + THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO + USE THE CATHARON PACKAGE. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the Catharon Packages (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`license.txt') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part on the work of + Catharon Productions, Inc. in the distribution documentation. + + These conditions apply to any software derived from or based on + the Catharon Packages, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither Catharon Productions, Inc. and contributors nor you shall + use the name of the other for commercial, advertising, or + promotional purposes without specific prior written permission. + + We suggest, but do not require, that you use the following phrase + to refer to this software in your documentation: 'this software is + based in part on the Catharon Typography Project'. + + As you have not signed this license, you are not required to + accept it. However, as the Catharon Packages are copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the Catharon + Packages, you indicate that you understand and accept all the + terms of this license. From 96fd8008cdfe0bccc094292963244ede8edf6de7 Mon Sep 17 00:00:00 2001 From: Sergey Zolotarev <4525736+sryze@users.noreply.github.com> Date: Mon, 29 Apr 2024 09:45:53 +0600 Subject: [PATCH 03/99] Fix cross-compilation errors when CGO_CFLAGS/CGO_LDFLAGS is set (#30749) When you cross-compile Gitea and you specify one of the envrionment variables related to C flags, cgo will fail to build the generator programs (e.g. generate-bindata) because GOOS and GOARCH are unset, but those additional flags variables are not unset together with those. To solve this issue, the simplest way that I've found is to disable cgo in the `go generate` command as it's not really used there. For example, I've had this problem with cross-compiling Gitea on FreeBSD x86_64 to ARMv7 where it's necessary to pass `--target` to `clang` via `CGO_CFLAGS`: ``` GOOS=freebsd \ GOARCH=arm \ GGOARM=7 \ CGO_ENABLED=1 \ SYSROOT=/usr/local/freebsd-sysroot/armv7 \ CC=clang \ CGO_CFLAGS="--target=armv7-unknown-freebsd13.2-gnueabihf" \ TAGS="bindata sqlite sqlite_unlock_notify" \ make SHELL='sh -x' build ``` ``` Running go generate... # runtime/cgo In file included from gcc_freebsd_amd64.c:9: In file included from /usr/include/signal.h:42: /usr/include/sys/_ucontext.h:44:2: error: unknown type name 'mcontext_t' modules/migration/schemas_bindata.go:8: running "go": exit status 1 # runtime/cgo In file included from gcc_freebsd_amd64.c:9: In file included from /usr/include/signal.h:42: /usr/include/sys/_ucontext.h:44:2: error: unknown type name 'mcontext_t' modules/options/options_bindata.go:8: running "go": exit status 1 # runtime/cgo In file included from gcc_freebsd_amd64.c:9: In file included from /usr/include/signal.h:42: /usr/include/sys/_ucontext.h:44:2: error: unknown type name 'mcontext_t' modules/public/public_bindata.go:8: running "go": exit status 1 # runtime/cgo In file included from gcc_freebsd_amd64.c:9: In file included from /usr/include/signal.h:42: /usr/include/sys/_ucontext.h:44:2: error: unknown type name 'mcontext_t' modules/templates/templates_bindata.go:8: running "go": exit status 1 gmake[1]: *** [Makefile:781: generate-go] Error 1 *** Error code 2 Stop. ``` But with this fix Gitea compiles successfully. (cherry picked from commit d11133b83652238023b52576e0d3e57a4f4b21c9) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d4e3e0703..49609e437c 100644 --- a/Makefile +++ b/Makefile @@ -767,7 +767,7 @@ generate-backend: $(TAGS_PREREQ) generate-go .PHONY: generate-go generate-go: $(TAGS_PREREQ) @echo "Running go generate..." - @CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' ./... + @CC= GOOS= GOARCH= CGO_ENABLED=0 $(GO) generate -tags '$(TAGS)' ./... .PHONY: merge-locales merge-locales: From b8e7b3941a462c177bd547317b9b1d30758b8fc1 Mon Sep 17 00:00:00 2001 From: Micash <70768913+micash545@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:19:06 +0200 Subject: [PATCH 04/99] Add support for npm bundleDependencies (#30751) (cherry picked from commit ad4e902d5a1430c0c1df18bf404537df5ded1dba) --- modules/packages/npm/creator.go | 2 ++ modules/packages/npm/metadata.go | 1 + options/locale/locale_en-US.ini | 1 + routers/api/packages/npm/api.go | 1 + templates/package/content/npm.tmpl | 9 +++++++++ 5 files changed, 14 insertions(+) diff --git a/modules/packages/npm/creator.go b/modules/packages/npm/creator.go index 9e636757af..7d3d7cd6b5 100644 --- a/modules/packages/npm/creator.go +++ b/modules/packages/npm/creator.go @@ -78,6 +78,7 @@ type PackageMetadataVersion struct { Repository Repository `json:"repository,omitempty"` Keywords []string `json:"keywords,omitempty"` Dependencies map[string]string `json:"dependencies,omitempty"` + BundleDependencies []string `json:"bundleDependencies,omitempty"` DevDependencies map[string]string `json:"devDependencies,omitempty"` PeerDependencies map[string]string `json:"peerDependencies,omitempty"` Bin map[string]string `json:"bin,omitempty"` @@ -218,6 +219,7 @@ func ParsePackage(r io.Reader) (*Package, error) { ProjectURL: meta.Homepage, Keywords: meta.Keywords, Dependencies: meta.Dependencies, + BundleDependencies: meta.BundleDependencies, DevelopmentDependencies: meta.DevDependencies, PeerDependencies: meta.PeerDependencies, OptionalDependencies: meta.OptionalDependencies, diff --git a/modules/packages/npm/metadata.go b/modules/packages/npm/metadata.go index 77b77472a7..6bb77f302b 100644 --- a/modules/packages/npm/metadata.go +++ b/modules/packages/npm/metadata.go @@ -16,6 +16,7 @@ type Metadata struct { ProjectURL string `json:"project_url,omitempty"` Keywords []string `json:"keywords,omitempty"` Dependencies map[string]string `json:"dependencies,omitempty"` + BundleDependencies []string `json:"bundleDependencies,omitempty"` DevelopmentDependencies map[string]string `json:"development_dependencies,omitempty"` PeerDependencies map[string]string `json:"peer_dependencies,omitempty"` OptionalDependencies map[string]string `json:"optional_dependencies,omitempty"` diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9148d57a27..690bf1eddd 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3573,6 +3573,7 @@ npm.install = To install the package using npm, run the following command: npm.install2 = or add it to the package.json file: npm.dependencies = Dependencies npm.dependencies.development = Development Dependencies +npm.dependencies.bundle = Bundled Dependencies npm.dependencies.peer = Peer Dependencies npm.dependencies.optional = Optional Dependencies npm.details.tag = Tag diff --git a/routers/api/packages/npm/api.go b/routers/api/packages/npm/api.go index f8e839c424..b4379f3f49 100644 --- a/routers/api/packages/npm/api.go +++ b/routers/api/packages/npm/api.go @@ -64,6 +64,7 @@ func createPackageMetadataVersion(registryURL string, pd *packages_model.Package Homepage: metadata.ProjectURL, License: metadata.License, Dependencies: metadata.Dependencies, + BundleDependencies: metadata.BundleDependencies, DevDependencies: metadata.DevelopmentDependencies, PeerDependencies: metadata.PeerDependencies, OptionalDependencies: metadata.OptionalDependencies, diff --git a/templates/package/content/npm.tmpl b/templates/package/content/npm.tmpl index c5d9b3f428..1ffbd199e3 100644 --- a/templates/package/content/npm.tmpl +++ b/templates/package/content/npm.tmpl @@ -45,6 +45,15 @@ {{end}} + {{if .PackageDescriptor.Metadata.BundleDependencies}} +

{{ctx.Locale.Tr "packages.npm.dependencies.bundle"}}

+
+ {{range .PackageDescriptor.Metadata.BundleDependencies}} + {{.}} + {{end}} +
+ {{end}} + {{if .PackageDescriptor.Metadata.Keywords}}

{{ctx.Locale.Tr "packages.keywords"}}

From c504461b66fb36aa6ed758d6c967c3296560644d Mon Sep 17 00:00:00 2001 From: Chongyi Zheng Date: Mon, 29 Apr 2024 04:47:56 -0400 Subject: [PATCH 05/99] Resolve lint for unused parameter and unnecessary type arguments (#30750) Resolve all cases for `unused parameter` and `unnecessary type arguments` Related: #30729 --------- Co-authored-by: Giteabot (cherry picked from commit e80466f7349164ce4cf3c07bdac30d736d20f035) Conflicts: modules/markup/markdown/transform_codespan.go modules/setting/incoming_email.go routers/api/v1/admin/user_badge.go routers/private/hook_pre_receive.go tests/integration/repo_search_test.go resolved by discarding the change, this is linting only and for the sake of avoiding future conflicts --- models/issues/issue_xref_test.go | 12 +++++----- models/organization/org_test.go | 6 ++--- modules/actions/workflows.go | 24 ++++++++++---------- modules/git/commit_info_nogogit.go | 4 ++-- modules/git/parse_gogit.go | 2 +- modules/git/parse_gogit_test.go | 2 +- modules/git/parse_nogogit.go | 6 ++--- modules/git/parse_nogogit_test.go | 10 +++----- modules/git/tree_nogogit.go | 14 ++++-------- modules/indexer/code/git.go | 12 ++++------ modules/markup/markdown/goldmark.go | 6 ++--- modules/markup/markdown/transform_heading.go | 2 +- modules/markup/markdown/transform_image.go | 3 +-- modules/markup/markdown/transform_link.go | 3 +-- modules/markup/markdown/transform_list.go | 3 +-- modules/markup/mdstripper/mdstripper.go | 4 ++-- modules/optional/option_test.go | 2 +- modules/setting/incoming_email.go | 4 ++-- modules/setting/storage.go | 4 ++-- routers/api/v1/repo/migrate.go | 6 ++--- routers/web/admin/admin.go | 2 +- routers/web/feed/convert.go | 2 +- routers/web/feed/release.go | 2 +- services/context/repo.go | 8 +++---- services/doctor/storage.go | 14 ++++++------ services/migrations/gitea_uploader.go | 15 ++++++------ services/mirror/mirror.go | 2 +- services/pull/review.go | 4 ++-- services/pull/update.go | 2 +- services/pull/update_rebase.go | 2 +- services/repository/adopt.go | 4 ++-- services/repository/branch.go | 6 ++--- services/repository/files/update.go | 4 ++-- services/user/update_test.go | 2 +- tests/integration/api_packages_chef_test.go | 4 ++-- tests/integration/api_releases_test.go | 14 ++++++------ tests/integration/api_repo_git_tags_test.go | 2 +- tests/integration/pull_create_test.go | 4 +--- tests/integration/repo_badges_test.go | 2 +- tests/integration/repo_branch_test.go | 6 ++--- tests/integration/repofiles_change_test.go | 6 ++--- 41 files changed, 107 insertions(+), 129 deletions(-) diff --git a/models/issues/issue_xref_test.go b/models/issues/issue_xref_test.go index 5bcaf75518..f1b1bb2a6b 100644 --- a/models/issues/issue_xref_test.go +++ b/models/issues/issue_xref_test.go @@ -34,7 +34,7 @@ func TestXRef_AddCrossReferences(t *testing.T) { // Comment on PR to reopen issue #1 content = fmt.Sprintf("content2, reopens #%d", itarget.Index) - c := testCreateComment(t, 1, 2, pr.ID, content) + c := testCreateComment(t, 2, pr.ID, content) ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: pr.ID, RefCommentID: c.ID}) assert.Equal(t, issues_model.CommentTypeCommentRef, ref.Type) assert.Equal(t, pr.RepoID, ref.RefRepoID) @@ -104,18 +104,18 @@ func TestXRef_ResolveCrossReferences(t *testing.T) { pr := testCreatePR(t, 1, 2, "titlepr", fmt.Sprintf("closes #%d", i1.Index)) rp := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i1.ID, RefIssueID: pr.Issue.ID, RefCommentID: 0}) - c1 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i2.Index)) + c1 := testCreateComment(t, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i2.Index)) r1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i2.ID, RefIssueID: pr.Issue.ID, RefCommentID: c1.ID}) // Must be ignored - c2 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("mentions #%d", i2.Index)) + c2 := testCreateComment(t, 2, pr.Issue.ID, fmt.Sprintf("mentions #%d", i2.Index)) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i2.ID, RefIssueID: pr.Issue.ID, RefCommentID: c2.ID}) // Must be superseded by c4/r4 - c3 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("reopens #%d", i3.Index)) + c3 := testCreateComment(t, 2, pr.Issue.ID, fmt.Sprintf("reopens #%d", i3.Index)) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i3.ID, RefIssueID: pr.Issue.ID, RefCommentID: c3.ID}) - c4 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i3.Index)) + c4 := testCreateComment(t, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i3.Index)) r4 := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i3.ID, RefIssueID: pr.Issue.ID, RefCommentID: c4.ID}) refs, err := pr.ResolveCrossReferences(db.DefaultContext) @@ -168,7 +168,7 @@ func testCreatePR(t *testing.T, repo, doer int64, title, content string) *issues return pr } -func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *issues_model.Comment { +func testCreateComment(t *testing.T, doer, issue int64, content string) *issues_model.Comment { d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue}) c := &issues_model.Comment{Type: issues_model.CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content} diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 5e40dd4190..23ef22e2fb 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -291,15 +291,15 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) { func TestAccessibleReposEnv_RepoIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - testSuccess := func(userID, _, pageSize int64, expectedRepoIDs []int64) { + testSuccess := func(userID int64, expectedRepoIDs []int64) { env, err := organization.AccessibleReposEnv(db.DefaultContext, org, userID) assert.NoError(t, err) repoIDs, err := env.RepoIDs(1, 100) assert.NoError(t, err) assert.Equal(t, expectedRepoIDs, repoIDs) } - testSuccess(2, 1, 100, []int64{3, 5, 32}) - testSuccess(4, 0, 100, []int64{3, 32}) + testSuccess(2, []int64{3, 5, 32}) + testSuccess(4, []int64{3, 32}) } func TestAccessibleReposEnv_Repos(t *testing.T) { diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index c103aa1928..8677e1fd55 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -211,14 +211,14 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web webhook_module.HookEventIssueAssign, webhook_module.HookEventIssueLabel, webhook_module.HookEventIssueMilestone: - return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt) + return matchIssuesEvent(payload.(*api.IssuePayload), evt) case // issue_comment webhook_module.HookEventIssueComment, // `pull_request_comment` is same as `issue_comment` // See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment webhook_module.HookEventPullRequestComment: - return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt) + return matchIssueCommentEvent(payload.(*api.IssueCommentPayload), evt) case // pull_request webhook_module.HookEventPullRequest, @@ -232,19 +232,19 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web case // pull_request_review webhook_module.HookEventPullRequestReviewApproved, webhook_module.HookEventPullRequestReviewRejected: - return matchPullRequestReviewEvent(commit, payload.(*api.PullRequestPayload), evt) + return matchPullRequestReviewEvent(payload.(*api.PullRequestPayload), evt) case // pull_request_review_comment webhook_module.HookEventPullRequestReviewComment: - return matchPullRequestReviewCommentEvent(commit, payload.(*api.PullRequestPayload), evt) + return matchPullRequestReviewCommentEvent(payload.(*api.PullRequestPayload), evt) case // release webhook_module.HookEventRelease: - return matchReleaseEvent(commit, payload.(*api.ReleasePayload), evt) + return matchReleaseEvent(payload.(*api.ReleasePayload), evt) case // registry_package webhook_module.HookEventPackage: - return matchPackageEvent(commit, payload.(*api.PackagePayload), evt) + return matchPackageEvent(payload.(*api.PackagePayload), evt) default: log.Warn("unsupported event %q", triggedEvent) @@ -350,7 +350,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa return matchTimes == len(evt.Acts()) } -func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *jobparser.Event) bool { +func matchIssuesEvent(issuePayload *api.IssuePayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true @@ -498,7 +498,7 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa return activityTypeMatched && matchTimes == len(evt.Acts()) } -func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool { +func matchIssueCommentEvent(issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true @@ -530,7 +530,7 @@ func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCo return matchTimes == len(evt.Acts()) } -func matchPullRequestReviewEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool { +func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true @@ -579,7 +579,7 @@ func matchPullRequestReviewEvent(commit *git.Commit, prPayload *api.PullRequestP return matchTimes == len(evt.Acts()) } -func matchPullRequestReviewCommentEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool { +func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true @@ -628,7 +628,7 @@ func matchPullRequestReviewCommentEvent(commit *git.Commit, prPayload *api.PullR return matchTimes == len(evt.Acts()) } -func matchReleaseEvent(commit *git.Commit, payload *api.ReleasePayload, evt *jobparser.Event) bool { +func matchReleaseEvent(payload *api.ReleasePayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true @@ -665,7 +665,7 @@ func matchReleaseEvent(commit *git.Commit, payload *api.ReleasePayload, evt *job return matchTimes == len(evt.Acts()) } -func matchPackageEvent(commit *git.Commit, payload *api.PackagePayload, evt *jobparser.Event) bool { +func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool { // with no special filter parameters if len(evt.Acts()) == 0 { return true diff --git a/modules/git/commit_info_nogogit.go b/modules/git/commit_info_nogogit.go index a5d18694f7..7c369b07f9 100644 --- a/modules/git/commit_info_nogogit.go +++ b/modules/git/commit_info_nogogit.go @@ -29,7 +29,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath var revs map[string]*Commit if commit.repo.LastCommitCache != nil { var unHitPaths []string - revs, unHitPaths, err = getLastCommitForPathsByCache(ctx, commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache) + revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache) if err != nil { return nil, nil, err } @@ -97,7 +97,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath return commitsInfo, treeCommit, nil } -func getLastCommitForPathsByCache(ctx context.Context, commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) { +func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) { var unHitEntryPaths []string results := make(map[string]*Commit) for _, p := range paths { diff --git a/modules/git/parse_gogit.go b/modules/git/parse_gogit.go index d1fdd346e4..74d258de8e 100644 --- a/modules/git/parse_gogit.go +++ b/modules/git/parse_gogit.go @@ -18,7 +18,7 @@ import ( ) // ParseTreeEntries parses the output of a `git ls-tree -l` command. -func ParseTreeEntries(h ObjectFormat, data []byte) ([]*TreeEntry, error) { +func ParseTreeEntries(data []byte) ([]*TreeEntry, error) { return parseTreeEntries(data, nil) } diff --git a/modules/git/parse_gogit_test.go b/modules/git/parse_gogit_test.go index d9e5b4441f..3e171d7e56 100644 --- a/modules/git/parse_gogit_test.go +++ b/modules/git/parse_gogit_test.go @@ -67,7 +67,7 @@ func TestParseTreeEntries(t *testing.T) { } for _, testCase := range testCases { - entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte(testCase.Input)) + entries, err := ParseTreeEntries([]byte(testCase.Input)) assert.NoError(t, err) if len(entries) > 1 { fmt.Println(testCase.Expected[0].ID) diff --git a/modules/git/parse_nogogit.go b/modules/git/parse_nogogit.go index 225342cc5a..546b38be37 100644 --- a/modules/git/parse_nogogit.go +++ b/modules/git/parse_nogogit.go @@ -17,13 +17,13 @@ import ( ) // ParseTreeEntries parses the output of a `git ls-tree -l` command. -func ParseTreeEntries(objectFormat ObjectFormat, data []byte) ([]*TreeEntry, error) { - return parseTreeEntries(objectFormat, data, nil) +func ParseTreeEntries(data []byte) ([]*TreeEntry, error) { + return parseTreeEntries(data, nil) } var sepSpace = []byte{' '} -func parseTreeEntries(objectFormat ObjectFormat, data []byte, ptree *Tree) ([]*TreeEntry, error) { +func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) { var err error entries := make([]*TreeEntry, 0, bytes.Count(data, []byte{'\n'})+1) for pos := 0; pos < len(data); { diff --git a/modules/git/parse_nogogit_test.go b/modules/git/parse_nogogit_test.go index f037fd7a2e..23fddb014c 100644 --- a/modules/git/parse_nogogit_test.go +++ b/modules/git/parse_nogogit_test.go @@ -12,8 +12,6 @@ import ( ) func TestParseTreeEntriesLong(t *testing.T) { - objectFormat := Sha1ObjectFormat - testCases := []struct { Input string Expected []*TreeEntry @@ -56,7 +54,7 @@ func TestParseTreeEntriesLong(t *testing.T) { }, } for _, testCase := range testCases { - entries, err := ParseTreeEntries(objectFormat, []byte(testCase.Input)) + entries, err := ParseTreeEntries([]byte(testCase.Input)) assert.NoError(t, err) assert.Len(t, entries, len(testCase.Expected)) for i, entry := range entries { @@ -66,8 +64,6 @@ func TestParseTreeEntriesLong(t *testing.T) { } func TestParseTreeEntriesShort(t *testing.T) { - objectFormat := Sha1ObjectFormat - testCases := []struct { Input string Expected []*TreeEntry @@ -91,7 +87,7 @@ func TestParseTreeEntriesShort(t *testing.T) { }, } for _, testCase := range testCases { - entries, err := ParseTreeEntries(objectFormat, []byte(testCase.Input)) + entries, err := ParseTreeEntries([]byte(testCase.Input)) assert.NoError(t, err) assert.Len(t, entries, len(testCase.Expected)) for i, entry := range entries { @@ -102,7 +98,7 @@ func TestParseTreeEntriesShort(t *testing.T) { func TestParseTreeEntriesInvalid(t *testing.T) { // there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315 - entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af")) + entries, err := ParseTreeEntries([]byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af")) assert.Error(t, err) assert.Len(t, entries, 0) } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index a591485082..e0a72de5b8 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -77,11 +77,8 @@ func (t *Tree) ListEntries() (Entries, error) { return nil, runErr } - objectFormat, err := t.repo.GetObjectFormat() - if err != nil { - return nil, err - } - t.entries, err = parseTreeEntries(objectFormat, stdout, t) + var err error + t.entries, err = parseTreeEntries(stdout, t) if err == nil { t.entriesParsed = true } @@ -104,11 +101,8 @@ func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) { return nil, runErr } - objectFormat, err := t.repo.GetObjectFormat() - if err != nil { - return nil, err - } - t.entriesRecursive, err = parseTreeEntries(objectFormat, stdout, t) + var err error + t.entriesRecursive, err = parseTreeEntries(stdout, t) if err == nil { t.entriesRecursiveParsed = true } diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index 2905a540e5..bc345f2325 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -62,8 +62,8 @@ func isIndexable(entry *git.TreeEntry) bool { } // parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command -func parseGitLsTreeOutput(objectFormat git.ObjectFormat, stdout []byte) ([]internal.FileUpdate, error) { - entries, err := git.ParseTreeEntries(objectFormat, stdout) +func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { + entries, err := git.ParseTreeEntries(stdout) if err != nil { return nil, err } @@ -91,10 +91,8 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s return nil, runErr } - objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName) - var err error - changes.Updates, err = parseGitLsTreeOutput(objectFormat, stdout) + changes.Updates, err = parseGitLsTreeOutput(stdout) return &changes, err } @@ -172,8 +170,6 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio return nil, err } - objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName) - - changes.Updates, err = parseGitLsTreeOutput(objectFormat, lsTreeStdout) + changes.Updates, err = parseGitLsTreeOutput(lsTreeStdout) return &changes, err } diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 8289e28677..0290e1312d 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -58,11 +58,11 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa case *ast.Paragraph: g.applyElementDir(v) case *ast.Image: - g.transformImage(ctx, v, reader) + g.transformImage(ctx, v) case *ast.Link: - g.transformLink(ctx, v, reader) + g.transformLink(ctx, v) case *ast.List: - g.transformList(ctx, v, reader, rc) + g.transformList(ctx, v, rc) case *ast.Text: if v.SoftLineBreak() && !v.HardLineBreak() { if ctx.Metas["mode"] != "document" { diff --git a/modules/markup/markdown/transform_heading.go b/modules/markup/markdown/transform_heading.go index ce585a37de..6f38abfad9 100644 --- a/modules/markup/markdown/transform_heading.go +++ b/modules/markup/markdown/transform_heading.go @@ -13,7 +13,7 @@ import ( "github.com/yuin/goldmark/util" ) -func (g *ASTTransformer) transformHeading(ctx *markup.RenderContext, v *ast.Heading, reader text.Reader, tocList *[]markup.Header) { +func (g *ASTTransformer) transformHeading(_ *markup.RenderContext, v *ast.Heading, reader text.Reader, tocList *[]markup.Header) { for _, attr := range v.Attributes() { if _, ok := attr.Value.([]byte); !ok { v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value))) diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go index db449e9dd9..b34a710fed 100644 --- a/modules/markup/markdown/transform_image.go +++ b/modules/markup/markdown/transform_image.go @@ -10,10 +10,9 @@ import ( giteautil "code.gitea.io/gitea/modules/util" "github.com/yuin/goldmark/ast" - "github.com/yuin/goldmark/text" ) -func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image, reader text.Reader) { +func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image) { // Images need two things: // // 1. Their src needs to munged to be a real value diff --git a/modules/markup/markdown/transform_link.go b/modules/markup/markdown/transform_link.go index aceae5b74f..e6f3836412 100644 --- a/modules/markup/markdown/transform_link.go +++ b/modules/markup/markdown/transform_link.go @@ -12,10 +12,9 @@ import ( giteautil "code.gitea.io/gitea/modules/util" "github.com/yuin/goldmark/ast" - "github.com/yuin/goldmark/text" ) -func (g *ASTTransformer) transformLink(ctx *markup.RenderContext, v *ast.Link, reader text.Reader) { +func (g *ASTTransformer) transformLink(ctx *markup.RenderContext, v *ast.Link) { // Links need their href to munged to be a real value link := v.Destination diff --git a/modules/markup/markdown/transform_list.go b/modules/markup/markdown/transform_list.go index 6563e2dd64..b982fd4a83 100644 --- a/modules/markup/markdown/transform_list.go +++ b/modules/markup/markdown/transform_list.go @@ -11,7 +11,6 @@ import ( "github.com/yuin/goldmark/ast" east "github.com/yuin/goldmark/extension/ast" "github.com/yuin/goldmark/renderer/html" - "github.com/yuin/goldmark/text" "github.com/yuin/goldmark/util" ) @@ -50,7 +49,7 @@ func (r *HTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node return ast.WalkContinue, nil } -func (g *ASTTransformer) transformList(ctx *markup.RenderContext, v *ast.List, reader text.Reader, rc *RenderConfig) { +func (g *ASTTransformer) transformList(_ *markup.RenderContext, v *ast.List, rc *RenderConfig) { if v.HasChildren() { children := make([]ast.Node, 0, v.ChildCount()) child := v.FirstChild() diff --git a/modules/markup/mdstripper/mdstripper.go b/modules/markup/mdstripper/mdstripper.go index e19f8f6419..2a69d95224 100644 --- a/modules/markup/mdstripper/mdstripper.go +++ b/modules/markup/mdstripper/mdstripper.go @@ -54,7 +54,7 @@ func (r *stripRenderer) Render(w io.Writer, source []byte, doc ast.Node) error { } return ast.WalkContinue, nil case *ast.Link: - r.processLink(w, v.Destination) + r.processLink(v.Destination) return ast.WalkSkipChildren, nil case *ast.AutoLink: // This could be a reference to an issue or pull - if so convert it @@ -124,7 +124,7 @@ func (r *stripRenderer) processAutoLink(w io.Writer, link []byte) { _, _ = w.Write([]byte(parts[4])) } -func (r *stripRenderer) processLink(w io.Writer, link []byte) { +func (r *stripRenderer) processLink(link []byte) { // Links are processed out of band r.links = append(r.links, string(link)) } diff --git a/modules/optional/option_test.go b/modules/optional/option_test.go index 4f55608004..203e9221e3 100644 --- a/modules/optional/option_test.go +++ b/modules/optional/option_test.go @@ -22,7 +22,7 @@ func TestOption(t *testing.T) { assert.Equal(t, int(0), none.Value()) assert.Equal(t, int(1), none.ValueOrDefault(1)) - some := optional.Some[int](1) + some := optional.Some(1) assert.True(t, some.Has()) assert.Equal(t, int(1), some.Value()) assert.Equal(t, int(1), some.ValueOrDefault(2)) diff --git a/modules/setting/incoming_email.go b/modules/setting/incoming_email.go index 314fdea137..287e72941c 100644 --- a/modules/setting/incoming_email.go +++ b/modules/setting/incoming_email.go @@ -56,12 +56,12 @@ func loadIncomingEmailFrom(rootCfg ConfigProvider) { } } - if err := checkReplyToAddress(IncomingEmail.ReplyToAddress); err != nil { + if err := checkReplyToAddress(); err != nil { log.Fatal("Invalid incoming_mail.REPLY_TO_ADDRESS (%s): %v", IncomingEmail.ReplyToAddress, err) } } -func checkReplyToAddress(address string) error { +func checkReplyToAddress() error { parsed, err := mail.ParseAddress(IncomingEmail.ReplyToAddress) if err != nil { return err diff --git a/modules/setting/storage.go b/modules/setting/storage.go index 1e2d28a88b..c082579d39 100644 --- a/modules/setting/storage.go +++ b/modules/setting/storage.go @@ -99,7 +99,7 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S return nil, err } - overrideSec := getStorageOverrideSection(rootCfg, targetSec, sec, tp, name) + overrideSec := getStorageOverrideSection(rootCfg, sec, tp, name) targetType := targetSec.Key("STORAGE_TYPE").String() switch targetType { @@ -191,7 +191,7 @@ func getStorageTargetSection(rootCfg ConfigProvider, name, typ string, sec Confi } // getStorageOverrideSection override section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible -func getStorageOverrideSection(rootConfig ConfigProvider, targetSec, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection { +func getStorageOverrideSection(rootConfig ConfigProvider, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection { if targetSecType == targetSecIsSec { return nil } diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index 2caaa130e8..f246b08c0a 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -180,7 +180,7 @@ func Migrate(ctx *context.APIContext) { Status: repo_model.RepositoryBeingMigrated, }) if err != nil { - handleMigrateError(ctx, repoOwner, remoteAddr, err) + handleMigrateError(ctx, repoOwner, err) return } @@ -207,7 +207,7 @@ func Migrate(ctx *context.APIContext) { }() if repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.Doer, repoOwner.Name, opts, nil); err != nil { - handleMigrateError(ctx, repoOwner, remoteAddr, err) + handleMigrateError(ctx, repoOwner, err) return } @@ -215,7 +215,7 @@ func Migrate(ctx *context.APIContext) { ctx.JSON(http.StatusCreated, convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeAdmin})) } -func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, remoteAddr string, err error) { +func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err error) { switch { case repo_model.IsErrRepoAlreadyExist(err): ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go index fe98178ac3..6c778c686c 100644 --- a/routers/web/admin/admin.go +++ b/routers/web/admin/admin.go @@ -158,7 +158,7 @@ func DashboardPost(ctx *context.Context) { switch form.Op { case "sync_repo_branches": go func() { - if err := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext(), ctx.Doer.ID); err != nil { + if err := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext()); err != nil { log.Error("AddAllRepoBranchesToSyncQueue: %v: %v", ctx.Doer.ID, err) } }() diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 743465082e..9ed57ec48c 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -287,7 +287,7 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) { } // feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item -func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) { +func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release) (items []*feeds.Item, err error) { for _, rel := range releases { err := rel.LoadAttributes(ctx) if err != nil { diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go index 273f47e3b4..fb6e3add65 100644 --- a/routers/web/feed/release.go +++ b/routers/web/feed/release.go @@ -42,7 +42,7 @@ func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleas Created: time.Now(), } - feed.Items, err = releasesToFeedItems(ctx, releases, isReleasesOnly) + feed.Items, err = releasesToFeedItems(ctx, releases) if err != nil { ctx.ServerError("releasesToFeedItems", err) return diff --git a/services/context/repo.go b/services/context/repo.go index 3e30f2ba97..54453cc2d9 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -810,7 +810,7 @@ func (rt RepoRefType) RefTypeIncludesTags() bool { return false } -func getRefNameFromPath(ctx *Base, repo *Repository, path string, isExist func(string) bool) string { +func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool) string { refName := "" parts := strings.Split(path, "/") for i, part := range parts { @@ -846,7 +846,7 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { repo.TreePath = path return repo.Repository.DefaultBranch case RepoRefBranch: - ref := getRefNameFromPath(ctx, repo, path, repo.GitRepo.IsBranchExist) + ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist) if len(ref) == 0 { // check if ref is HEAD parts := strings.Split(path, "/") @@ -856,7 +856,7 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { } // maybe it's a renamed branch - return getRefNameFromPath(ctx, repo, path, func(s string) bool { + return getRefNameFromPath(repo, path, func(s string) bool { b, exist, err := git_model.FindRenamedBranch(ctx, repo.Repository.ID, s) if err != nil { log.Error("FindRenamedBranch: %v", err) @@ -876,7 +876,7 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { return ref case RepoRefTag: - return getRefNameFromPath(ctx, repo, path, repo.GitRepo.IsTagExist) + return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist) case RepoRefCommit: parts := strings.Split(path, "/") diff --git a/services/doctor/storage.go b/services/doctor/storage.go index 787df27549..3f3b562c37 100644 --- a/services/doctor/storage.go +++ b/services/doctor/storage.go @@ -27,7 +27,7 @@ type commonStorageCheckOptions struct { name string } -func commonCheckStorage(ctx context.Context, logger log.Logger, autofix bool, opts *commonStorageCheckOptions) error { +func commonCheckStorage(logger log.Logger, autofix bool, opts *commonStorageCheckOptions) error { totalCount, orphanedCount := 0, 0 totalSize, orphanedSize := int64(0), int64(0) @@ -98,7 +98,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo } if opts.Attachments || opts.All { - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.Attachments, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { @@ -116,7 +116,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo logger.Info("LFS isn't enabled (skipped)") return nil } - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.LFS, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { @@ -132,7 +132,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo } if opts.Avatars || opts.All { - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.Avatars, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { @@ -146,7 +146,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo } if opts.RepoAvatars || opts.All { - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.RepoAvatars, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { @@ -160,7 +160,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo } if opts.RepoArchives || opts.All { - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.RepoArchives, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { @@ -182,7 +182,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo logger.Info("Packages isn't enabled (skipped)") return nil } - if err := commonCheckStorage(ctx, logger, autofix, + if err := commonCheckStorage(logger, autofix, &commonStorageCheckOptions{ storer: storage.Packages, isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) { diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 9baae6d31d..21a9c53a5c 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -982,25 +982,24 @@ func (g *GiteaLocalUploader) Finish() error { } func (g *GiteaLocalUploader) remapUser(source user_model.ExternalUserMigrated, target user_model.ExternalUserRemappable) error { - var userid int64 + var userID int64 var err error if g.sameApp { - userid, err = g.remapLocalUser(source, target) + userID, err = g.remapLocalUser(source) } else { - userid, err = g.remapExternalUser(source, target) + userID, err = g.remapExternalUser(source) } - if err != nil { return err } - if userid > 0 { - return target.RemapExternalUser("", 0, userid) + if userID > 0 { + return target.RemapExternalUser("", 0, userID) } return target.RemapExternalUser(source.GetExternalName(), source.GetExternalID(), g.doer.ID) } -func (g *GiteaLocalUploader) remapLocalUser(source user_model.ExternalUserMigrated, target user_model.ExternalUserRemappable) (int64, error) { +func (g *GiteaLocalUploader) remapLocalUser(source user_model.ExternalUserMigrated) (int64, error) { userid, ok := g.userMap[source.GetExternalID()] if !ok { name, err := user_model.GetUserNameByID(g.ctx, source.GetExternalID()) @@ -1018,7 +1017,7 @@ func (g *GiteaLocalUploader) remapLocalUser(source user_model.ExternalUserMigrat return userid, nil } -func (g *GiteaLocalUploader) remapExternalUser(source user_model.ExternalUserMigrated, target user_model.ExternalUserRemappable) (userid int64, err error) { +func (g *GiteaLocalUploader) remapExternalUser(source user_model.ExternalUserMigrated) (userid int64, err error) { userid, ok := g.userMap[source.GetExternalID()] if !ok { userid, err = user_model.GetUserIDByExternalUserID(g.ctx, g.gitServiceType.Name(), fmt.Sprintf("%d", source.GetExternalID())) diff --git a/services/mirror/mirror.go b/services/mirror/mirror.go index 0270f87039..44218d6fb3 100644 --- a/services/mirror/mirror.go +++ b/services/mirror/mirror.go @@ -90,7 +90,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error { pullMirrorsRequested := 0 if pullLimit != 0 { - if err := repo_model.MirrorsIterate(ctx, pullLimit, func(idx int, bean any) error { + if err := repo_model.MirrorsIterate(ctx, pullLimit, func(_ int, bean any) error { if err := handler(bean); err != nil { return err } diff --git a/services/pull/review.go b/services/pull/review.go index cff6f346ae..7a7f140602 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -49,7 +49,7 @@ var ErrSubmitReviewOnClosedPR = errors.New("can't submit review for a closed or // checkInvalidation checks if the line of code comment got changed by another commit. // If the line got changed the comment is going to be invalidated. -func checkInvalidation(ctx context.Context, c *issues_model.Comment, doer *user_model.User, repo *git.Repository, branch string) error { +func checkInvalidation(ctx context.Context, c *issues_model.Comment, repo *git.Repository, branch string) error { // FIXME differentiate between previous and proposed line commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine())) if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) { @@ -83,7 +83,7 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis return fmt.Errorf("find code comments: %v", err) } for _, comment := range codeComments { - if err := checkInvalidation(ctx, comment, doer, repo, branch); err != nil { + if err := checkInvalidation(ctx, comment, repo, branch); err != nil { return err } } diff --git a/services/pull/update.go b/services/pull/update.go index 1de125eb4d..1bba396880 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -39,7 +39,7 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model. AddTestPullRequestTask(ctx, doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "", 0) }() - return updateHeadByRebaseOnToBase(ctx, pr, doer, message) + return updateHeadByRebaseOnToBase(ctx, pr, doer) } if err := pr.LoadBaseRepo(ctx); err != nil { diff --git a/services/pull/update_rebase.go b/services/pull/update_rebase.go index 8e7bfa0ffd..3e2a7be132 100644 --- a/services/pull/update_rebase.go +++ b/services/pull/update_rebase.go @@ -18,7 +18,7 @@ import ( ) // updateHeadByRebaseOnToBase handles updating a PR's head branch by rebasing it on the PR current base branch -func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, message string) error { +func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User) error { // "Clone" base repo and add the cache headers for the head repo and branch mergeCtx, cancel, err := createTemporaryRepoForMerge(ctx, pr, doer, "") if err != nil { diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 31e3e581b3..914cd9047b 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -80,7 +80,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR return fmt.Errorf("getRepositoryByID: %w", err) } - if err := adoptRepository(ctx, repoPath, doer, repo, opts.DefaultBranch); err != nil { + if err := adoptRepository(ctx, repoPath, repo, opts.DefaultBranch); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } @@ -111,7 +111,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR return repo, nil } -func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, defaultBranch string) (err error) { +func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repository, defaultBranch string) (err error) { isExist, err := util.IsExist(repoPath) if err != nil { log.Error("Unable to check if %s exists. Error: %v", repoPath, err) diff --git a/services/repository/branch.go b/services/repository/branch.go index a59ad69717..b34bfa5fd5 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -491,7 +491,7 @@ func handlerBranchSync(items ...*BranchSyncOptions) []*BranchSyncOptions { return nil } -func addRepoToBranchSyncQueue(repoID, doerID int64) error { +func addRepoToBranchSyncQueue(repoID int64) error { return branchSyncQueue.Push(&BranchSyncOptions{ RepoID: repoID, }) @@ -507,9 +507,9 @@ func initBranchSyncQueue(ctx context.Context) error { return nil } -func AddAllRepoBranchesToSyncQueue(ctx context.Context, doerID int64) error { +func AddAllRepoBranchesToSyncQueue(ctx context.Context) error { if err := db.Iterate(ctx, builder.Eq{"is_empty": false}, func(ctx context.Context, repo *repo_model.Repository) error { - return addRepoToBranchSyncQueue(repo.ID, doerID) + return addRepoToBranchSyncQueue(repo.ID) }); err != nil { return fmt.Errorf("run sync all branches failed: %v", err) } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index 81a61da5ed..d6025b6ced 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -211,7 +211,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } for _, file := range opts.Files { - if err := handleCheckErrors(file, commit, opts, repo); err != nil { + if err := handleCheckErrors(file, commit, opts); err != nil { return nil, err } } @@ -277,7 +277,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } // handles the check for various issues for ChangeRepoFiles -func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions, repo *repo_model.Repository) error { +func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error { if file.Operation == "update" || file.Operation == "delete" { fromEntry, err := commit.GetTreeEntryByPath(file.Options.fromTreePath) if err != nil { diff --git a/services/user/update_test.go b/services/user/update_test.go index c2ff26a140..fc24a6c212 100644 --- a/services/user/update_test.go +++ b/services/user/update_test.go @@ -35,7 +35,7 @@ func TestUpdateUser(t *testing.T) { Description: optional.Some("description"), AllowGitHook: optional.Some(true), AllowImportLocal: optional.Some(true), - MaxRepoCreation: optional.Some[int](10), + MaxRepoCreation: optional.Some(10), IsRestricted: optional.Some(true), IsActive: optional.Some(false), IsAdmin: optional.Some(true), diff --git a/tests/integration/api_packages_chef_test.go b/tests/integration/api_packages_chef_test.go index 05545f11a6..6efb2708af 100644 --- a/tests/integration/api_packages_chef_test.go +++ b/tests/integration/api_packages_chef_test.go @@ -169,7 +169,7 @@ nwIDAQAB assert.Nil(t, u) assert.Error(t, err) - signRequest := func(t *testing.T, rw *RequestWrapper, version string) { + signRequest := func(rw *RequestWrapper, version string) { req := rw.Request username := req.Header.Get("X-Ops-Userid") if version != "1.0" && version != "1.3" { @@ -255,7 +255,7 @@ nwIDAQAB t.Run(v, func(t *testing.T) { defer tests.PrintCurrentTest(t)() - signRequest(t, req, v) + signRequest(req, v) u, err = auth.Verify(req.Request, nil, nil, nil) assert.NotNil(t, u) assert.NoError(t, err) diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go index 0a392d0a15..398ad15571 100644 --- a/tests/integration/api_releases_test.go +++ b/tests/integration/api_releases_test.go @@ -77,7 +77,7 @@ func TestAPIListReleases(t *testing.T) { testFilterByLen(true, url.Values{"draft": {"true"}, "pre-release": {"true"}}, 0, "there is no pre-release draft") } -func createNewReleaseUsingAPI(t *testing.T, session *TestSession, token string, owner *user_model.User, repo *repo_model.Repository, name, target, title, desc string) *api.Release { +func createNewReleaseUsingAPI(t *testing.T, token string, owner *user_model.User, repo *repo_model.Repository, name, target, title, desc string) *api.Release { urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases", owner.Name, repo.Name) req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateReleaseOption{ TagName: name, @@ -120,7 +120,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) { target, err := gitRepo.GetTagCommitID("v0.0.1") assert.NoError(t, err) - newRelease := createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", target, "v0.0.1", "test") + newRelease := createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", target, "v0.0.1", "test") urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/%d", owner.Name, repo.Name, newRelease.ID) req := NewRequest(t, "GET", urlStr). @@ -167,7 +167,7 @@ func TestAPICreateReleaseToDefaultBranch(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test") + createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", "", "v0.0.1", "test") } func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) { @@ -185,7 +185,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) { err = gitRepo.CreateTag("v0.0.1", "master") assert.NoError(t, err) - createNewReleaseUsingAPI(t, session, token, owner, repo, "v0.0.1", "", "v0.0.1", "test") + createNewReleaseUsingAPI(t, token, owner, repo, "v0.0.1", "", "v0.0.1", "test") } func TestAPIGetLatestRelease(t *testing.T) { @@ -237,7 +237,7 @@ func TestAPIDeleteReleaseByTagName(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test") + createNewReleaseUsingAPI(t, token, owner, repo, "release-tag", "", "Release Tag", "test") // delete release req := NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag", owner.Name, repo.Name)). @@ -263,7 +263,7 @@ func TestAPIUploadAssetRelease(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - r := createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test") + r := createNewReleaseUsingAPI(t, token, owner, repo, "release-tag", "", "Release Tag", "test") filename := "image.png" buff := generateImg() @@ -335,7 +335,7 @@ func TestAPIGetReleaseArchiveDownloadCount(t *testing.T) { name := "ReleaseDownloadCount" - createNewReleaseUsingAPI(t, session, token, owner, repo, name, "", name, "test") + createNewReleaseUsingAPI(t, token, owner, repo, name, "", name, "test") urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, name) diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go index 937f6a829c..c5883a8058 100644 --- a/tests/integration/api_repo_git_tags_test.go +++ b/tests/integration/api_repo_git_tags_test.go @@ -80,7 +80,7 @@ func TestAPIDeleteTagByName(t *testing.T) { _ = MakeRequest(t, req, http.StatusNoContent) // Make sure that actual releases can't be deleted outright - createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test") + createNewReleaseUsingAPI(t, token, owner, repo, "release-tag", "", "Release Tag", "test") req = NewRequest(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/tags/release-tag", owner.Name, repo.Name)). AddTokenAuth(token) diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go index 338305d950..a1252fa014 100644 --- a/tests/integration/pull_create_test.go +++ b/tests/integration/pull_create_test.go @@ -455,8 +455,6 @@ func TestRecentlyPushed(t *testing.T) { t.Run("unrelated branches are not shown", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}) - // Create a new branch with no relation to the default branch. // 1. Create a new Tree object cmd := git.NewCommand(db.DefaultContext, "write-tree") @@ -473,7 +471,7 @@ func TestRecentlyPushed(t *testing.T) { _, _, gitErr = cmd.RunStdString(&git.RunOpts{Dir: repo.RepoPath()}) assert.NoError(t, gitErr) // 4. Sync the git repo to the database - syncErr := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext(), adminUser.ID) + syncErr := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext()) assert.NoError(t, syncErr) // 5. Add a fresh commit, so that FindRecentlyPushedBranches has // something to find. diff --git a/tests/integration/repo_badges_test.go b/tests/integration/repo_badges_test.go index dbf6acb098..fda991b8dd 100644 --- a/tests/integration/repo_badges_test.go +++ b/tests/integration/repo_badges_test.go @@ -215,7 +215,7 @@ func TestBadges(t *testing.T) { token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) err := release.CreateNewTag(git.DefaultContext, repo.Owner, repo, "main", "repo-name-2.0", "dash in the tag name") assert.NoError(t, err) - createNewReleaseUsingAPI(t, session, token, repo.Owner, repo, "repo-name-2.0", "main", "dashed release", "dashed release") + createNewReleaseUsingAPI(t, token, repo.Owner, repo, "repo-name-2.0", "main", "dashed release", "dashed release") req := NewRequestf(t, "GET", "/user2/%s/badges/release.svg", repo.Name) resp := MakeRequest(t, req, http.StatusSeeOther) diff --git a/tests/integration/repo_branch_test.go b/tests/integration/repo_branch_test.go index 99d4f16d56..7f18bc7ddf 100644 --- a/tests/integration/repo_branch_test.go +++ b/tests/integration/repo_branch_test.go @@ -16,7 +16,6 @@ import ( git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/setting" @@ -170,7 +169,6 @@ func TestCreateBranchInvalidCSRF(t *testing.T) { func TestDatabaseMissingABranch(t *testing.T) { onGiteaRun(t, func(t *testing.T, URL *url.URL) { - adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}) session := loginUser(t, "user2") // Create two branches @@ -178,7 +176,7 @@ func TestDatabaseMissingABranch(t *testing.T) { testCreateBranch(t, session, "user2", "repo1", "branch/master", "will-be-missing", http.StatusSeeOther) // Run the repo branch sync, to ensure the db and git agree. - err2 := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext(), adminUser.ID) + err2 := repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext()) assert.NoError(t, err2) // Delete one branch from git only, leaving it in the database @@ -197,7 +195,7 @@ func TestDatabaseMissingABranch(t *testing.T) { assert.GreaterOrEqual(t, firstBranchCount, 3) // Run the repo branch sync again - err2 = repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext(), adminUser.ID) + err2 = repo_service.AddAllRepoBranchesToSyncQueue(graceful.GetManager().ShutdownContext()) assert.NoError(t, err2) // Verify that loading the repo's branches page works still, and that it diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index 49abeb83fb..7633d6915f 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -78,7 +78,7 @@ func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang } } -func getExpectedFileResponseForRepofilesDelete(u *url.URL) *api.FileResponse { +func getExpectedFileResponseForRepofilesDelete() *api.FileResponse { // Just returns fields that don't change, i.e. fields with commit SHAs and dates can't be determined return &api.FileResponse{ Content: nil, @@ -418,7 +418,7 @@ func testDeleteRepoFiles(t *testing.T, u *url.URL) { t.Run("Delete README.md file", func(t *testing.T) { filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) assert.NoError(t, err) - expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete() assert.NotNil(t, filesResponse) assert.Nil(t, filesResponse.Files[0]) assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) @@ -460,7 +460,7 @@ func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) { t.Run("Delete README.md without Branch Name", func(t *testing.T) { filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) assert.NoError(t, err) - expectedFileResponse := getExpectedFileResponseForRepofilesDelete(u) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete() assert.NotNil(t, filesResponse) assert.Nil(t, filesResponse.Files[0]) assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) From 60e58255793f0b325ea4c8a2d3250fb0df906e2c Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Tue, 30 Apr 2024 11:53:16 +0800 Subject: [PATCH 06/99] Fix duplicate status check contexts (#30660) Caused by #30076. There may be some duplicate status check contexts when setting status checks for a branch protection rule. The duplicate contexts should be removed. Before: After: (cherry picked from commit 7ad50313284db7eec565ad1750108de1444c5a84) --- models/git/commit_status.go | 30 +++-------------- models/git/commit_status_test.go | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 3f2172e50a..d975f0572c 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -362,36 +362,16 @@ func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, co // FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) { - type result struct { - Index int64 - SHA string - } - getBase := func() *xorm.Session { - return db.GetEngine(ctx).Table(&CommitStatus{}).Where("repo_id = ?", repoID) - } - start := timeutil.TimeStampNow().AddDuration(-before) - results := make([]result, 0, 10) - sess := getBase().And("updated_unix >= ?", start). - Select("max( `index` ) as `index`, sha"). - GroupBy("context_hash, sha").OrderBy("max( `index` ) desc") - - err := sess.Find(&results) - if err != nil { + var contexts []string + if err := db.GetEngine(ctx).Table("commit_status"). + Where("repo_id = ?", repoID).And("updated_unix >= ?", start). + Cols("context").Distinct().Find(&contexts); err != nil { return nil, err } - contexts := make([]string, 0, len(results)) - if len(results) == 0 { - return contexts, nil - } - - conds := make([]builder.Cond, 0, len(results)) - for _, result := range results { - conds = append(conds, builder.Eq{"`index`": result.Index, "sha": result.SHA}) - } - return contexts, getBase().And(builder.Or(conds...)).Select("context").Find(&contexts) + return contexts, nil } // NewCommitStatusOptions holds options for creating a CommitStatus diff --git a/models/git/commit_status_test.go b/models/git/commit_status_test.go index 94c8d3776c..2ada8b3724 100644 --- a/models/git/commit_status_test.go +++ b/models/git/commit_status_test.go @@ -5,11 +5,15 @@ package git_test import ( "testing" + "time" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/structs" "github.com/stretchr/testify/assert" @@ -183,3 +187,55 @@ func Test_CalcCommitStatus(t *testing.T) { assert.Equal(t, kase.expected, git_model.CalcCommitStatus(kase.statuses)) } } + +func TestFindRepoRecentCommitStatusContexts(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo2) + assert.NoError(t, err) + defer gitRepo.Close() + + commit, err := gitRepo.GetBranchCommit(repo2.DefaultBranch) + assert.NoError(t, err) + + defer func() { + _, err := db.DeleteByBean(db.DefaultContext, &git_model.CommitStatus{ + RepoID: repo2.ID, + CreatorID: user2.ID, + SHA: commit.ID.String(), + }) + assert.NoError(t, err) + }() + + err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{ + Repo: repo2, + Creator: user2, + SHA: commit.ID, + CommitStatus: &git_model.CommitStatus{ + State: structs.CommitStatusFailure, + TargetURL: "https://example.com/tests/", + Context: "compliance/lint-backend", + }, + }) + assert.NoError(t, err) + + err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{ + Repo: repo2, + Creator: user2, + SHA: commit.ID, + CommitStatus: &git_model.CommitStatus{ + State: structs.CommitStatusSuccess, + TargetURL: "https://example.com/tests/", + Context: "compliance/lint-backend", + }, + }) + assert.NoError(t, err) + + contexts, err := git_model.FindRepoRecentCommitStatusContexts(db.DefaultContext, repo2.ID, time.Hour) + assert.NoError(t, err) + if assert.Len(t, contexts, 1) { + assert.Equal(t, "compliance/lint-backend", contexts[0]) + } +} From 51b8d964c85b1fef52ffe7baeed0fb4a333ceeef Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 30 Apr 2024 17:36:28 +0200 Subject: [PATCH 07/99] Get repo assignees and reviewers should ignore deactivated users (#30770) (#30782) Backport #30770 If an user is deactivated, it should not be in the list of users who are suggested to be assigned or review-requested. old assignees or reviewers are not affected. --- *Sponsored by Kithara Software GmbH* (cherry picked from commit f2d8ccc5bb2df25557cc0d4d23f2cdd029358274) Conflicts: models/repo/user_repo_test.go because there is one less fixture user compared to Gitea --- models/repo/user_repo.go | 8 ++++++-- models/repo/user_repo_test.go | 23 ++++++++++++++++------- tests/integration/api_repo_test.go | 4 +++- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index d3fbd961bd..6790ee1da9 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -95,7 +95,10 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us // and just waste 1 unit is cheaper than re-allocate memory once. users := make([]*user_model.User, 0, len(uniqueUserIDs)+1) if len(userIDs) > 0 { - if err = e.In("id", uniqueUserIDs.Values()).OrderBy(user_model.GetOrderByName()).Find(&users); err != nil { + if err = e.In("id", uniqueUserIDs.Values()). + Where(builder.Eq{"`user`.is_active": true}). + OrderBy(user_model.GetOrderByName()). + Find(&users); err != nil { return nil, err } } @@ -117,7 +120,8 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) return nil, err } - cond := builder.And(builder.Neq{"`user`.id": posterID}) + cond := builder.And(builder.Neq{"`user`.id": posterID}). + And(builder.Eq{"`user`.is_active": true}) if repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate { // This a private repository: diff --git a/models/repo/user_repo_test.go b/models/repo/user_repo_test.go index ad794beb9b..0433ff83d8 100644 --- a/models/repo/user_repo_test.go +++ b/models/repo/user_repo_test.go @@ -26,10 +26,17 @@ func TestRepoAssignees(t *testing.T) { repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}) users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21) assert.NoError(t, err) - assert.Len(t, users, 3) - assert.Equal(t, users[0].ID, int64(15)) - assert.Equal(t, users[1].ID, int64(18)) - assert.Equal(t, users[2].ID, int64(16)) + if assert.Len(t, users, 3) { + assert.ElementsMatch(t, []int64{15, 16, 18}, []int64{users[0].ID, users[1].ID, users[2].ID}) + } + + // do not return deactivated users + assert.NoError(t, user_model.UpdateUserCols(db.DefaultContext, &user_model.User{ID: 15, IsActive: false}, "is_active")) + users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21) + assert.NoError(t, err) + if assert.Len(t, users, 2) { + assert.NotContains(t, []int64{users[0].ID, users[1].ID}, 15) + } } func TestRepoGetReviewers(t *testing.T) { @@ -41,17 +48,19 @@ func TestRepoGetReviewers(t *testing.T) { ctx := db.DefaultContext reviewers, err := repo_model.GetReviewers(ctx, repo1, 2, 2) assert.NoError(t, err) - assert.Len(t, reviewers, 4) + if assert.Len(t, reviewers, 3) { + assert.ElementsMatch(t, []int64{1, 4, 11}, []int64{reviewers[0].ID, reviewers[1].ID, reviewers[2].ID}) + } // should include doer if doer is not PR poster. reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 2) assert.NoError(t, err) - assert.Len(t, reviewers, 4) + assert.Len(t, reviewers, 3) // should not include PR poster, if PR poster would be otherwise eligible reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 4) assert.NoError(t, err) - assert.Len(t, reviewers, 3) + assert.Len(t, reviewers, 2) // test private user repo repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go index 2fb89cfa6e..96f38edc86 100644 --- a/tests/integration/api_repo_test.go +++ b/tests/integration/api_repo_test.go @@ -684,7 +684,9 @@ func TestAPIRepoGetReviewers(t *testing.T) { resp := MakeRequest(t, req, http.StatusOK) var reviewers []*api.User DecodeJSON(t, resp, &reviewers) - assert.Len(t, reviewers, 4) + if assert.Len(t, reviewers, 3) { + assert.ElementsMatch(t, []int64{1, 4, 11}, []int64{reviewers[0].ID, reviewers[1].ID, reviewers[2].ID}) + } } func TestAPIRepoGetAssignees(t *testing.T) { From 9792a377e4c646b8021ea9c5e92e7609415cbf0a Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 30 Apr 2024 14:34:40 +0200 Subject: [PATCH 08/99] Fix tautological conditions (#30735) As discovered by https://github.com/go-gitea/gitea/pull/30729. --------- Co-authored-by: Giteabot (cherry picked from commit 610802df85933e7a190a705bc3f7800da87ce868) Conflicts: tests/integration/git_test.go trivial conflict because of https://codeberg.org/forgejo/forgejo/pulls/2834 --- routers/private/hook_post_receive.go | 18 ++++++++---------- services/auth/source/oauth2/providers.go | 2 +- services/convert/issue.go | 14 ++++++++------ tests/integration/git_test.go | 9 +++------ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 2558ffe1ab..381e3c6c77 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -114,16 +114,14 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { } } if len(branchesToSync) > 0 { - if gitRepo == nil { - var err error - gitRepo, err = gitrepo.OpenRepository(ctx, repo) - if err != nil { - log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err) - ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ - Err: fmt.Sprintf("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err), - }) - return - } + var err error + gitRepo, err = gitrepo.OpenRepository(ctx, repo) + if err != nil { + log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ + Err: fmt.Sprintf("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err), + }) + return } var ( diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 6ed6c184eb..f2c1bb4894 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -182,7 +182,7 @@ func createProvider(providerName string, source *Source) (goth.Provider, error) } // always set the name if provider is created so we can support multiple setups of 1 provider - if err == nil && provider != nil { + if provider != nil { provider.SetName(providerName) } diff --git a/services/convert/issue.go b/services/convert/issue.go index 54b00cd88e..668affe09a 100644 --- a/services/convert/issue.go +++ b/services/convert/issue.go @@ -211,13 +211,11 @@ func ToLabel(label *issues_model.Label, repo *repo_model.Repository, org *user_m IsArchived: label.IsArchived(), } + labelBelongsToRepo := label.BelongsToRepo() + // calculate URL - if label.BelongsToRepo() && repo != nil { - if repo != nil { - result.URL = fmt.Sprintf("%s/labels/%d", repo.APIURL(), label.ID) - } else { - log.Error("ToLabel did not get repo to calculate url for label with id '%d'", label.ID) - } + if labelBelongsToRepo && repo != nil { + result.URL = fmt.Sprintf("%s/labels/%d", repo.APIURL(), label.ID) } else { // BelongsToOrg if org != nil { result.URL = fmt.Sprintf("%sapi/v1/orgs/%s/labels/%d", setting.AppURL, url.PathEscape(org.Name), label.ID) @@ -226,6 +224,10 @@ func ToLabel(label *issues_model.Label, repo *repo_model.Repository, org *user_m } } + if labelBelongsToRepo && repo == nil { + log.Error("ToLabel did not get repo to calculate url for label with id '%d'", label.ID) + } + return result } diff --git a/tests/integration/git_test.go b/tests/integration/git_test.go index 6ee3be2df2..d19b34a528 100644 --- a/tests/integration/git_test.go +++ b/tests/integration/git_test.go @@ -83,7 +83,7 @@ func testGit(t *testing.T, u *url.URL) { rawTest(t, &httpContext, little, big, littleLFS, bigLFS) mediaTest(t, &httpContext, little, big, littleLFS, bigLFS) - t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &httpContext, "master", "test/head")) + t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &httpContext, "test/head")) t.Run("InternalReferences", doInternalReferences(&httpContext, dstPath)) t.Run("BranchProtectMerge", doBranchProtectPRMerge(&httpContext, dstPath)) t.Run("AutoMerge", doAutoPRMerge(&httpContext, dstPath)) @@ -125,7 +125,7 @@ func testGit(t *testing.T, u *url.URL) { rawTest(t, &sshContext, little, big, littleLFS, bigLFS) mediaTest(t, &sshContext, little, big, littleLFS, bigLFS) - t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &sshContext, "master", "test/head2")) + t.Run("CreateAgitFlowPull", doCreateAgitFlowPull(dstPath, &sshContext, "test/head2")) t.Run("InternalReferences", doInternalReferences(&sshContext, dstPath)) t.Run("BranchProtectMerge", doBranchProtectPRMerge(&sshContext, dstPath)) t.Run("MergeFork", func(t *testing.T) { @@ -333,9 +333,6 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin } written += n } - if err != nil { - return "", err - } // Commit // Now here we should explicitly allow lfs filters to run @@ -750,7 +747,7 @@ func doInternalReferences(ctx *APITestContext, dstPath string) func(t *testing.T } } -func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headBranch string) func(t *testing.T) { +func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string) func(t *testing.T) { return func(t *testing.T) { defer tests.PrintCurrentTest(t)() From 1a40fe54a6fe169e3605f6eb634be4e5db4f4c64 Mon Sep 17 00:00:00 2001 From: Chester Date: Wed, 1 May 2024 09:40:23 +0800 Subject: [PATCH 09/99] Add API endpoints for getting action jobs status (#26673) Sample of response, it is similar to Github actions ref https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository ``` json { "workflow_runs": [ { "id": 3, "name": "Explore-Gitea-Actions", "head_branch": "main", "head_sha": "6d8d29a9f7a01ded8f8aeb64341cb31ee1ab5f19", "run_number": 3, "event": "push", "display_title": "More job", "status": "success", "workflow_id": "demo2.yaml", "url": "/chester/test/actions/runs/3", "created_at": "2023-08-22T13:41:33-04:00", "updated_at": "2023-08-22T13:41:37-04:00", "run_started_at": "2023-08-22T13:41:33-04:00" }, { "id": 2, "name": "Explore-Gitea-Actions", "head_branch": "main", "head_sha": "6d8d29a9f7a01ded8f8aeb64341cb31ee1ab5f19", "run_number": 2, "event": "push", "display_title": "More job", "status": "success", "workflow_id": "demo.yaml", "url": "/chester/test/actions/runs/2", "created_at": "2023-08-22T13:41:30-04:00", "updated_at": "2023-08-22T13:41:33-04:00", "run_started_at": "2023-08-22T13:41:30-04:00" }, { "id": 1, "name": "Explore-Gitea-Actions", "head_branch": "main", "head_sha": "e5369ab054cae79899ba36e45ee82811a6e0acd5", "run_number": 1, "event": "push", "display_title": "Add job", "status": "failure", "workflow_id": "demo.yaml", "url": "/chester/test/actions/runs/1", "created_at": "2023-08-22T13:15:21-04:00", "updated_at": "2023-08-22T13:18:10-04:00", "run_started_at": "2023-08-22T13:15:21-04:00" } ], "total_count": 3 } ``` --------- Co-authored-by: yp05327 <576951401@qq.com> Co-authored-by: puni9869 <80308335+puni9869@users.noreply.github.com> (cherry picked from commit 6709e28da78a0ea7e63f9fe4e32f620abdc88d14) Conflicts: routers/api/v1/swagger/repo.go trivial context conflict --- modules/structs/repo_actions.go | 34 ++++++++ routers/api/v1/api.go | 3 + routers/api/v1/repo/actions.go | 80 +++++++++++++++++ routers/api/v1/swagger/repo.go | 7 ++ services/convert/convert.go | 27 ++++++ templates/swagger/v1_json.tmpl | 149 ++++++++++++++++++++++++++++++++ 6 files changed, 300 insertions(+) create mode 100644 modules/structs/repo_actions.go create mode 100644 routers/api/v1/repo/actions.go diff --git a/modules/structs/repo_actions.go b/modules/structs/repo_actions.go new file mode 100644 index 0000000000..b13f344738 --- /dev/null +++ b/modules/structs/repo_actions.go @@ -0,0 +1,34 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +import ( + "time" +) + +// ActionTask represents a ActionTask +type ActionTask struct { + ID int64 `json:"id"` + Name string `json:"name"` + HeadBranch string `json:"head_branch"` + HeadSHA string `json:"head_sha"` + RunNumber int64 `json:"run_number"` + Event string `json:"event"` + DisplayTitle string `json:"display_title"` + Status string `json:"status"` + WorkflowID string `json:"workflow_id"` + URL string `json:"url"` + // swagger:strfmt date-time + CreatedAt time.Time `json:"created_at"` + // swagger:strfmt date-time + UpdatedAt time.Time `json:"updated_at"` + // swagger:strfmt date-time + RunStartedAt time.Time `json:"run_started_at"` +} + +// ActionTaskResponse returns a ActionTask +type ActionTaskResponse struct { + Entries []*ActionTask `json:"workflow_runs"` + TotalCount int64 `json:"total_count"` +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e4c848cd2f..528a5763eb 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1103,6 +1103,9 @@ func Routes() *web.Route { m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateTagOption{}), repo.CreateTag) m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteTag) }, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true)) + m.Group("/actions", func() { + m.Get("/tasks", repo.ListActionTasks) + }, reqRepoReader(unit.TypeActions), context.ReferencesGitRepo(true)) m.Group("/keys", func() { m.Combo("").Get(repo.ListDeployKeys). Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey) diff --git a/routers/api/v1/repo/actions.go b/routers/api/v1/repo/actions.go new file mode 100644 index 0000000000..635cb4e138 --- /dev/null +++ b/routers/api/v1/repo/actions.go @@ -0,0 +1,80 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repo + +import ( + "net/http" + + actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/convert" +) + +// ListActionTasks list all the actions of a repository +func ListActionTasks(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/actions/tasks repository ListActionTasks + // --- + // summary: List a repository's action tasks + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results, default maximum page size is 50 + // type: integer + // responses: + // "200": + // "$ref": "#/responses/TasksList" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" + // "409": + // "$ref": "#/responses/conflict" + // "422": + // "$ref": "#/responses/validationError" + + tasks, total, err := db.FindAndCount[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{ + ListOptions: utils.GetListOptions(ctx), + RepoID: ctx.Repo.Repository.ID, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ListActionTasks", err) + return + } + + res := new(api.ActionTaskResponse) + res.TotalCount = total + + res.Entries = make([]*api.ActionTask, len(tasks)) + for i := range tasks { + convertedTask, err := convert.ToActionTask(ctx, tasks[i]) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ToActionTask", err) + return + } + res.Entries[i] = convertedTask + } + + ctx.JSON(http.StatusOK, &res) +} diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index b55ea1d0a9..6d399ea185 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -422,6 +422,13 @@ type swaggerBlockedUserList struct { Body []api.BlockedUser `json:"body"` } +// TasksList +// swagger:response TasksList +type swaggerRepoTasksList struct { + // in:body + Body api.ActionTaskResponse `json:"body"` +} + // swagger:response Compare type swaggerCompare struct { // in:body diff --git a/services/convert/convert.go b/services/convert/convert.go index 55996d8fe3..abcdf917cd 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -11,6 +11,7 @@ import ( "strings" "time" + actions_model "code.gitea.io/gitea/models/actions" asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" git_model "code.gitea.io/gitea/models/git" @@ -24,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" @@ -195,6 +197,31 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag { } } +// ToActionTask convert a actions_model.ActionTask to an api.ActionTask +func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.ActionTask, error) { + if err := t.LoadAttributes(ctx); err != nil { + return nil, err + } + + url := strings.TrimSuffix(setting.AppURL, "/") + t.GetRunLink() + + return &api.ActionTask{ + ID: t.ID, + Name: t.Job.Name, + HeadBranch: t.Job.Run.PrettyRef(), + HeadSHA: t.Job.CommitSHA, + RunNumber: t.Job.Run.Index, + Event: t.Job.Run.TriggerEvent, + DisplayTitle: t.Job.Run.Title, + Status: t.Status.String(), + WorkflowID: t.Job.Run.WorkflowID, + URL: url, + CreatedAt: t.Created.AsLocalTime(), + UpdatedAt: t.Updated.AsLocalTime(), + RunStartedAt: t.Started.AsLocalTime(), + }, nil +} + // ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification func ToVerification(ctx context.Context, c *git.Commit) *api.PayloadCommitVerification { verif := asymkey_model.ParseCommitWithSignature(ctx, c) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index dbf9eb89e2..68ae0c3c43 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3865,6 +3865,66 @@ } } }, + "/repos/{owner}/{repo}/actions/tasks": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "List a repository's action tasks", + "operationId": "ListActionTasks", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results, default maximum page size is 50", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/TasksList" + }, + "400": { + "$ref": "#/responses/error" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" + }, + "409": { + "$ref": "#/responses/conflict" + }, + "422": { + "$ref": "#/responses/validationError" + } + } + } + }, "/repos/{owner}/{repo}/actions/variables": { "get": { "produces": [ @@ -18253,6 +18313,89 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "ActionTask": { + "description": "ActionTask represents a ActionTask", + "type": "object", + "properties": { + "created_at": { + "type": "string", + "format": "date-time", + "x-go-name": "CreatedAt" + }, + "display_title": { + "type": "string", + "x-go-name": "DisplayTitle" + }, + "event": { + "type": "string", + "x-go-name": "Event" + }, + "head_branch": { + "type": "string", + "x-go-name": "HeadBranch" + }, + "head_sha": { + "type": "string", + "x-go-name": "HeadSHA" + }, + "id": { + "type": "integer", + "format": "int64", + "x-go-name": "ID" + }, + "name": { + "type": "string", + "x-go-name": "Name" + }, + "run_number": { + "type": "integer", + "format": "int64", + "x-go-name": "RunNumber" + }, + "run_started_at": { + "type": "string", + "format": "date-time", + "x-go-name": "RunStartedAt" + }, + "status": { + "type": "string", + "x-go-name": "Status" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "x-go-name": "UpdatedAt" + }, + "url": { + "type": "string", + "x-go-name": "URL" + }, + "workflow_id": { + "type": "string", + "x-go-name": "WorkflowID" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "ActionTaskResponse": { + "description": "ActionTaskResponse returns a ActionTask", + "type": "object", + "properties": { + "total_count": { + "type": "integer", + "format": "int64", + "x-go-name": "TotalCount" + }, + "workflow_runs": { + "type": "array", + "items": { + "$ref": "#/definitions/ActionTask" + }, + "x-go-name": "Entries" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "ActionVariable": { "description": "ActionVariable return value of the query API", "type": "object", @@ -25831,6 +25974,12 @@ } } }, + "TasksList": { + "description": "TasksList", + "schema": { + "$ref": "#/definitions/ActionTaskResponse" + } + }, "Team": { "description": "Team", "schema": { From f0e466420a90852fe8075ebb30ee489f5c015b49 Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:33:40 -0700 Subject: [PATCH 10/99] Don't have `redis-cluster` as possible cache/session adapter in docs (#30794) This is because it doesn't exist as an adapter. The `redis` adapter already handles Redis cluster configurations. Fixes #30534. (cherry picked from commit f135cb7c9457f7b9bdc43601f44757834573950f) Conflicts: docs/content/administration/config-cheat-sheet.en-us.md does not exist in Forgejo --- custom/conf/app.example.ini | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 4eee2cd1ff..1d00c38816 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1471,7 +1471,7 @@ LEVEL = Info ;; Batch size to send for batched queues ;BATCH_LENGTH = 20 ;; -;; Connection string for redis queues this will store the redis or redis-cluster connection string. +;; Connection string for redis queues this will store the redis (or Redis cluster) connection string. ;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb ;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`. ;CONN_STR = "redis://127.0.0.1:6379/0" @@ -1756,9 +1756,8 @@ LEVEL = Info ;; For "memory" only, GC interval in seconds, default is 60 ;INTERVAL = 60 ;; -;; For "redis", "redis-cluster" and "memcache", connection host address -;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` -;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` +;; For "redis" and "memcache", connection host address +;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster) ;; memcache: `127.0.0.1:11211` ;; twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` ;HOST = @@ -1788,15 +1787,14 @@ LEVEL = Info ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Either "memory", "file", "redis", "redis-cluster", "db", "mysql", "couchbase", "memcache" or "postgres" +;; Either "memory", "file", "redis", "db", "mysql", "couchbase", "memcache" or "postgres" ;; Default is "memory". "db" will reuse the configuration in [database] ;PROVIDER = memory ;; ;; Provider config options ;; memory: doesn't have any config yet ;; file: session file path, e.g. `data/sessions` -;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` -;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` +;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster) ;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table` ;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_. ;; From 4e35e5b8ae2bf01694bca76bd6fbee9c58934388 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 2 May 2024 10:27:25 +0800 Subject: [PATCH 11/99] Skip gzip for some well-known compressed file types (#30796) Co-authored-by: silverwind (cherry picked from commit be112c1fc30f87a248b30f48e891d1c8c18e8280) Conflicts: routers/web/web.go trivial conflict because of https://codeberg.org/forgejo/forgejo/pulls/1533 --- modules/httplib/serve.go | 8 +++++++ tests/integration/repo_archive_test.go | 31 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/integration/repo_archive_test.go diff --git a/modules/httplib/serve.go b/modules/httplib/serve.go index a193ed901c..6e147d76f5 100644 --- a/modules/httplib/serve.go +++ b/modules/httplib/serve.go @@ -17,11 +17,14 @@ import ( "time" charsetModule "code.gitea.io/gitea/modules/charset" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/typesniffer" "code.gitea.io/gitea/modules/util" + + "github.com/klauspost/compress/gzhttp" ) type ServeHeaderOptions struct { @@ -38,6 +41,11 @@ type ServeHeaderOptions struct { func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) { header := w.Header() + skipCompressionExts := container.SetOf(".gz", ".bz2", ".zip", ".xz", ".zst", ".deb", ".apk", ".jar", ".png", ".jpg", ".webp") + if skipCompressionExts.Contains(strings.ToLower(path.Ext(opts.Filename))) { + w.Header().Add(gzhttp.HeaderNoCompression, "1") + } + contentType := typesniffer.ApplicationOctetStream if opts.ContentType != "" { if opts.ContentTypeCharset != "" { diff --git a/tests/integration/repo_archive_test.go b/tests/integration/repo_archive_test.go new file mode 100644 index 0000000000..ebc6467378 --- /dev/null +++ b/tests/integration/repo_archive_test.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "io" + "net/http" + "testing" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/routers" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestRepoDownloadArchive(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.EnableGzip, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + + req := NewRequest(t, "GET", "/user2/repo1/archive/master.zip") + req.Header.Set("Accept-Encoding", "gzip") + resp := MakeRequest(t, req, http.StatusOK) + bs, err := io.ReadAll(resp.Body) + assert.NoError(t, err) + assert.Empty(t, resp.Header().Get("Content-Encoding")) + assert.Equal(t, 320, len(bs)) +} From ee97bb17ba5312730bf4de94244af63132f687a5 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 2 May 2024 19:19:44 +0800 Subject: [PATCH 12/99] Fix issue card layout (#30800) Fix #30788 (cherry picked from commit 6ff2acc52c976e9d7bb6a5693f8a2365d12400f5) --- templates/repo/issue/card.tmpl | 6 +++--- web_src/css/repo.css | 8 +------- web_src/css/repo/issue-card.css | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl index 4a0ac050aa..526f6dd5db 100644 --- a/templates/repo/issue/card.tmpl +++ b/templates/repo/issue/card.tmpl @@ -62,13 +62,13 @@
{{if or .Labels .Assignees}} -
-
+
+
{{range .Labels}} {{RenderLabel ctx ctx.Locale .}} {{end}}
-
+
{{range .Assignees}} {{ctx.AvatarUtils.Avatar . 28}} {{end}} diff --git a/web_src/css/repo.css b/web_src/css/repo.css index bf6bfd464b..a29e9a0986 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -2368,18 +2368,12 @@ td .commit-summary { display: inline-flex; flex-wrap: wrap; gap: 2.5px; -} - -.labels-list a { - display: flex; - text-decoration: none; + align-items: center; } .labels-list .label { padding: 0 6px; - margin: 0 !important; min-height: 20px; - display: inline-flex !important; line-height: 1.3; /* there is a `font-size: 1.25em` for inside emoji, so here the line-height needs to be larger slightly */ } diff --git a/web_src/css/repo/issue-card.css b/web_src/css/repo/issue-card.css index 609b1b3dbd..390bfb6a01 100644 --- a/web_src/css/repo/issue-card.css +++ b/web_src/css/repo/issue-card.css @@ -23,3 +23,18 @@ .issue-card.sortable-chosen .issue-card-title { cursor: inherit; } + +.issue-card-bottom { + display: flex; + width: 100%; + justify-content: space-between; + gap: 0.25em; +} + +.issue-card-assignees { + display: flex; + align-items: center; + gap: 0.25em; + justify-content: end; + flex-wrap: wrap; +} From fb693442f5f148fdbf7f6d62e6e9e6a084402ca2 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 2 May 2024 16:43:23 +0200 Subject: [PATCH 13/99] Remove external API calls in `TestPassword` (#30716) The test had a dependency on `https://api.pwnedpasswords.com` which caused many failures on CI recently: ``` --- FAIL: TestPassword (2.37s) pwn_test.go:41: Get "https://api.pwnedpasswords.com/range/e6b6a": context deadline exceeded (Client.Timeout exceeded while awaiting headers) FAIL coverage: 82.9% of statements ``` (cherry picked from commit 9235442ba58524c8d12ae54865d583acfa1f439d) --- go.mod | 2 + go.sum | 6 ++ modules/auth/password/pwn/pwn_test.go | 101 ++++++-------------------- 3 files changed, 32 insertions(+), 77 deletions(-) diff --git a/go.mod b/go.mod index 9dc8ae3f5b..1fa24d023a 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.1.2 github.com/gorilla/sessions v1.2.2 + github.com/h2non/gock v1.2.0 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/huandu/xstrings v1.4.0 @@ -202,6 +203,7 @@ require ( github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect + github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/hcl v1.0.0 // indirect diff --git a/go.sum b/go.sum index a42bce3812..4276c181c7 100644 --- a/go.sum +++ b/go.sum @@ -477,6 +477,10 @@ github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= +github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= @@ -641,6 +645,8 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE= github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek= github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= diff --git a/modules/auth/password/pwn/pwn_test.go b/modules/auth/password/pwn/pwn_test.go index a2a6b3a174..b3e7734c3f 100644 --- a/modules/auth/password/pwn/pwn_test.go +++ b/modules/auth/password/pwn/pwn_test.go @@ -4,12 +4,11 @@ package pwn import ( - "math/rand/v2" "net/http" - "strings" "testing" "time" + "github.com/h2non/gock" "github.com/stretchr/testify/assert" ) @@ -18,86 +17,34 @@ var client = New(WithHTTP(&http.Client{ })) func TestPassword(t *testing.T) { - // Check input error - _, err := client.CheckPassword("", false) + defer gock.Off() + + count, err := client.CheckPassword("", false) assert.ErrorIs(t, err, ErrEmptyPassword, "blank input should return ErrEmptyPassword") + assert.Equal(t, -1, count) - // Should fail - fail := "password1234" - count, err := client.CheckPassword(fail, false) - assert.NotEmpty(t, count, "%s should fail as a password", fail) + gock.New("https://api.pwnedpasswords.com").Get("/range/5c1d8").Times(1).Reply(200).BodyString("EAF2F254732680E8AC339B84F3266ECCBB5:1\r\nFC446EB88938834178CB9322C1EE273C2A7:2") + count, err = client.CheckPassword("pwned", false) assert.NoError(t, err) + assert.Equal(t, 1, count) - // Should fail (with padding) - failPad := "administrator" - count, err = client.CheckPassword(failPad, true) - assert.NotEmpty(t, count, "%s should fail as a password", failPad) + gock.New("https://api.pwnedpasswords.com").Get("/range/ba189").Times(1).Reply(200).BodyString("FD4CB34F0378BCB15D23F6FFD28F0775C9E:3\r\nFDF342FCD8C3611DAE4D76E8A992A3E4169:4") + count, err = client.CheckPassword("notpwned", false) assert.NoError(t, err) + assert.Equal(t, 0, count) - // Checking for a "good" password isn't going to be perfect, but we can give it a good try - // with hopefully minimal error. Try five times? - assert.Condition(t, func() bool { - for i := 0; i <= 5; i++ { - count, err = client.CheckPassword(testPassword(), false) - assert.NoError(t, err) - if count == 0 { - return true - } - } - return false - }, "no generated passwords passed. there is a chance this is a fluke") + gock.New("https://api.pwnedpasswords.com").Get("/range/a1733").Times(1).Reply(200).BodyString("C4CE0F1F0062B27B9E2F41AF0C08218017C:1\r\nFC446EB88938834178CB9322C1EE273C2A7:2\r\nFE81480327C992FE62065A827429DD1318B:0") + count, err = client.CheckPassword("paddedpwned", true) + assert.NoError(t, err) + assert.Equal(t, 1, count) - // Again, but with padded responses - assert.Condition(t, func() bool { - for i := 0; i <= 5; i++ { - count, err = client.CheckPassword(testPassword(), true) - assert.NoError(t, err) - if count == 0 { - return true - } - } - return false - }, "no generated passwords passed. there is a chance this is a fluke") -} - -// Credit to https://golangbyexample.com/generate-random-password-golang/ -// DO NOT USE THIS FOR AN ACTUAL PASSWORD GENERATOR -var ( - lowerCharSet = "abcdedfghijklmnopqrst" - upperCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - specialCharSet = "!@#$%&*" - numberSet = "0123456789" - allCharSet = lowerCharSet + upperCharSet + specialCharSet + numberSet -) - -func testPassword() string { - var password strings.Builder - - // Set special character - for i := 0; i < 5; i++ { - random := rand.IntN(len(specialCharSet)) - password.WriteString(string(specialCharSet[random])) - } - - // Set numeric - for i := 0; i < 5; i++ { - random := rand.IntN(len(numberSet)) - password.WriteString(string(numberSet[random])) - } - - // Set uppercase - for i := 0; i < 5; i++ { - random := rand.IntN(len(upperCharSet)) - password.WriteString(string(upperCharSet[random])) - } - - for i := 0; i < 5; i++ { - random := rand.IntN(len(allCharSet)) - password.WriteString(string(allCharSet[random])) - } - inRune := []rune(password.String()) - rand.Shuffle(len(inRune), func(i, j int) { - inRune[i], inRune[j] = inRune[j], inRune[i] - }) - return string(inRune) + gock.New("https://api.pwnedpasswords.com").Get("/range/5617b").Times(1).Reply(200).BodyString("FD4CB34F0378BCB15D23F6FFD28F0775C9E:3\r\nFDF342FCD8C3611DAE4D76E8A992A3E4169:4\r\nFE81480327C992FE62065A827429DD1318B:0") + count, err = client.CheckPassword("paddednotpwned", true) + assert.NoError(t, err) + assert.Equal(t, 0, count) + + gock.New("https://api.pwnedpasswords.com").Get("/range/79082").Times(1).Reply(200).BodyString("FDF342FCD8C3611DAE4D76E8A992A3E4169:4\r\nFE81480327C992FE62065A827429DD1318B:0\r\nAFEF386F56EB0B4BE314E07696E5E6E6536:0") + count, err = client.CheckPassword("paddednotpwnedzero", true) + assert.NoError(t, err) + assert.Equal(t, 0, count) } From 396f16e7b2aa59275444139b5f7d7cfa417b7e5f Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 2 May 2024 16:56:17 +0200 Subject: [PATCH 14/99] Add hover outline to heatmap squares (#30828) Makes it easier to use because you see which square is currently hovered: Screenshot 2024-05-02 at 15 38 20 I did try a `scoped` style for this, but that did not work for some reason. (cherry picked from commit 6f89d5e3a0886d02ead732005f593ae003f78f78) --- web_src/css/features/heatmap.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web_src/css/features/heatmap.css b/web_src/css/features/heatmap.css index 364754751a..c064590c46 100644 --- a/web_src/css/features/heatmap.css +++ b/web_src/css/features/heatmap.css @@ -31,6 +31,10 @@ padding: 0 5px; } +#user-heatmap .vch__day__square:hover { + outline: 1.5px solid var(--color-text); +} + /* move the "? contributions in the last ? months" text from top to bottom */ #user-heatmap .total-contributions { font-size: 11px; From 9cd0441cd384f7fbff8e973182c6094270e7f97e Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Thu, 2 May 2024 09:33:31 -0700 Subject: [PATCH 15/99] Catch and handle unallowed file type errors in issue attachment API (#30791) Before, we would just throw 500 if a user passes an attachment that is not an allowed type. This commit catches this error and throws a 422 instead since this should be considered a validation error. (cherry picked from commit 872caa17c0a30d95f85ab75c068d606e07bd10b3) Conflicts: tests/integration/api_comment_attachment_test.go tests/integration/api_issue_attachment_test.go trivial context conflict because of 'allow setting the update date on issues and comments' --- routers/api/v1/repo/issue_attachment.go | 9 +++++- .../api/v1/repo/issue_comment_attachment.go | 10 ++++++- templates/swagger/v1_json.tmpl | 6 ++++ .../api_comment_attachment_test.go | 28 +++++++++++++++++++ .../integration/api_issue_attachment_test.go | 27 ++++++++++++++++++ 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go index 6f3e4b5e77..658d18094a 100644 --- a/routers/api/v1/repo/issue_attachment.go +++ b/routers/api/v1/repo/issue_attachment.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/attachment" "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) @@ -159,6 +160,8 @@ func CreateIssueAttachment(ctx *context.APIContext) { // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/error" + // "422": + // "$ref": "#/responses/validationError" // "423": // "$ref": "#/responses/repoArchivedError" @@ -207,7 +210,11 @@ func CreateIssueAttachment(ctx *context.APIContext) { CreatedUnix: issue.UpdatedUnix, }) if err != nil { - ctx.Error(http.StatusInternalServerError, "UploadAttachment", err) + if upload.IsErrFileTypeForbidden(err) { + ctx.Error(http.StatusUnprocessableEntity, "", err) + } else { + ctx.Error(http.StatusInternalServerError, "UploadAttachment", err) + } return } diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go index 0f8fc96f08..ed8ea10293 100644 --- a/routers/api/v1/repo/issue_comment_attachment.go +++ b/routers/api/v1/repo/issue_comment_attachment.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/attachment" "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" ) @@ -156,6 +157,8 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) { // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/error" + // "422": + // "$ref": "#/responses/validationError" // "423": // "$ref": "#/responses/repoArchivedError" @@ -209,9 +212,14 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) { CreatedUnix: comment.Issue.UpdatedUnix, }) if err != nil { - ctx.Error(http.StatusInternalServerError, "UploadAttachment", err) + if upload.IsErrFileTypeForbidden(err) { + ctx.Error(http.StatusUnprocessableEntity, "", err) + } else { + ctx.Error(http.StatusInternalServerError, "UploadAttachment", err) + } return } + if err := comment.LoadAttachments(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "LoadAttachments", err) return diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 68ae0c3c43..9c78b718a7 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -7606,6 +7606,9 @@ "404": { "$ref": "#/responses/error" }, + "422": { + "$ref": "#/responses/validationError" + }, "423": { "$ref": "#/responses/repoArchivedError" } @@ -8232,6 +8235,9 @@ "404": { "$ref": "#/responses/error" }, + "422": { + "$ref": "#/responses/validationError" + }, "423": { "$ref": "#/responses/repoArchivedError" } diff --git a/tests/integration/api_comment_attachment_test.go b/tests/integration/api_comment_attachment_test.go index d4368d51fe..1b3cae91e2 100644 --- a/tests/integration/api_comment_attachment_test.go +++ b/tests/integration/api_comment_attachment_test.go @@ -240,3 +240,31 @@ func TestAPIDeleteCommentAttachment(t *testing.T) { unittest.AssertNotExistsBean(t, &repo_model.Attachment{ID: attachment.ID, CommentID: comment.ID}) } + +func TestAPICreateCommentAttachmentWithUnallowedFile(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2}) + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) + repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + session := loginUser(t, repoOwner.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue) + + filename := "file.bad" + body := &bytes.Buffer{} + + // Setup multi-part. + writer := multipart.NewWriter(body) + _, err := writer.CreateFormFile("attachment", filename) + assert.NoError(t, err) + err = writer.Close() + assert.NoError(t, err) + + req := NewRequestWithBody(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/assets", repoOwner.Name, repo.Name, comment.ID), body). + AddTokenAuth(token). + SetHeader("Content-Type", writer.FormDataContentType()) + + session.MakeRequest(t, req, http.StatusUnprocessableEntity) +} diff --git a/tests/integration/api_issue_attachment_test.go b/tests/integration/api_issue_attachment_test.go index b6a0cca6d5..919dea2e62 100644 --- a/tests/integration/api_issue_attachment_test.go +++ b/tests/integration/api_issue_attachment_test.go @@ -173,6 +173,33 @@ func TestAPICreateIssueAttachmentAutoDate(t *testing.T) { }) } +func TestAPICreateIssueAttachmentWithUnallowedFile(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID}) + repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + session := loginUser(t, repoOwner.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue) + + filename := "file.bad" + body := &bytes.Buffer{} + + // Setup multi-part. + writer := multipart.NewWriter(body) + _, err := writer.CreateFormFile("attachment", filename) + assert.NoError(t, err) + err = writer.Close() + assert.NoError(t, err) + + req := NewRequestWithBody(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/assets", repoOwner.Name, repo.Name, issue.Index), body). + AddTokenAuth(token) + req.Header.Add("Content-Type", writer.FormDataContentType()) + + session.MakeRequest(t, req, http.StatusUnprocessableEntity) +} + func TestAPIEditIssueAttachment(t *testing.T) { defer tests.PrepareTestEnv(t)() From 1b088fade6c69e63843d1bdf402454c363b22ce2 Mon Sep 17 00:00:00 2001 From: Archer Date: Thu, 2 May 2024 19:05:59 +0200 Subject: [PATCH 16/99] Prevent automatic OAuth grants for public clients (#30790) This commit forces the resource owner (user) to always approve OAuth 2.0 authorization requests if the client is public (e.g. native applications). As detailed in [RFC 6749 Section 10.2](https://www.rfc-editor.org/rfc/rfc6749.html#section-10.2), > The authorization server SHOULD NOT process repeated authorization requests automatically (without active resource owner interaction) without authenticating the client or relying on other measures to ensure that the repeated request comes from the original client and not an impersonator. With the implementation prior to this patch, attackers with access to the redirect URI (e.g., the loopback interface for `git-credential-oauth`) can get access to the user account without any user interaction if they can redirect the user to the `/login/oauth/authorize` endpoint somehow (e.g., with `xdg-open` on Linux). Fixes #25061. Co-authored-by: wxiaoguang (cherry picked from commit 5c542ca94caa3587329167cfe9e949357ca15cf1) --- routers/web/auth/oauth.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index 3ad7a4738e..61c580cae3 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -471,8 +471,9 @@ func AuthorizeOAuth(ctx *context.Context) { return } - // Redirect if user already granted access - if grant != nil { + // Redirect if user already granted access and the application is confidential. + // I.e. always require authorization for public clients as recommended by RFC 6749 Section 10.2 + if app.ConfidentialClient && grant != nil { code, err := grant.GenerateNewAuthorizationCode(ctx, form.RedirectURI, form.CodeChallenge, form.CodeChallengeMethod) if err != nil { handleServerError(ctx, form.State, form.RedirectURI) From b29190c4f0b6ec419e74cb14dff0e30d069b870b Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Fri, 3 May 2024 01:43:29 +0800 Subject: [PATCH 17/99] refactor: merge ListActionTasks func to action.go file (#30811) Just merge actions.go file to action.go Signed-off-by: Bo-Yi Wu (cherry picked from commit e67fbe4f15cdc544f6bec975de6560556724f098) --- routers/api/v1/repo/action.go | 66 ++++++++++++++++++++++++++++ routers/api/v1/repo/actions.go | 80 ---------------------------------- 2 files changed, 66 insertions(+), 80 deletions(-) delete mode 100644 routers/api/v1/repo/actions.go diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 311cfca6e9..f6656d89c6 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/routers/api/v1/utils" actions_service "code.gitea.io/gitea/services/actions" "code.gitea.io/gitea/services/context" + "code.gitea.io/gitea/services/convert" secret_service "code.gitea.io/gitea/services/secrets" ) @@ -517,3 +518,68 @@ type Action struct{} func NewAction() actions_service.API { return Action{} } + +// ListActionTasks list all the actions of a repository +func ListActionTasks(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/actions/tasks repository ListActionTasks + // --- + // summary: List a repository's action tasks + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results, default maximum page size is 50 + // type: integer + // responses: + // "200": + // "$ref": "#/responses/TasksList" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" + // "409": + // "$ref": "#/responses/conflict" + // "422": + // "$ref": "#/responses/validationError" + + tasks, total, err := db.FindAndCount[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{ + ListOptions: utils.GetListOptions(ctx), + RepoID: ctx.Repo.Repository.ID, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ListActionTasks", err) + return + } + + res := new(api.ActionTaskResponse) + res.TotalCount = total + + res.Entries = make([]*api.ActionTask, len(tasks)) + for i := range tasks { + convertedTask, err := convert.ToActionTask(ctx, tasks[i]) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ToActionTask", err) + return + } + res.Entries[i] = convertedTask + } + + ctx.JSON(http.StatusOK, &res) +} diff --git a/routers/api/v1/repo/actions.go b/routers/api/v1/repo/actions.go deleted file mode 100644 index 635cb4e138..0000000000 --- a/routers/api/v1/repo/actions.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repo - -import ( - "net/http" - - actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/routers/api/v1/utils" - "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/convert" -) - -// ListActionTasks list all the actions of a repository -func ListActionTasks(ctx *context.APIContext) { - // swagger:operation GET /repos/{owner}/{repo}/actions/tasks repository ListActionTasks - // --- - // summary: List a repository's action tasks - // produces: - // - application/json - // parameters: - // - name: owner - // in: path - // description: owner of the repo - // type: string - // required: true - // - name: repo - // in: path - // description: name of the repo - // type: string - // required: true - // - name: page - // in: query - // description: page number of results to return (1-based) - // type: integer - // - name: limit - // in: query - // description: page size of results, default maximum page size is 50 - // type: integer - // responses: - // "200": - // "$ref": "#/responses/TasksList" - // "400": - // "$ref": "#/responses/error" - // "403": - // "$ref": "#/responses/forbidden" - // "404": - // "$ref": "#/responses/notFound" - // "409": - // "$ref": "#/responses/conflict" - // "422": - // "$ref": "#/responses/validationError" - - tasks, total, err := db.FindAndCount[actions_model.ActionTask](ctx, &actions_model.FindTaskOptions{ - ListOptions: utils.GetListOptions(ctx), - RepoID: ctx.Repo.Repository.ID, - }) - if err != nil { - ctx.Error(http.StatusInternalServerError, "ListActionTasks", err) - return - } - - res := new(api.ActionTaskResponse) - res.TotalCount = total - - res.Entries = make([]*api.ActionTask, len(tasks)) - for i := range tasks { - convertedTask, err := convert.ToActionTask(ctx, tasks[i]) - if err != nil { - ctx.Error(http.StatusInternalServerError, "ToActionTask", err) - return - } - res.Entries[i] = convertedTask - } - - ctx.JSON(http.StatusOK, &res) -} From d93d62371ce2b6cf7c207b01479799293bd2efd6 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 3 May 2024 10:39:36 +0800 Subject: [PATCH 18/99] Ignore useless error message "broken pipe" (#30801) Fix #30792 (cherry picked from commit 53b55223d167c3fc996dd0278a656f421408ace7) --- routers/api/packages/maven/maven.go | 4 +--- services/context/base.go | 4 +--- services/context/context_response.go | 3 ++- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go index 7571797593..58271e1d43 100644 --- a/routers/api/packages/maven/maven.go +++ b/routers/api/packages/maven/maven.go @@ -143,9 +143,7 @@ func serveMavenMetadata(ctx *context.Context, params parameters) { ctx.Resp.Header().Set("Content-Length", strconv.Itoa(len(xmlMetadataWithHeader))) ctx.Resp.Header().Set("Content-Type", contentTypeXML) - if _, err := ctx.Resp.Write(xmlMetadataWithHeader); err != nil { - log.Error("write bytes failed: %v", err) - } + _, _ = ctx.Resp.Write(xmlMetadataWithHeader) } func servePackageFile(ctx *context.Context, params parameters, serveContent bool) { diff --git a/services/context/base.go b/services/context/base.go index 25ff935055..0259e0d806 100644 --- a/services/context/base.go +++ b/services/context/base.go @@ -234,9 +234,7 @@ func (b *Base) plainTextInternal(skip, status int, bs []byte) { b.Resp.Header().Set("Content-Type", "text/plain;charset=utf-8") b.Resp.Header().Set("X-Content-Type-Options", "nosniff") b.Resp.WriteHeader(status) - if _, err := b.Resp.Write(bs); err != nil { - log.ErrorWithSkip(skip, "plainTextInternal (status=%d): write bytes failed: %v", status, err) - } + _, _ = b.Resp.Write(bs) } // PlainTextBytes renders bytes as plain text diff --git a/services/context/context_response.go b/services/context/context_response.go index 2f2d7b0e1b..f36b834a44 100644 --- a/services/context/context_response.go +++ b/services/context/context_response.go @@ -13,6 +13,7 @@ import ( "path" "strconv" "strings" + "syscall" "time" user_model "code.gitea.io/gitea/models/user" @@ -80,7 +81,7 @@ func (ctx *Context) HTML(status int, name base.TplName) { } err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data, ctx.TemplateContext) - if err == nil { + if err == nil || errors.Is(err, syscall.EPIPE) { return } From 6a4bc0289db5d5d791864f45ed9bb47b6bc8d2fe Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Fri, 3 May 2024 15:11:51 +0900 Subject: [PATCH 19/99] Fix no edit history after editing issue's title and content (#30814) Fix #30807 reuse functions in services (cherry picked from commit a50026e2f30897904704895362da0fb12c7e5b26) Conflicts: models/issues/issue_update.go routers/api/v1/repo/issue.go trivial context conflict because of 'allow setting the update date on issues and comments' --- models/issues/issue_update.go | 59 ----------------------------- modules/structs/pull.go | 2 +- routers/api/v1/repo/issue.go | 36 ++++++++---------- routers/api/v1/repo/pull.go | 37 +++++++++--------- tests/integration/api_issue_test.go | 4 ++ tests/integration/api_pull_test.go | 26 +++++++++---- 6 files changed, 56 insertions(+), 108 deletions(-) diff --git a/models/issues/issue_update.go b/models/issues/issue_update.go index 78e1f8e030..c3debac92e 100644 --- a/models/issues/issue_update.go +++ b/models/issues/issue_update.go @@ -450,65 +450,6 @@ func UpdateIssueMentions(ctx context.Context, issueID int64, mentions []*user_mo return nil } -// UpdateIssueByAPI updates all allowed fields of given issue. -// If the issue status is changed a statusChangeComment is returned -// similarly if the title is changed the titleChanged bool is set to true -func UpdateIssueByAPI(ctx context.Context, issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return nil, false, err - } - defer committer.Close() - - if err := issue.LoadRepo(ctx); err != nil { - return nil, false, fmt.Errorf("loadRepo: %w", err) - } - - // Reload the issue - currentIssue, err := GetIssueByID(ctx, issue.ID) - if err != nil { - return nil, false, err - } - - sess := db.GetEngine(ctx).ID(issue.ID) - cols := []string{"name", "content", "milestone_id", "priority", "deadline_unix", "is_locked"} - if issue.NoAutoTime { - cols = append(cols, "updated_unix") - sess.NoAutoTime() - } - if _, err := sess.Cols(cols...).Update(issue); err != nil { - return nil, false, err - } - - titleChanged = currentIssue.Title != issue.Title - if titleChanged { - opts := &CreateCommentOptions{ - Type: CommentTypeChangeTitle, - Doer: doer, - Repo: issue.Repo, - Issue: issue, - OldTitle: currentIssue.Title, - NewTitle: issue.Title, - } - _, err := CreateComment(ctx, opts) - if err != nil { - return nil, false, fmt.Errorf("createComment: %w", err) - } - } - - if currentIssue.IsClosed != issue.IsClosed { - statusChangeComment, err = doChangeIssueStatus(ctx, issue, doer, false) - if err != nil { - return nil, false, err - } - } - - if err := issue.AddCrossReferences(ctx, doer, true); err != nil { - return nil, false, err - } - return statusChangeComment, titleChanged, committer.Commit() -} - // UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it. func UpdateIssueDeadline(ctx context.Context, issue *Issue, deadlineUnix timeutil.TimeStamp, doer *user_model.User) (err error) { // if the deadline hasn't changed do nothing diff --git a/modules/structs/pull.go b/modules/structs/pull.go index 05a8d59633..b04def52b8 100644 --- a/modules/structs/pull.go +++ b/modules/structs/pull.go @@ -85,7 +85,7 @@ type CreatePullRequestOption struct { // EditPullRequestOption options when modify pull request type EditPullRequestOption struct { Title string `json:"title"` - Body string `json:"body"` + Body *string `json:"body"` Base string `json:"base"` Assignee string `json:"assignee"` Assignees []string `json:"assignees"` diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 35c1fdcc0c..2b4342dbd1 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -29,7 +29,6 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" - notify_service "code.gitea.io/gitea/services/notify" ) // SearchIssues searches for issues across the repositories that the user has access to @@ -809,12 +808,19 @@ func EditIssue(ctx *context.APIContext) { return } - oldTitle := issue.Title if len(form.Title) > 0 { - issue.Title = form.Title + err = issue_service.ChangeTitle(ctx, issue, ctx.Doer, form.Title) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ChangeTitle", err) + return + } } if form.Body != nil { - issue.Content = *form.Body + err = issue_service.ChangeContent(ctx, issue, ctx.Doer, *form.Body) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ChangeContent", err) + return + } } if form.Ref != nil { err = issue_service.ChangeIssueRef(ctx, issue, ctx.Doer, *form.Ref) @@ -882,24 +888,14 @@ func EditIssue(ctx *context.APIContext) { return } } - issue.IsClosed = api.StateClosed == api.StateType(*form.State) - } - statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer) - if err != nil { - if issues_model.IsErrDependenciesLeft(err) { - ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") + if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", api.StateClosed == api.StateType(*form.State)); err != nil { + if issues_model.IsErrDependenciesLeft(err) { + ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") + return + } + ctx.Error(http.StatusInternalServerError, "ChangeStatus", err) return } - ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err) - return - } - - if titleChanged { - notify_service.IssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) - } - - if statusChangeComment != nil { - notify_service.IssueChangeStatus(ctx, ctx.Doer, "", issue, statusChangeComment, issue.IsClosed) } // Refetch from database to assign some automatic values diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 852ec78ade..dbb7de6e66 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -601,12 +601,19 @@ func EditPullRequest(ctx *context.APIContext) { return } - oldTitle := issue.Title if len(form.Title) > 0 { - issue.Title = form.Title + err = issue_service.ChangeTitle(ctx, issue, ctx.Doer, form.Title) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ChangeTitle", err) + return + } } - if len(form.Body) > 0 { - issue.Content = form.Body + if form.Body != nil { + err = issue_service.ChangeContent(ctx, issue, ctx.Doer, *form.Body) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ChangeContent", err) + return + } } // Update or remove deadline if set @@ -683,24 +690,14 @@ func EditPullRequest(ctx *context.APIContext) { ctx.Error(http.StatusPreconditionFailed, "MergedPRState", "cannot change state of this pull request, it was already merged") return } - issue.IsClosed = api.StateClosed == api.StateType(*form.State) - } - statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer) - if err != nil { - if issues_model.IsErrDependenciesLeft(err) { - ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies") + if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", api.StateClosed == api.StateType(*form.State)); err != nil { + if issues_model.IsErrDependenciesLeft(err) { + ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies") + return + } + ctx.Error(http.StatusInternalServerError, "ChangeStatus", err) return } - ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err) - return - } - - if titleChanged { - notify_service.IssueChangeTitle(ctx, ctx.Doer, issue, oldTitle) - } - - if statusChangeComment != nil { - notify_service.IssueChangeStatus(ctx, ctx.Doer, "", issue, statusChangeComment, issue.IsClosed) } // change pull target branch diff --git a/tests/integration/api_issue_test.go b/tests/integration/api_issue_test.go index 849535ff8e..e6fb62a3a9 100644 --- a/tests/integration/api_issue_test.go +++ b/tests/integration/api_issue_test.go @@ -188,6 +188,10 @@ func TestAPIEditIssue(t *testing.T) { issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10}) repoAfter := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID}) + // check comment history + unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: issueAfter.ID, OldTitle: issueBefore.Title, NewTitle: title}) + unittest.AssertExistsAndLoadBean(t, &issues_model.ContentHistory{IssueID: issueAfter.ID, ContentText: body, IsFirstCreated: false}) + // check deleted user assert.Equal(t, int64(500), issueAfter.PosterID) assert.NoError(t, issueAfter.LoadAttributes(db.DefaultContext)) diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go index 21417bb77e..4f068502f7 100644 --- a/tests/integration/api_pull_test.go +++ b/tests/integration/api_pull_test.go @@ -223,23 +223,33 @@ func TestAPIEditPull(t *testing.T) { session := loginUser(t, owner10.Name) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + title := "create a success pr" req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls", owner10.Name, repo10.Name), &api.CreatePullRequestOption{ Head: "develop", Base: "master", - Title: "create a success pr", + Title: title, }).AddTokenAuth(token) - pull := new(api.PullRequest) + apiPull := new(api.PullRequest) resp := MakeRequest(t, req, http.StatusCreated) - DecodeJSON(t, resp, pull) - assert.EqualValues(t, "master", pull.Base.Name) + DecodeJSON(t, resp, apiPull) + assert.EqualValues(t, "master", apiPull.Base.Name) - req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, pull.Index), &api.EditPullRequestOption{ + newTitle := "edit a this pr" + newBody := "edited body" + req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, apiPull.Index), &api.EditPullRequestOption{ Base: "feature/1", - Title: "edit a this pr", + Title: newTitle, + Body: &newBody, }).AddTokenAuth(token) resp = MakeRequest(t, req, http.StatusCreated) - DecodeJSON(t, resp, pull) - assert.EqualValues(t, "feature/1", pull.Base.Name) + DecodeJSON(t, resp, apiPull) + assert.EqualValues(t, "feature/1", apiPull.Base.Name) + // check comment history + pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID}) + err := pull.LoadIssue(db.DefaultContext) + assert.NoError(t, err) + unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: pull.Issue.ID, OldTitle: title, NewTitle: newTitle}) + unittest.AssertExistsAndLoadBean(t, &issues_model.ContentHistory{IssueID: pull.Issue.ID, ContentText: newBody, IsFirstCreated: false}) req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, pull.Index), &api.EditPullRequestOption{ Base: "not-exist", From e388822e9dc6bfe59df06c7b2008cba517f908fc Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Fri, 3 May 2024 00:58:31 -0700 Subject: [PATCH 20/99] Don't only list code-enabled repositories when using repository API (#30817) We should be listing all repositories by default. Fixes #28483. (cherry picked from commit 9f0ef3621a3b63ccbe93f302a446b67dc54ad725) Conflict: - if ctx.IsSigned && ctx.Doer.IsAdmin || permission.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeRead { + if ctx.IsSigned && ctx.Doer.IsAdmin || permission.HasAccess() { because of https://codeberg.org/forgejo/forgejo/pulls/2001 --- routers/api/v1/user/repo.go | 4 +--- tests/integration/api_repo_test.go | 34 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index 81f8e0f3fe..9b6701b067 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -6,10 +6,8 @@ package user import ( "net/http" - "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" - unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/utils" @@ -44,7 +42,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) return } - if ctx.IsSigned && ctx.Doer.IsAdmin || permission.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeRead { + if ctx.IsSigned && ctx.Doer.IsAdmin || permission.HasAccess() { apiRepos = append(apiRepos, convert.ToRepo(ctx, repos[i], permission)) } } diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go index 96f38edc86..a503b201bc 100644 --- a/tests/integration/api_repo_test.go +++ b/tests/integration/api_repo_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/db" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" @@ -326,6 +327,39 @@ func TestAPIOrgRepos(t *testing.T) { } } +// See issue #28483. Tests to make sure we consider more than just code unit-enabled repositories. +func TestAPIOrgReposWithCodeUnitDisabled(t *testing.T) { + defer tests.PrepareTestEnv(t)() + repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "repo21"}) + org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo21.OwnerID}) + + // Disable code repository unit. + var units []unit_model.Type + units = append(units, unit_model.TypeCode) + + if err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo21, nil, units); err != nil { + assert.Fail(t, "should have been able to delete code repository unit; failed to %v", err) + } + assert.False(t, repo21.UnitEnabled(db.DefaultContext, unit_model.TypeCode)) + + session := loginUser(t, "user2") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization) + + req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org3.Name). + AddTokenAuth(token) + + resp := MakeRequest(t, req, http.StatusOK) + var apiRepos []*api.Repository + DecodeJSON(t, resp, &apiRepos) + + var repoNames []string + for _, r := range apiRepos { + repoNames = append(repoNames, r.Name) + } + + assert.Contains(t, repoNames, repo21.Name) +} + func TestAPIGetRepoByIDUnauthorized(t *testing.T) { defer tests.PrepareTestEnv(t)() user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) From 1a76664d565351898e7322c5629d6e6de44f9388 Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Tue, 7 May 2024 17:58:13 +0200 Subject: [PATCH 21/99] next step on the way to federation --- models/forgefed/federationhost.go | 52 +++++ models/forgefed/federationhost_repository.go | 61 +++++ models/forgefed/federationhost_test.go | 55 +++++ models/forgefed/nodeinfo.go | 123 ++++++++++ models/forgefed/nodeinfo_test.go | 89 ++++++++ modules/activitypub/client.go | 54 ++++- modules/activitypub/client_test.go | 77 +++++++ modules/forgefed/actor.go | 226 +++++++++++++++++++ modules/forgefed/actor_test.go | 223 ++++++++++++++++++ modules/forgefed/nodeinfo.go | 19 ++ services/federation/federation_service.go | 68 ++++++ 11 files changed, 1044 insertions(+), 3 deletions(-) create mode 100644 models/forgefed/federationhost.go create mode 100644 models/forgefed/federationhost_repository.go create mode 100644 models/forgefed/federationhost_test.go create mode 100644 models/forgefed/nodeinfo.go create mode 100644 models/forgefed/nodeinfo_test.go create mode 100644 modules/forgefed/actor.go create mode 100644 modules/forgefed/actor_test.go create mode 100644 modules/forgefed/nodeinfo.go diff --git a/models/forgefed/federationhost.go b/models/forgefed/federationhost.go new file mode 100644 index 0000000000..eb1183a2a7 --- /dev/null +++ b/models/forgefed/federationhost.go @@ -0,0 +1,52 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "fmt" + "strings" + "time" + + "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/validation" +) + +// FederationHost data type +// swagger:model +type FederationHost struct { + ID int64 `xorm:"pk autoincr"` + HostFqdn string `xorm:"host_fqdn UNIQUE INDEX VARCHAR(255) NOT NULL"` + NodeInfo NodeInfo `xorm:"extends NOT NULL"` + LatestActivity time.Time `xorm:"NOT NULL"` + Create timeutil.TimeStamp `xorm:"created"` + Updated timeutil.TimeStamp `xorm:"updated"` +} + +// Factory function for PersonID. Created struct is asserted to be valid +func NewFederationHost(nodeInfo NodeInfo, hostFqdn string) (FederationHost, error) { + result := FederationHost{ + HostFqdn: strings.ToLower(hostFqdn), + NodeInfo: nodeInfo, + } + if valid, err := validation.IsValid(result); !valid { + return FederationHost{}, err + } + return result, nil +} + +// Validate collects error strings in a slice and returns this +func (host FederationHost) Validate() []string { + var result []string + result = append(result, validation.ValidateNotEmpty(host.HostFqdn, "HostFqdn")...) + result = append(result, validation.ValidateMaxLen(host.HostFqdn, 255, "HostFqdn")...) + result = append(result, host.NodeInfo.Validate()...) + if host.HostFqdn != strings.ToLower(host.HostFqdn) { + result = append(result, fmt.Sprintf("HostFqdn has to be lower case but was: %v", host.HostFqdn)) + } + if !host.LatestActivity.IsZero() && host.LatestActivity.After(time.Now().Add(10*time.Minute)) { + result = append(result, fmt.Sprintf("Latest Activity may not be far futurer: %v", host.LatestActivity)) + } + + return result +} diff --git a/models/forgefed/federationhost_repository.go b/models/forgefed/federationhost_repository.go new file mode 100644 index 0000000000..b4e72b0ce1 --- /dev/null +++ b/models/forgefed/federationhost_repository.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "context" + "fmt" + "strings" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/validation" +) + +func init() { + db.RegisterModel(new(FederationHost)) +} + +func GetFederationHost(ctx context.Context, ID int64) (*FederationHost, error) { + host := new(FederationHost) + has, err := db.GetEngine(ctx).Where("id=?", ID).Get(host) + if err != nil { + return nil, err + } else if !has { + return nil, fmt.Errorf("FederationInfo record %v does not exist", ID) + } + if res, err := validation.IsValid(host); !res { + return nil, fmt.Errorf("FederationInfo is not valid: %v", err) + } + return host, nil +} + +func FindFederationHostByFqdn(ctx context.Context, fqdn string) (*FederationHost, error) { + host := new(FederationHost) + has, err := db.GetEngine(ctx).Where("host_fqdn=?", strings.ToLower(fqdn)).Get(host) + if err != nil { + return nil, err + } else if !has { + return nil, nil + } + if res, err := validation.IsValid(host); !res { + return nil, fmt.Errorf("FederationInfo is not valid: %v", err) + } + return host, nil +} + +func CreateFederationHost(ctx context.Context, host *FederationHost) error { + if res, err := validation.IsValid(host); !res { + return fmt.Errorf("FederationInfo is not valid: %v", err) + } + _, err := db.GetEngine(ctx).Insert(host) + return err +} + +func UpdateFederationHost(ctx context.Context, host *FederationHost) error { + if res, err := validation.IsValid(host); !res { + return fmt.Errorf("FederationInfo is not valid: %v", err) + } + _, err := db.GetEngine(ctx).ID(host.ID).Update(host) + return err +} diff --git a/models/forgefed/federationhost_test.go b/models/forgefed/federationhost_test.go new file mode 100644 index 0000000000..04f941d93d --- /dev/null +++ b/models/forgefed/federationhost_test.go @@ -0,0 +1,55 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "testing" + "time" + + "code.gitea.io/gitea/modules/validation" +) + +func Test_FederationHostValidation(t *testing.T) { + sut := FederationHost{ + HostFqdn: "host.do.main", + NodeInfo: NodeInfo{ + SoftwareName: "forgejo", + }, + LatestActivity: time.Now(), + } + if res, err := validation.IsValid(sut); !res { + t.Errorf("sut should be valid but was %q", err) + } + + sut = FederationHost{ + HostFqdn: "host.do.main", + NodeInfo: NodeInfo{}, + LatestActivity: time.Now(), + } + if res, _ := validation.IsValid(sut); res { + t.Errorf("sut should be invalid") + } + + sut = FederationHost{ + HostFqdn: "host.do.main", + NodeInfo: NodeInfo{ + SoftwareName: "forgejo", + }, + LatestActivity: time.Now().Add(1 * time.Hour), + } + if res, _ := validation.IsValid(sut); res { + t.Errorf("sut should be invalid: Future timestamp") + } + + sut = FederationHost{ + HostFqdn: "hOst.do.main", + NodeInfo: NodeInfo{ + SoftwareName: "forgejo", + }, + LatestActivity: time.Now(), + } + if res, _ := validation.IsValid(sut); res { + t.Errorf("sut should be invalid: HostFqdn lower case") + } +} diff --git a/models/forgefed/nodeinfo.go b/models/forgefed/nodeinfo.go new file mode 100644 index 0000000000..bb56570635 --- /dev/null +++ b/models/forgefed/nodeinfo.go @@ -0,0 +1,123 @@ +// Copyright 2023 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "net/url" + + "code.gitea.io/gitea/modules/validation" + + "github.com/valyala/fastjson" +) + +// ToDo: Search for full text SourceType and Source, also in .md files +type ( + SoftwareNameType string +) + +const ( + ForgejoSourceType SoftwareNameType = "forgejo" + GiteaSourceType SoftwareNameType = "gitea" +) + +var KnownSourceTypes = []any{ + ForgejoSourceType, GiteaSourceType, +} + +// ------------------------------------------------ NodeInfoWellKnown ------------------------------------------------ + +// NodeInfo data type +// swagger:model +type NodeInfoWellKnown struct { + Href string +} + +// Factory function for PersonID. Created struct is asserted to be valid +func NewNodeInfoWellKnown(body []byte) (NodeInfoWellKnown, error) { + result, err := NodeInfoWellKnownUnmarshalJSON(body) + if err != nil { + return NodeInfoWellKnown{}, err + } + + if valid, err := validation.IsValid(result); !valid { + return NodeInfoWellKnown{}, err + } + + return result, nil +} + +func NodeInfoWellKnownUnmarshalJSON(data []byte) (NodeInfoWellKnown, error) { + p := fastjson.Parser{} + val, err := p.ParseBytes(data) + if err != nil { + return NodeInfoWellKnown{}, err + } + href := string(val.GetStringBytes("links", "0", "href")) + return NodeInfoWellKnown{Href: href}, nil +} + +// Validate collects error strings in a slice and returns this +func (node NodeInfoWellKnown) Validate() []string { + var result []string + result = append(result, validation.ValidateNotEmpty(node.Href, "Href")...) + + parsedURL, err := url.Parse(node.Href) + if err != nil { + result = append(result, err.Error()) + return result + } + + if parsedURL.Host == "" { + result = append(result, "Href has to be absolute") + } + + result = append(result, validation.ValidateOneOf(parsedURL.Scheme, []any{"http", "https"}, "parsedURL.Scheme")...) + + if parsedURL.RawQuery != "" { + result = append(result, "Href may not contain query") + } + + return result +} + +// ------------------------------------------------ NodeInfo ------------------------------------------------ + +// NodeInfo data type +// swagger:model +type NodeInfo struct { + SoftwareName SoftwareNameType +} + +func NodeInfoUnmarshalJSON(data []byte) (NodeInfo, error) { + p := fastjson.Parser{} + val, err := p.ParseBytes(data) + if err != nil { + return NodeInfo{}, err + } + source := string(val.GetStringBytes("software", "name")) + result := NodeInfo{} + result.SoftwareName = SoftwareNameType(source) + return result, nil +} + +func NewNodeInfo(body []byte) (NodeInfo, error) { + result, err := NodeInfoUnmarshalJSON(body) + if err != nil { + return NodeInfo{}, err + } + + if valid, err := validation.IsValid(result); !valid { + return NodeInfo{}, err + } + return result, nil +} + +// Validate collects error strings in a slice and returns this +func (node NodeInfo) Validate() []string { + var result []string + result = append(result, validation.ValidateNotEmpty(string(node.SoftwareName), "node.SoftwareName")...) + result = append(result, validation.ValidateOneOf(node.SoftwareName, KnownSourceTypes, "node.SoftwareName")...) + + return result +} diff --git a/models/forgefed/nodeinfo_test.go b/models/forgefed/nodeinfo_test.go new file mode 100644 index 0000000000..ba1bd90be8 --- /dev/null +++ b/models/forgefed/nodeinfo_test.go @@ -0,0 +1,89 @@ +// Copyright 2023 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "fmt" + "reflect" + "testing" + + "code.gitea.io/gitea/modules/validation" +) + +func Test_NodeInfoWellKnownUnmarshalJSON(t *testing.T) { + type testPair struct { + item []byte + want NodeInfoWellKnown + wantErr error + } + + tests := map[string]testPair{ + "with href": { + item: []byte(`{"links":[{"href":"https://federated-repo.prod.meissa.de/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`), + want: NodeInfoWellKnown{ + Href: "https://federated-repo.prod.meissa.de/api/v1/nodeinfo", + }, + }, + "empty": { + item: []byte(``), + wantErr: fmt.Errorf("cannot parse JSON: cannot parse empty string; unparsed tail: \"\""), + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + got, err := NodeInfoWellKnownUnmarshalJSON(tt.item) + if (err != nil || tt.wantErr != nil) && tt.wantErr.Error() != err.Error() { + t.Errorf("UnmarshalJSON() error = \"%v\", wantErr \"%v\"", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("UnmarshalJSON() got = %q, want %q", got, tt.want) + } + }) + } +} + +func Test_NodeInfoWellKnownValidate(t *testing.T) { + sut := NodeInfoWellKnown{Href: "https://federated-repo.prod.meissa.de/api/v1/nodeinfo"} + if b, err := validation.IsValid(sut); !b { + t.Errorf("sut should be valid, %v, %v", sut, err) + } + + sut = NodeInfoWellKnown{Href: "./federated-repo.prod.meissa.de/api/v1/nodeinfo"} + if _, err := validation.IsValid(sut); err.Error() != "Href has to be absolute\nValue is not contained in allowed values [http https]" { + t.Errorf("validation error expected but was: %v\n", err) + } + + sut = NodeInfoWellKnown{Href: "https://federated-repo.prod.meissa.de/api/v1/nodeinfo?alert=1"} + if _, err := validation.IsValid(sut); err.Error() != "Href may not contain query" { + t.Errorf("sut should be valid, %v, %v", sut, err) + } +} + +func Test_NewNodeInfoWellKnown(t *testing.T) { + sut, _ := NewNodeInfoWellKnown([]byte(`{"links":[{"href":"https://federated-repo.prod.meissa.de/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`)) + expected := NodeInfoWellKnown{Href: "https://federated-repo.prod.meissa.de/api/v1/nodeinfo"} + if sut != expected { + t.Errorf("expected was: %v but was: %v", expected, sut) + } + + _, err := NewNodeInfoWellKnown([]byte(`invalid`)) + if err == nil { + t.Errorf("error was expected here") + } +} + +func Test_NewNodeInfo(t *testing.T) { + sut, _ := NewNodeInfo([]byte(`{"version":"2.1","software":{"name":"gitea","version":"1.20.0+dev-2539-g5840cc6d3","repository":"https://github.com/go-gitea/gitea.git","homepage":"https://gitea.io/"},"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},"openRegistrations":true,"usage":{"users":{"total":13,"activeHalfyear":1,"activeMonth":1}},"metadata":{}}`)) + expected := NodeInfo{SoftwareName: "gitea"} + if sut != expected { + t.Errorf("expected was: %v but was: %v", expected, sut) + } + + _, err := NewNodeInfo([]byte(`invalid`)) + if err == nil { + t.Errorf("error was expected here") + } +} diff --git a/modules/activitypub/client.go b/modules/activitypub/client.go index 66b977c01f..4962ad79a4 100644 --- a/modules/activitypub/client.go +++ b/modules/activitypub/client.go @@ -1,6 +1,8 @@ // Copyright 2022 The Gitea Authors. All rights reserved. +// Copyright 2024 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT +// TODO: Think about whether this should be moved to services/activitypub (compare to exosy/services/activitypub/client.go) package activitypub import ( @@ -10,11 +12,13 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "io" "net/http" "strings" "time" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/setting" @@ -84,6 +88,7 @@ func NewClient(ctx context.Context, user *user_model.User, pubID string) (c *Cli Transport: &http.Transport{ Proxy: proxy.Proxy(), }, + Timeout: 5 * time.Second, }, algs: setting.HttpsigAlgs, digestAlg: httpsig.DigestAlgorithm(setting.Federation.DigestAlgorithm), @@ -96,9 +101,9 @@ func NewClient(ctx context.Context, user *user_model.User, pubID string) (c *Cli } // NewRequest function -func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error) { +func (c *Client) NewRequest(method string, b []byte, to string) (req *http.Request, err error) { buf := bytes.NewBuffer(b) - req, err = http.NewRequest(http.MethodPost, to, buf) + req, err = http.NewRequest(method, to, buf) if err != nil { return nil, err } @@ -116,9 +121,52 @@ func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error) // Post function func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) { var req *http.Request - if req, err = c.NewRequest(b, to); err != nil { + if req, err = c.NewRequest(http.MethodPost, b, to); err != nil { return nil, err } resp, err = c.client.Do(req) return resp, err } + +// Create an http GET request with forgejo/gitea specific headers +func (c *Client) Get(to string) (resp *http.Response, err error) { // ToDo: we might not need the b parameter + var req *http.Request + emptyBody := []byte{0} + if req, err = c.NewRequest(http.MethodGet, emptyBody, to); err != nil { + return nil, err + } + resp, err = c.client.Do(req) + return resp, err +} + +// Create an http GET request with forgejo/gitea specific headers +func (c *Client) GetBody(uri string) ([]byte, error) { + response, err := c.Get(uri) + if err != nil { + return nil, err + } + log.Debug("Client: got status: %v", response.Status) + if response.StatusCode != 200 { + err = fmt.Errorf("got non 200 status code for id: %v", uri) + return nil, err + } + defer response.Body.Close() + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + log.Debug("Client: got body: %v", charLimiter(string(body), 120)) + return body, nil +} + +// Limit number of characters in a string (useful to prevent log injection attacks and overly long log outputs) +// Thanks to https://www.socketloop.com/tutorials/golang-characters-limiter-example +func charLimiter(s string, limit int) string { + reader := strings.NewReader(s) + buff := make([]byte, limit) + n, _ := io.ReadAtLeast(reader, buff, limit) + if n != 0 { + return fmt.Sprint(string(buff), "...") + } + return s +} diff --git a/modules/activitypub/client_test.go b/modules/activitypub/client_test.go index 65ea8d4d5b..2ef16fcdf5 100644 --- a/modules/activitypub/client_test.go +++ b/modules/activitypub/client_test.go @@ -1,4 +1,5 @@ // Copyright 2022 The Gitea Authors. All rights reserved. +// Copyright 2023 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package activitypub @@ -14,11 +15,87 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" + + _ "github.com/mattn/go-sqlite3" ) +/* ToDo: Set Up tests for http get requests + +Set up an expected response for GET on api with user-id = 1: +{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1" + ], + "id": "http://localhost:3000/api/v1/activitypub/user-id/1", + "type": "Person", + "icon": { + "type": "Image", + "mediaType": "image/png", + "url": "http://localhost:3000/avatar/3120fd0edc57d5d41230013ad88232e2" + }, + "url": "http://localhost:3000/me", + "inbox": "http://localhost:3000/api/v1/activitypub/user-id/1/inbox", + "outbox": "http://localhost:3000/api/v1/activitypub/user-id/1/outbox", + "preferredUsername": "me", + "publicKey": { + "id": "http://localhost:3000/api/v1/activitypub/user-id/1#main-key", + "owner": "http://localhost:3000/api/v1/activitypub/user-id/1", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAo1VDZGWQBDTWKhpWiPQp\n7nD94UsKkcoFwDQVuxE3bMquKEHBomB4cwUnVou922YkL3AmSOr1sX2yJQGqnCLm\nOeKS74/mCIAoYlu0d75bqY4A7kE2VrQmQLZBbmpCTfrPqDaE6Mfm/kXaX7+hsrZS\n4bVvzZCYq8sjtRxdPk+9ku2QhvznwTRlWLvwHmFSGtlQYPRu+f/XqoVM/DVRA/Is\nwDk9yiNIecV+Isus0CBq1jGQkfuVNu1GK2IvcSg9MoDm3VH/tCayAP+xWm0g7sC8\nKay6Y/khvTvE7bWEKGQsJGvi3+4wITLVLVt+GoVOuCzdbhTV2CHBzn7h30AoZD0N\nY6eyb+Q142JykoHadcRwh1a36wgoG7E496wPvV3ST8xdiClca8cDNhOzCj8woY+t\nTFCMl32U3AJ4e/cAsxKRocYLZqc95dDqdNQiIyiRMMkf5NaA/QvelY4PmFuHC0WR\nVuJ4A3mcti2QLS9j0fSwSJdlfolgW6xaPgjdvuSQsgX1AgMBAAE=\n-----END PUBLIC KEY-----\n" + } +} + +Set up a user called "me" for all tests + + + +*/ + +func TestNewClientReturnsClient(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + pubID := "myGpgId" + c, err := NewClient(db.DefaultContext, user, pubID) + + log.Debug("Client: %v\nError: %v", c, err) + assert.NoError(t, err) +} + +/* TODO: bring this test to work or delete +func TestActivityPubSignedGet(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1, Name: "me"}) + pubID := "myGpgId" + c, err := NewClient(db.DefaultContext, user, pubID) + assert.NoError(t, err) + + expected := "TestActivityPubSignedGet" + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Regexp(t, regexp.MustCompile("^"+setting.Federation.DigestAlgorithm), r.Header.Get("Digest")) + assert.Contains(t, r.Header.Get("Signature"), pubID) + assert.Equal(t, r.Header.Get("Content-Type"), ActivityStreamsContentType) + body, err := io.ReadAll(r.Body) + assert.NoError(t, err) + assert.Equal(t, expected, string(body)) + fmt.Fprint(w, expected) + })) + defer srv.Close() + + r, err := c.Get(srv.URL) + assert.NoError(t, err) + defer r.Body.Close() + body, err := io.ReadAll(r.Body) + assert.NoError(t, err) + assert.Equal(t, expected, string(body)) + +} +*/ + func TestActivityPubSignedPost(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) diff --git a/modules/forgefed/actor.go b/modules/forgefed/actor.go new file mode 100644 index 0000000000..a34abc2075 --- /dev/null +++ b/modules/forgefed/actor.go @@ -0,0 +1,226 @@ +// Copyright 2023, 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "fmt" + "net/url" + "strings" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/validation" + + ap "github.com/go-ap/activitypub" +) + +// ----------------------------- ActorID -------------------------------------------- +type ActorID struct { + ID string + Source string + Schema string + Path string + Host string + Port string + UnvalidatedInput string +} + +// Factory function for ActorID. Created struct is asserted to be valid +func NewActorID(uri string) (ActorID, error) { + result, err := newActorID(uri) + if err != nil { + return ActorID{}, err + } + + if valid, outcome := validation.IsValid(result); !valid { + return ActorID{}, outcome + } + + return result, nil +} + +func (id ActorID) AsURI() string { + var result string + if id.Port == "" { + result = fmt.Sprintf("%s://%s/%s/%s", id.Schema, id.Host, id.Path, id.ID) + } else { + result = fmt.Sprintf("%s://%s:%s/%s/%s", id.Schema, id.Host, id.Port, id.Path, id.ID) + } + return result +} + +func (id ActorID) Validate() []string { + var result []string + result = append(result, validation.ValidateNotEmpty(id.ID, "userId")...) + result = append(result, validation.ValidateNotEmpty(id.Schema, "schema")...) + result = append(result, validation.ValidateNotEmpty(id.Path, "path")...) + result = append(result, validation.ValidateNotEmpty(id.Host, "host")...) + result = append(result, validation.ValidateNotEmpty(id.UnvalidatedInput, "unvalidatedInput")...) + + if id.UnvalidatedInput != id.AsURI() { + result = append(result, fmt.Sprintf("not all input was parsed, \nUnvalidated Input:%q \nParsed URI: %q", id.UnvalidatedInput, id.AsURI())) + } + + return result +} + +// ----------------------------- PersonID -------------------------------------------- +type PersonID struct { + ActorID +} + +// Factory function for PersonID. Created struct is asserted to be valid +func NewPersonID(uri, source string) (PersonID, error) { + // TODO: remove after test + //if !validation.IsValidExternalURL(uri) { + // return PersonId{}, fmt.Errorf("uri %s is not a valid external url", uri) + //} + result, err := newActorID(uri) + if err != nil { + return PersonID{}, err + } + result.Source = source + + // validate Person specific path + personID := PersonID{result} + if valid, outcome := validation.IsValid(personID); !valid { + return PersonID{}, outcome + } + + return personID, nil +} + +func (id PersonID) AsWebfinger() string { + result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host)) + return result +} + +func (id PersonID) AsLoginName() string { + result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix()) + return result +} + +func (id PersonID) HostSuffix() string { + result := fmt.Sprintf("-%s", strings.ToLower(id.Host)) + return result +} + +func (id PersonID) Validate() []string { + result := id.ActorID.Validate() + result = append(result, validation.ValidateNotEmpty(id.Source, "source")...) + result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...) + switch id.Source { + case "forgejo", "gitea": + if strings.ToLower(id.Path) != "api/v1/activitypub/user-id" && strings.ToLower(id.Path) != "api/activitypub/user-id" { + result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path)) + } + } + return result +} + +// ----------------------------- RepositoryID -------------------------------------------- + +type RepositoryID struct { + ActorID +} + +// Factory function for RepositoryID. Created struct is asserted to be valid. +func NewRepositoryID(uri, source string) (RepositoryID, error) { + if !validation.IsAPIURL(uri) { + return RepositoryID{}, fmt.Errorf("uri %s is not a valid repo url on this host %s", uri, setting.AppURL+"api") + } + result, err := newActorID(uri) + if err != nil { + return RepositoryID{}, err + } + result.Source = source + + // validate Person specific path + repoID := RepositoryID{result} + if valid, outcome := validation.IsValid(repoID); !valid { + return RepositoryID{}, outcome + } + + return repoID, nil +} + +func (id RepositoryID) Validate() []string { + result := id.ActorID.Validate() + result = append(result, validation.ValidateNotEmpty(id.Source, "source")...) + result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...) + switch id.Source { + case "forgejo", "gitea": + if strings.ToLower(id.Path) != "api/v1/activitypub/repository-id" && strings.ToLower(id.Path) != "api/activitypub/repository-id" { + result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path)) + } + } + return result +} + +func containsEmptyString(ar []string) bool { + for _, elem := range ar { + if elem == "" { + return true + } + } + return false +} + +func removeEmptyStrings(ls []string) []string { + var rs []string + for _, str := range ls { + if str != "" { + rs = append(rs, str) + } + } + return rs +} + +func newActorID(uri string) (ActorID, error) { + validatedURI, err := url.ParseRequestURI(uri) + if err != nil { + return ActorID{}, err + } + pathWithActorID := strings.Split(validatedURI.Path, "/") + if containsEmptyString(pathWithActorID) { + pathWithActorID = removeEmptyStrings(pathWithActorID) + } + length := len(pathWithActorID) + pathWithoutActorID := strings.Join(pathWithActorID[0:length-1], "/") + id := pathWithActorID[length-1] + + result := ActorID{} + result.ID = id + result.Schema = validatedURI.Scheme + result.Host = validatedURI.Hostname() + result.Path = pathWithoutActorID + result.Port = validatedURI.Port() + result.UnvalidatedInput = uri + return result, nil +} + +// ----------------------------- ForgePerson ------------------------------------- + +// ForgePerson activity data type +// swagger:model +type ForgePerson struct { + // swagger:ignore + ap.Actor +} + +func (s ForgePerson) MarshalJSON() ([]byte, error) { + return s.Actor.MarshalJSON() +} + +func (s *ForgePerson) UnmarshalJSON(data []byte) error { + return s.Actor.UnmarshalJSON(data) +} + +func (s ForgePerson) Validate() []string { + var result []string + result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...) + result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...) + result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...) + + return result +} diff --git a/modules/forgefed/actor_test.go b/modules/forgefed/actor_test.go new file mode 100644 index 0000000000..9a1dbd4c3d --- /dev/null +++ b/modules/forgefed/actor_test.go @@ -0,0 +1,223 @@ +// Copyright 2023, 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "reflect" + "strings" + "testing" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/validation" + + ap "github.com/go-ap/activitypub" +) + +func TestNewPersonId(t *testing.T) { + expected := PersonID{} + expected.ID = "1" + expected.Source = "forgejo" + expected.Schema = "https" + expected.Path = "api/v1/activitypub/user-id" + expected.Host = "an.other.host" + expected.Port = "" + expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1" + sut, _ := NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") + if sut != expected { + t.Errorf("expected: %v\n but was: %v\n", expected, sut) + } + + expected = PersonID{} + expected.ID = "1" + expected.Source = "forgejo" + expected.Schema = "https" + expected.Path = "api/v1/activitypub/user-id" + expected.Host = "an.other.host" + expected.Port = "443" + expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1" + sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo") + if sut != expected { + t.Errorf("expected: %v\n but was: %v\n", expected, sut) + } +} + +func TestNewRepositoryId(t *testing.T) { + setting.AppURL = "http://localhost:3000/" + expected := RepositoryID{} + expected.ID = "1" + expected.Source = "forgejo" + expected.Schema = "http" + expected.Path = "api/activitypub/repository-id" + expected.Host = "localhost" + expected.Port = "3000" + expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1" + sut, _ := NewRepositoryID("http://localhost:3000/api/activitypub/repository-id/1", "forgejo") + if sut != expected { + t.Errorf("expected: %v\n but was: %v\n", expected, sut) + } +} + +func TestActorIdValidation(t *testing.T) { + sut := ActorID{} + sut.Source = "forgejo" + sut.Schema = "https" + sut.Path = "api/v1/activitypub/user-id" + sut.Host = "an.other.host" + sut.Port = "" + sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/" + if sut.Validate()[0] != "userId should not be empty" { + t.Errorf("validation error expected but was: %v\n", sut.Validate()) + } + + sut = ActorID{} + sut.ID = "1" + sut.Source = "forgejo" + sut.Schema = "https" + sut.Path = "api/v1/activitypub/user-id" + sut.Host = "an.other.host" + sut.Port = "" + sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action" + if sut.Validate()[0] != "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"" { + t.Errorf("validation error expected but was: %v\n", sut.Validate()[0]) + } +} + +func TestPersonIdValidation(t *testing.T) { + sut := PersonID{} + sut.ID = "1" + sut.Source = "forgejo" + sut.Schema = "https" + sut.Path = "path" + sut.Host = "an.other.host" + sut.Port = "" + sut.UnvalidatedInput = "https://an.other.host/path/1" + if _, err := validation.IsValid(sut); err.Error() != "path: \"path\" has to be a person specific api path" { + t.Errorf("validation error expected but was: %v\n", err) + } + + sut = PersonID{} + sut.ID = "1" + sut.Source = "forgejox" + sut.Schema = "https" + sut.Path = "api/v1/activitypub/user-id" + sut.Host = "an.other.host" + sut.Port = "" + sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1" + if sut.Validate()[0] != "Value forgejox is not contained in allowed values [forgejo gitea]" { + t.Errorf("validation error expected but was: %v\n", sut.Validate()[0]) + } +} + +func TestWebfingerId(t *testing.T) { + sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") + if sut.AsWebfinger() != "@12345@codeberg.org" { + t.Errorf("wrong webfinger: %v", sut.AsWebfinger()) + } + + sut, _ = NewPersonID("https://Codeberg.org/api/v1/activitypub/user-id/12345", "forgejo") + if sut.AsWebfinger() != "@12345@codeberg.org" { + t.Errorf("wrong webfinger: %v", sut.AsWebfinger()) + } +} + +func TestShouldThrowErrorOnInvalidInput(t *testing.T) { + var err any + // TODO: remove after test + //_, err = NewPersonId("", "forgejo") + //if err == nil { + // t.Errorf("empty input should be invalid.") + //} + + _, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo") + if err == nil { + t.Errorf("localhost uris are not external") + } + _, err = NewPersonID("./api/v1/something", "forgejo") + if err == nil { + t.Errorf("relative uris are not allowed") + } + _, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo") + if err == nil { + t.Errorf("uri may not be ip-4 based") + } + _, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo") + if err == nil { + t.Errorf("uri may not be ip-6 based") + } + _, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo") + if err == nil { + t.Errorf("uri may not contain relative path elements") + } + _, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo") + if err == nil { + t.Errorf("uri may not contain unparsed elements") + } + + _, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo") + if err != nil { + t.Errorf("this uri should be valid but was: %v", err) + } +} + +func Test_PersonMarshalJSON(t *testing.T) { + sut := ForgePerson{} + sut.Type = "Person" + sut.PreferredUsername = ap.NaturalLanguageValuesNew() + sut.PreferredUsername.Set("en", ap.Content("MaxMuster")) + result, _ := sut.MarshalJSON() + if string(result) != "{\"type\":\"Person\",\"preferredUsername\":\"MaxMuster\"}" { + t.Errorf("MarshalJSON() was = %q", result) + } +} + +func Test_PersonUnmarshalJSON(t *testing.T) { + expected := &ForgePerson{ + Actor: ap.Actor{ + Type: "Person", + PreferredUsername: ap.NaturalLanguageValues{ + ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")}, + }, + }, + } + sut := new(ForgePerson) + err := sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`)) + if err != nil { + t.Errorf("UnmarshalJSON() unexpected error: %v", err) + } + x, _ := expected.MarshalJSON() + y, _ := sut.MarshalJSON() + if !reflect.DeepEqual(x, y) { + t.Errorf("UnmarshalJSON() expected: %q got: %q", x, y) + } + + expectedStr := strings.ReplaceAll(strings.ReplaceAll(`{ + "id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10", + "type":"Person", + "icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatar/fa7f9c4af2a64f41b1bef292bf872614"}, + "url":"https://federated-repo.prod.meissa.de/stargoose9", + "inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/inbox", + "outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/outbox", + "preferredUsername":"stargoose9", + "publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10#main-key", + "owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10", + "publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBoj...XAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`, + "\n", ""), + "\t", "") + err = sut.UnmarshalJSON([]byte(expectedStr)) + if err != nil { + t.Errorf("UnmarshalJSON() unexpected error: %v", err) + } + result, _ := sut.MarshalJSON() + if expectedStr != string(result) { + t.Errorf("UnmarshalJSON() expected: %q got: %q", expectedStr, result) + } +} + +func TestForgePersonValidation(t *testing.T) { + sut := new(ForgePerson) + sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`)) + if res, _ := validation.IsValid(sut); !res { + t.Errorf("sut expected to be valid: %v\n", sut.Validate()) + } +} diff --git a/modules/forgefed/nodeinfo.go b/modules/forgefed/nodeinfo.go new file mode 100644 index 0000000000..b22d2959d4 --- /dev/null +++ b/modules/forgefed/nodeinfo.go @@ -0,0 +1,19 @@ +// Copyright 2023 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package forgefed + +import ( + "fmt" +) + +func (id ActorID) AsWellKnownNodeInfoURI() string { + wellKnownPath := ".well-known/nodeinfo" + var result string + if id.Port == "" { + result = fmt.Sprintf("%s://%s/%s", id.Schema, id.Host, wellKnownPath) + } else { + result = fmt.Sprintf("%s://%s:%s/%s", id.Schema, id.Host, id.Port, wellKnownPath) + } + return result +} diff --git a/services/federation/federation_service.go b/services/federation/federation_service.go index 478b00df96..5aba8b38c5 100644 --- a/services/federation/federation_service.go +++ b/services/federation/federation_service.go @@ -5,8 +5,12 @@ package federation import ( "context" + "fmt" "net/http" + "code.gitea.io/gitea/models/forgefed" + "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/activitypub" fm "code.gitea.io/gitea/modules/forgefed" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/validation" @@ -26,5 +30,69 @@ func ProcessLikeActivity(ctx context.Context, form any, repositoryID int64) (int } log.Info("Activity validated:%v", activity) + // parse actorID (person) + actorURI := activity.Actor.GetID().String() + log.Info("actorURI was: %v", actorURI) + federationHost, err := GetFederationHostForURI(ctx, actorURI) + if err != nil { + return http.StatusInternalServerError, "Wrong FederationHost", err + } + if !activity.IsNewer(federationHost.LatestActivity) { + return http.StatusNotAcceptable, "Activity out of order.", fmt.Errorf("Activity already processed") + } + return 0, "", nil } + +func CreateFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forgefed.FederationHost, error) { + actionsUser := user.NewActionsUser() + client, err := activitypub.NewClient(ctx, actionsUser, "no idea where to get key material.") + if err != nil { + return nil, err + } + body, err := client.GetBody(actorID.AsWellKnownNodeInfoURI()) + if err != nil { + return nil, err + } + nodeInfoWellKnown, err := forgefed.NewNodeInfoWellKnown(body) + if err != nil { + return nil, err + } + body, err = client.GetBody(nodeInfoWellKnown.Href) + if err != nil { + return nil, err + } + nodeInfo, err := forgefed.NewNodeInfo(body) + if err != nil { + return nil, err + } + result, err := forgefed.NewFederationHost(nodeInfo, actorID.Host) + if err != nil { + return nil, err + } + err = forgefed.CreateFederationHost(ctx, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func GetFederationHostForURI(ctx context.Context, actorURI string) (*forgefed.FederationHost, error) { + log.Info("Input was: %v", actorURI) + rawActorID, err := fm.NewActorID(actorURI) + if err != nil { + return nil, err + } + federationHost, err := forgefed.FindFederationHostByFqdn(ctx, rawActorID.Host) + if err != nil { + return nil, err + } + if federationHost == nil { + result, err := CreateFederationHostFromAP(ctx, rawActorID) + if err != nil { + return nil, err + } + federationHost = result + } + return federationHost, nil +} From 778dd81615e1325a92f3d1bf06081718c9009605 Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Tue, 7 May 2024 18:40:27 +0200 Subject: [PATCH 22/99] unused code of the moment --- .deadcode-out | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.deadcode-out b/.deadcode-out index f22a9df101..723b357918 100644 --- a/.deadcode-out +++ b/.deadcode-out @@ -43,6 +43,10 @@ package "code.gitea.io/gitea/models/dbfs" func Create func Rename +package "code.gitea.io/gitea/models/forgefed" + func GetFederationHost + func UpdateFederationHost + package "code.gitea.io/gitea/models/forgejo/semver" func GetVersion func SetVersionString @@ -134,12 +138,7 @@ package "code.gitea.io/gitea/models/user" func GetUserNamesByIDs package "code.gitea.io/gitea/modules/activitypub" - func CurrentTime - func containsRequiredHTTPHeaders - func NewClient - func (*Client).NewRequest func (*Client).Post - func GetPrivateKey package "code.gitea.io/gitea/modules/assetfs" func Bindata @@ -170,6 +169,16 @@ package "code.gitea.io/gitea/modules/eventsource" package "code.gitea.io/gitea/modules/forgefed" func NewForgeLike + func NewPersonID + func (PersonID).AsWebfinger + func (PersonID).AsLoginName + func (PersonID).HostSuffix + func (PersonID).Validate + func NewRepositoryID + func (RepositoryID).Validate + func (ForgePerson).MarshalJSON + func (*ForgePerson).UnmarshalJSON + func (ForgePerson).Validate func GetItemByType func JSONUnmarshalerFn func NotEmpty @@ -310,9 +319,6 @@ package "code.gitea.io/gitea/modules/translation" package "code.gitea.io/gitea/modules/util/filebuffer" func CreateFromReader -package "code.gitea.io/gitea/modules/validation" - func ValidateMaxLen - package "code.gitea.io/gitea/modules/web" func RouteMock func RouteMockReset From 84224a65ff927e8c9c5f92c1a032b848f53366ee Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 8 May 2024 02:05:00 +0000 Subject: [PATCH 23/99] Update dependency @vue/test-utils to v2.4.6 --- 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 3343267029..0930a4dab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,7 +70,7 @@ "@stylistic/eslint-plugin-js": "1.8.0", "@stylistic/stylelint-plugin": "2.1.2", "@vitejs/plugin-vue": "5.0.4", - "@vue/test-utils": "2.4.5", + "@vue/test-utils": "2.4.6", "eslint": "8.57.0", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "4.10.2", @@ -2766,9 +2766,9 @@ "integrity": "sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==" }, "node_modules/@vue/test-utils": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.5.tgz", - "integrity": "sha512-oo2u7vktOyKUked36R93NB7mg2B+N7Plr8lxp2JBGwr18ch6EggFjixSCdIVVLkT6Qr0z359Xvnafc9dcKyDUg==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", "dev": true, "dependencies": { "js-beautify": "^1.14.9", diff --git a/package.json b/package.json index 4929af94dd..0c286e4c8f 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "@stylistic/eslint-plugin-js": "1.8.0", "@stylistic/stylelint-plugin": "2.1.2", "@vitejs/plugin-vue": "5.0.4", - "@vue/test-utils": "2.4.5", + "@vue/test-utils": "2.4.6", "eslint": "8.57.0", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "4.10.2", From b11eddfaa83b1d27b864c50de1c82dbbcb293f4f Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Wed, 8 May 2024 08:58:25 +0500 Subject: [PATCH 24/99] [I18N] English improvements (May 2024) - `editor.commit_id_not_matching` was reported by https://codeberg.org/kita. I confirmed the meaning on next.forgejo.org. - `additional_repo_units_hint` was suggested by https://codeberg.org/leana8959. --- options/locale/locale_en-US.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 938154c546..55af096e48 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -728,8 +728,8 @@ cancel = Cancel language = Language ui = Theme hints = Hints +additional_repo_units_hint = Suggest to enable additional repository units additional_repo_units_hint_description = Display an "Add more units..." button for repositories that do not have all available units enabled. -additional_repo_units_hint = Encourage enabling additional repository units update_hints = Update hints update_hints_success = Hints have been updated. hidden_comment_types = Hidden comment types @@ -1351,7 +1351,7 @@ editor.file_editing_no_longer_exists = The file being edited, "%s", no longer ex editor.file_deleting_no_longer_exists = The file being deleted, "%s", no longer exists in this repository. editor.file_changed_while_editing = The file contents have changed since you started editing. Click here to see them or Commit changes again to overwrite them. editor.file_already_exists = A file named "%s" already exists in this repository. -editor.commit_id_not_matching = The commit ID does not match the one you was editing. Commit to a new branch and then merge. +editor.commit_id_not_matching = The file was changed while you were editing it. Commit to a new branch and then merge. editor.push_out_of_date = The push appears to be out of date. editor.commit_empty_file_header = Commit an empty file editor.commit_empty_file_text = The file you're about to commit is empty. Proceed? From f3045f0519e0b072dbc574372179267ebe175a79 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 8 May 2024 14:21:20 +0200 Subject: [PATCH 25/99] fix(security): CVE-2024-24788 malformed DNS message Refs: https://pkg.go.dev/vuln/GO-2024-2824 --- go.mod | 2 +- release-notes/8.0.0/3671.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 release-notes/8.0.0/3671.md diff --git a/go.mod b/go.mod index 4c72a35b97..5a18bfac0c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module code.gitea.io/gitea -go 1.22.2 +go 1.22.3 require ( code.gitea.io/actions-proto-go v0.4.0 diff --git a/release-notes/8.0.0/3671.md b/release-notes/8.0.0/3671.md new file mode 100644 index 0000000000..4989ba310e --- /dev/null +++ b/release-notes/8.0.0/3671.md @@ -0,0 +1 @@ +CVE-2024-24788: a malformed DNS message in response to a query can cause the Lookup functions to get stuck in an infinite loop. From 7105e19468abd5b5fde6f5f43e34bb73a4129088 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 8 May 2024 16:03:56 +0000 Subject: [PATCH 26/99] Update dependency @stylistic/eslint-plugin-js to v1.8.1 --- 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 3343267029..2c919a5533 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,7 +67,7 @@ "@eslint-community/eslint-plugin-eslint-comments": "4.3.0", "@playwright/test": "1.43.0", "@stoplight/spectral-cli": "6.11.1", - "@stylistic/eslint-plugin-js": "1.8.0", + "@stylistic/eslint-plugin-js": "1.8.1", "@stylistic/stylelint-plugin": "2.1.2", "@vitejs/plugin-vue": "5.0.4", "@vue/test-utils": "2.4.5", @@ -2126,9 +2126,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.0.tgz", - "integrity": "sha512-jdvnzt+pZPg8TfclZlTZPiUbbima93ylvQ+wNgHLNmup3obY6heQvgewSu9i2CfS61BnRByv+F9fxQLPoNeHag==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.1.tgz", + "integrity": "sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==", "dev": true, "dependencies": { "@types/eslint": "^8.56.10", diff --git a/package.json b/package.json index 4929af94dd..30a3fb6394 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@eslint-community/eslint-plugin-eslint-comments": "4.3.0", "@playwright/test": "1.43.0", "@stoplight/spectral-cli": "6.11.1", - "@stylistic/eslint-plugin-js": "1.8.0", + "@stylistic/eslint-plugin-js": "1.8.1", "@stylistic/stylelint-plugin": "2.1.2", "@vitejs/plugin-vue": "5.0.4", "@vue/test-utils": "2.4.5", From d4bb6670514be8697cfd348f41e8c9b315a98ab7 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 8 May 2024 19:32:24 +0200 Subject: [PATCH 27/99] chore(dependency): automerge all JavaScript CI dependencies Make a pass to have a full inventory of JavaScript dependencies that can be automerged because they only have an impact on the CI. It is easier than to examine them one by one when an update is proposed. - add packages:test which indirectly includes packages:jsUnitTest and a number of test dependencies such as vitest - add prefixes for dependencies which are known to be exclusively used for testing (playwright, ...) - add modules Refs: https://docs.renovatebot.com/presets-packages --- renovate.json | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/renovate.json b/renovate.json index b8d0fae32c..d785e3b5a1 100644 --- a/renovate.json +++ b/renovate.json @@ -95,9 +95,22 @@ "enabled": false }, { - "description": "Automerge some packages when ci succeeds", - "extends": ["packages:linters"], - "matchDepNames": ["github.com/PuerkitoBio/goquery", "vitest", "vite-string-plugin"], + "description": "Automerge some packages when CI succeeds", + "extends": ["packages:linters", "packages:test"], + "matchDepNames": [ + "github.com/PuerkitoBio/goquery", + "happy-dom", + "markdownlint-cli", + "updates", + "vite-string-plugin", + "@vue/test-utils" + ], + "matchPackagePrefixes": [ + "@eslint-community/", + "@playwright/", + "@stoplight/spectral-cli", + "@stylistic/" + ], "automerge": true }, { From 4bff06dafb9fc6c613a0044d773c596cc148096c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 May 2024 00:05:39 +0000 Subject: [PATCH 28/99] Update module github.com/blevesearch/bleve/v2 to v2.4.0 --- go.mod | 10 ++++++---- go.sum | 20 ++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 5a18bfac0c..a87de37d4c 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/PuerkitoBio/goquery v1.9.2 github.com/alecthomas/chroma/v2 v2.13.0 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb - github.com/blevesearch/bleve/v2 v2.3.10 + github.com/blevesearch/bleve/v2 v2.4.0 github.com/buildkite/terminal-to-html/v3 v3.10.1 github.com/caddyserver/certmagic v0.20.0 github.com/chi-middleware/proxy v1.1.1 @@ -140,12 +140,13 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect - github.com/blevesearch/bleve_index_api v1.1.5 // indirect - github.com/blevesearch/geo v0.1.19 // indirect + github.com/blevesearch/bleve_index_api v1.1.6 // indirect + github.com/blevesearch/geo v0.1.20 // indirect + github.com/blevesearch/go-faiss v1.0.13 // indirect github.com/blevesearch/go-porterstemmer v1.0.3 // indirect github.com/blevesearch/gtreap v0.1.1 // indirect github.com/blevesearch/mmap-go v1.0.4 // indirect - github.com/blevesearch/scorch_segment_api/v2 v2.2.6 // indirect + github.com/blevesearch/scorch_segment_api/v2 v2.2.9 // indirect github.com/blevesearch/segment v0.9.1 // indirect github.com/blevesearch/snowballstem v0.9.0 // indirect github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect @@ -155,6 +156,7 @@ require ( github.com/blevesearch/zapx/v13 v13.3.10 // indirect github.com/blevesearch/zapx/v14 v14.3.10 // indirect github.com/blevesearch/zapx/v15 v15.3.13 // indirect + github.com/blevesearch/zapx/v16 v16.0.12 // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect diff --git a/go.sum b/go.sum index f9831db472..a7a9b18963 100644 --- a/go.sum +++ b/go.sum @@ -128,20 +128,22 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/blevesearch/bleve/v2 v2.3.10 h1:z8V0wwGoL4rp7nG/O3qVVLYxUqCbEwskMt4iRJsPLgg= -github.com/blevesearch/bleve/v2 v2.3.10/go.mod h1:RJzeoeHC+vNHsoLR54+crS1HmOWpnH87fL70HAUCzIA= -github.com/blevesearch/bleve_index_api v1.1.5 h1:0q05mzu6GT/kebzqKywCpou/eUea9wTKa7kfqX7QX+k= -github.com/blevesearch/bleve_index_api v1.1.5/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= -github.com/blevesearch/geo v0.1.19 h1:hlX1YpBZ+X+xfjS8hEpmM/tdPUFbqBME3mdAWKHo2s0= -github.com/blevesearch/geo v0.1.19/go.mod h1:EPyr3iJCcESYa830PnkFhqzJkOP7/daHT/ocun43WRY= +github.com/blevesearch/bleve/v2 v2.4.0 h1:2xyg+Wv60CFHYccXc+moGxbL+8QKT/dZK09AewHgKsg= +github.com/blevesearch/bleve/v2 v2.4.0/go.mod h1:IhQHoFAbHgWKYavb9rQgQEJJVMuY99cKdQ0wPpst2aY= +github.com/blevesearch/bleve_index_api v1.1.6 h1:orkqDFCBuNU2oHW9hN2YEJmet+TE9orml3FCGbl1cKk= +github.com/blevesearch/bleve_index_api v1.1.6/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= +github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM= +github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w= +github.com/blevesearch/go-faiss v1.0.13 h1:zfFs7ZYD0NqXVSY37j0JZjZT1BhE9AE4peJfcx/NB4A= +github.com/blevesearch/go-faiss v1.0.13/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8= github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk= github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= -github.com/blevesearch/scorch_segment_api/v2 v2.2.6 h1:rewrzgFaCEjjfWovAB9NubMAd4+aCLxD3RaQcPDaoNo= -github.com/blevesearch/scorch_segment_api/v2 v2.2.6/go.mod h1:0rv+k/OIjtYCT/g7Z45pCOVweFyta+0AdXO8keKfZxo= +github.com/blevesearch/scorch_segment_api/v2 v2.2.9 h1:3nBaSBRFokjE4FtPW3eUDgcAu3KphBg1GP07zy/6Uyk= +github.com/blevesearch/scorch_segment_api/v2 v2.2.9/go.mod h1:ckbeb7knyOOvAdZinn/ASbB7EA3HoagnJkmEV3J7+sg= github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= @@ -160,6 +162,8 @@ github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz7 github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns= github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ= github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg= +github.com/blevesearch/zapx/v16 v16.0.12 h1:Uccxvjmn+hQ6ywQP+wIiTpdq9LnAviGoryJOmGwAo/I= +github.com/blevesearch/zapx/v16 v16.0.12/go.mod h1:MYnOshRfSm4C4drxx1LGRI+MVFByykJ2anDY1fxdk9Q= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= From d3e02eaa890480fb4db9859a0d4871d6e7569c3d Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 8 May 2024 11:55:41 +0200 Subject: [PATCH 29/99] chore(licenses): make go-license --- assets/go-licenses.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 62971df47f..026321b3fa 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -224,6 +224,11 @@ "path": "github.com/blevesearch/zapx/v15/LICENSE", "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License." }, + { + "name": "github.com/blevesearch/zapx/v16", + "path": "github.com/blevesearch/zapx/v16/LICENSE", + "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License." + }, { "name": "github.com/boombuler/barcode", "path": "github.com/boombuler/barcode/LICENSE", From 8e1a6d8e736c4e7016b5fdf5fafe302358dba619 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 8 May 2024 20:05:21 +0000 Subject: [PATCH 30/99] Update ghcr.io/visualon/renovate Docker tag to v37.351.2 --- .forgejo/workflows/renovate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index f311c8ca6f..d26672d598 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -22,7 +22,7 @@ jobs: runs-on: docker container: - image: ghcr.io/visualon/renovate:37.340.9 + image: ghcr.io/visualon/renovate:37.351.2 steps: - name: Load renovate repo cache From f4dd53d79dda7481cd29634727cd8e2caae8d7fe Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 8 May 2024 21:14:46 +0000 Subject: [PATCH 31/99] Fix an incorrect form submission in repo-issue.js (#3675) This fixes `initRepoPullRequestAllowMaintainerEdit()` to submit the form correctly (as a web form, rather than as JSON payload). Fixes #3618, cherry picked from gitea#30854. Co-Authored-By: wxiaoguang --- Manual testing steps: - Open a PR against any repository, with the "Allow edits from maintainers" option checked. - Open the developer console (`Ctrl-Shift-I` on Firefox), and look at the Network tab. - Visit the PR, find the "Allow edits from maintainers" checkbox, and click it. - See the developer console, and check that the response says the setting is false. - Refresh the page *completely* (`Ctrl-Shift-R` on Firefox) - Observe that the setting is off. - Click the box again to enable it. - See the developer console, and check that the response says the setting is true. - Reload without cache again (`Ctrl-Shift-R` on Firefox) - Observe that the setting is now on. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3675 Reviewed-by: Earl Warren Co-authored-by: Gergely Nagy Co-committed-by: Gergely Nagy --- release-notes/8.0.0/fix/3675.md | 1 + web_src/js/features/repo-issue.js | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 release-notes/8.0.0/fix/3675.md diff --git a/release-notes/8.0.0/fix/3675.md b/release-notes/8.0.0/fix/3675.md new file mode 100644 index 0000000000..c6feed07ca --- /dev/null +++ b/release-notes/8.0.0/fix/3675.md @@ -0,0 +1 @@ +Fixed an issue that rendered the "Allow edits from maintainers" checkbox disfunctional, preventing people from turning it on. diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 3f2b3523f6..7432cbc65a 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -298,23 +298,23 @@ export function initRepoPullRequestMergeInstruction() { export function initRepoPullRequestAllowMaintainerEdit() { const wrapper = document.getElementById('allow-edits-from-maintainers'); if (!wrapper) return; - - wrapper.querySelector('input[type="checkbox"]')?.addEventListener('change', async (e) => { - const checked = e.target.checked; + const checkbox = wrapper.querySelector('input[type="checkbox"]'); + checkbox.addEventListener('input', async () => { const url = `${wrapper.getAttribute('data-url')}/set_allow_maintainer_edit`; wrapper.classList.add('is-loading'); - e.target.disabled = true; try { - const response = await POST(url, {data: {allow_maintainer_edit: checked}}); - if (!response.ok) { + const resp = await POST(url, {data: new URLSearchParams({allow_maintainer_edit: checkbox.checked})}); + if (!resp.ok) { throw new Error('Failed to update maintainer edit permission'); } + const data = await resp.json(); + checkbox.checked = data.allow_maintainer_edit; } catch (error) { + checkbox.checked = !checkbox.checked; console.error(error); showTemporaryTooltip(wrapper, wrapper.getAttribute('data-prompt-error')); } finally { wrapper.classList.remove('is-loading'); - e.target.disabled = false; } }); } From e71f8b8f7b0a83019a965bdb1691070db5eafca1 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 9 May 2024 00:06:13 +0000 Subject: [PATCH 32/99] Update dependency swagger-ui-dist to v5.17.6 --- 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 4ba3d404c8..6c4af49af4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "postcss-nesting": "12.1.2", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", - "swagger-ui-dist": "5.17.2", + "swagger-ui-dist": "5.17.6", "tailwindcss": "3.4.3", "temporal-polyfill": "0.2.4", "throttle-debounce": "5.0.0", @@ -11497,9 +11497,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.17.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.2.tgz", - "integrity": "sha512-V/NqUw6QoTrjSpctp2oLQvxrl3vW29UsUtZyq7B1CF0v870KOFbYGDQw8rpKaKm0JxTwHpWnW1SN9YuKZdiCyw==" + "version": "5.17.6", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.6.tgz", + "integrity": "sha512-8P48+WvFKDF7YoDqmWq3EItwdOh7tJlPSZ7y6CNqQIPMQ+qZVI0iNlBMSzyU+PXOd1M8ndRiNKWOvfItREBvHg==" }, "node_modules/sync-fetch": { "version": "0.4.5", diff --git a/package.json b/package.json index f8baad3ab9..012651f73b 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "postcss-nesting": "12.1.2", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", - "swagger-ui-dist": "5.17.2", + "swagger-ui-dist": "5.17.6", "tailwindcss": "3.4.3", "temporal-polyfill": "0.2.4", "throttle-debounce": "5.0.0", From 15c08780847e8fa63a08c046820eb10bf68ecdf8 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 9 May 2024 00:06:36 +0000 Subject: [PATCH 33/99] Update dependency vue to v3.4.27 --- package-lock.json | 106 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ba3d404c8..707fc593eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,7 +54,7 @@ "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", "vanilla-colorful": "0.7.2", - "vue": "3.4.26", + "vue": "3.4.27", "vue-bar-graph": "2.0.0", "vue-chartjs": "5.3.1", "vue-loader": "17.4.2", @@ -2668,36 +2668,36 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.26.tgz", - "integrity": "sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", "dependencies": { "@babel/parser": "^7.24.4", - "@vue/shared": "3.4.26", + "@vue/shared": "3.4.27", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.26.tgz", - "integrity": "sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", "dependencies": { - "@vue/compiler-core": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.26.tgz", - "integrity": "sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", "dependencies": { "@babel/parser": "^7.24.4", - "@vue/compiler-core": "3.4.26", - "@vue/compiler-dom": "3.4.26", - "@vue/compiler-ssr": "3.4.26", - "@vue/shared": "3.4.26", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", "estree-walker": "^2.0.2", "magic-string": "^0.30.10", "postcss": "^8.4.38", @@ -2713,57 +2713,57 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.26.tgz", - "integrity": "sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", "dependencies": { - "@vue/compiler-dom": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/reactivity": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.26.tgz", - "integrity": "sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", "dependencies": { - "@vue/shared": "3.4.26" + "@vue/shared": "3.4.27" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.26.tgz", - "integrity": "sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", "dependencies": { - "@vue/reactivity": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.26.tgz", - "integrity": "sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", "dependencies": { - "@vue/runtime-core": "3.4.26", - "@vue/shared": "3.4.26", + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.26.tgz", - "integrity": "sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", "dependencies": { - "@vue/compiler-ssr": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" }, "peerDependencies": { - "vue": "3.4.26" + "vue": "3.4.27" } }, "node_modules/@vue/shared": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.26.tgz", - "integrity": "sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==" + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==" }, "node_modules/@vue/test-utils": { "version": "2.4.6", @@ -12421,15 +12421,15 @@ } }, "node_modules/vue": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.26.tgz", - "integrity": "sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", "dependencies": { - "@vue/compiler-dom": "3.4.26", - "@vue/compiler-sfc": "3.4.26", - "@vue/runtime-dom": "3.4.26", - "@vue/server-renderer": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" }, "peerDependencies": { "typescript": "*" diff --git a/package.json b/package.json index f8baad3ab9..67e5bca4cf 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "tributejs": "5.1.3", "uint8-to-base64": "0.2.0", "vanilla-colorful": "0.7.2", - "vue": "3.4.26", + "vue": "3.4.27", "vue-bar-graph": "2.0.0", "vue-chartjs": "5.3.1", "vue-loader": "17.4.2", From e89e253636bf74bd023a548317b9c08bde664d21 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 9 May 2024 02:05:43 +0000 Subject: [PATCH 34/99] Update dependency @playwright/test to v1.44.0 --- package-lock.json | 24 ++++++++++++------------ package.json | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ba3d404c8..e1b0a759ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.3.0", - "@playwright/test": "1.43.0", + "@playwright/test": "1.44.0", "@stoplight/spectral-cli": "6.11.1", "@stylistic/eslint-plugin-js": "1.8.1", "@stylistic/stylelint-plugin": "2.1.2", @@ -1351,12 +1351,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", - "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.0.tgz", + "integrity": "sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==", "dev": true, "dependencies": { - "playwright": "1.43.0" + "playwright": "1.44.0" }, "bin": { "playwright": "cli.js" @@ -9631,12 +9631,12 @@ "dev": true }, "node_modules/playwright": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", - "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", + "integrity": "sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==", "dev": true, "dependencies": { - "playwright-core": "1.43.0" + "playwright-core": "1.44.0" }, "bin": { "playwright": "cli.js" @@ -9649,9 +9649,9 @@ } }, "node_modules/playwright-core": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", - "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", + "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/package.json b/package.json index f8baad3ab9..13a9e7a1ba 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.3.0", - "@playwright/test": "1.43.0", + "@playwright/test": "1.44.0", "@stoplight/spectral-cli": "6.11.1", "@stylistic/eslint-plugin-js": "1.8.1", "@stylistic/stylelint-plugin": "2.1.2", From 2b2fd2728c94c0ae2a3cd00c9cd95ab629fd2896 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Thu, 9 May 2024 13:49:37 +0000 Subject: [PATCH 35/99] Add codespell support and fix a good number of typos with its help (#3270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More about codespell: https://github.com/codespell-project/codespell . I personally introduced it to dozens if not hundreds of projects already and so far only positive feedback. ``` ❯ grep lint-spell Makefile @echo " - lint-spell lint spelling" @echo " - lint-spell-fix lint spelling and fix issues" lint: lint-frontend lint-backend lint-spell lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix .PHONY: lint-spell lint-spell: lint-codespell .PHONY: lint-spell-fix lint-spell-fix: lint-codespell-fix ❯ git grep lint- -- .forgejo/ .forgejo/workflows/testing.yml: - run: make --always-make -j$(nproc) lint-backend checks-backend # ensure the "go-licenses" make target runs .forgejo/workflows/testing.yml: - run: make lint-frontend ``` so how would you like me to invoke `lint-codespell` on CI? (without that would be IMHO very suboptimal and let typos sneak in) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3270 Reviewed-by: Earl Warren Co-authored-by: Yaroslav Halchenko Co-committed-by: Yaroslav Halchenko --- Makefile | 19 +++++++++++++-- RELEASE-NOTES.md | 24 +++++++++---------- contrib/backport/README | 2 +- contrib/legal/privacy.html.sample | 2 +- models/actions/tasks_version.go | 2 +- models/auth/oauth2_test.go | 2 +- models/auth/session_test.go | 2 +- .../pull_request.yml | 2 +- models/fixtures/commit_status.yml | 4 ++-- models/fixtures/pull_request.yml | 20 ++++++++-------- models/issues/label_test.go | 2 +- models/issues/pull.go | 2 +- models/issues/tracked_time.go | 12 +++++----- models/migrations/v1_17/v216.go | 2 +- models/repo/archive_download_count.go | 2 +- models/user/setting_keys.go | 2 +- modules/avatar/identicon/identicon.go | 2 +- modules/git/ref.go | 2 +- modules/git/repo_attribute.go | 2 +- modules/gitgraph/graph_models.go | 4 ++-- modules/indexer/code/git.go | 6 ++--- modules/indexer/issues/indexer.go | 2 +- .../indexer/issues/internal/tests/tests.go | 2 +- .../issues/meilisearch/meilisearch_test.go | 2 +- modules/log/event_format.go | 2 +- .../markup/markdown/callout/github_legacy.go | 2 +- modules/markup/markdown/markdown_test.go | 2 +- modules/process/manager.go | 6 ++--- modules/queue/queue.go | 2 +- modules/templates/helper_test.go | 4 ++-- modules/testlogger/testlogger.go | 6 ++--- modules/typesniffer/typesniffer_test.go | 4 ++-- modules/util/path.go | 2 +- poetry.lock | 20 +++++++++++++++- pyproject.toml | 14 +++++++++++ routers/api/actions/artifacts.go | 2 +- routers/api/actions/runner/interceptor.go | 4 ++-- routers/api/actions/runner/runner.go | 2 +- routers/api/packages/README.md | 2 +- routers/api/v1/org/team.go | 2 +- routers/api/v1/repo/git_ref.go | 4 ++-- routers/api/v1/repo/issue.go | 4 ++-- routers/api/v1/repo/issue_subscription.go | 2 +- routers/private/hook_pre_receive.go | 2 +- routers/web/admin/orgs.go | 2 +- routers/web/admin/users.go | 2 +- routers/web/repo/actions/view.go | 8 +++---- routers/web/repo/compare.go | 2 +- routers/web/repo/issue.go | 8 +++---- routers/web/user/profile.go | 2 +- services/asymkey/sign.go | 2 +- services/context/csrf.go | 2 +- services/convert/issue_comment.go | 4 ++-- services/doctor/dbconsistency.go | 2 +- services/issue/assignee.go | 4 ++-- services/issue/pull.go | 8 +++---- services/mailer/incoming/incoming_handler.go | 2 +- services/migrations/gitea_uploader.go | 2 +- services/migrations/github.go | 2 +- services/pull/check.go | 2 +- services/pull/comment.go | 2 +- services/pull/pull.go | 2 +- services/remote/promote.go | 2 +- .../repository/commitstatus/commitstatus.go | 2 +- services/repository/contributors_graph.go | 2 +- templates/base/head.tmpl | 2 +- templates/repo/branch/list.tmpl | 2 +- templates/repo/issue/milestone_issues.tmpl | 2 +- tests/integration/README.md | 2 +- .../integration/actions_commit_status_test.go | 2 +- tests/integration/api_issue_config_test.go | 4 ++-- tests/integration/api_packages_maven_test.go | 2 +- tests/integration/compare_test.go | 8 +++---- tests/integration/editor_test.go | 2 +- tests/integration/pull_reopen_test.go | 2 +- tests/integration/pull_review_test.go | 2 +- tests/integration/rename_branch_test.go | 2 +- tests/integration/repo_fork_test.go | 2 +- web_src/fomantic/build/semantic.js | 8 +++---- web_src/js/bootstrap.js | 2 +- 80 files changed, 183 insertions(+), 136 deletions(-) diff --git a/Makefile b/Makefile index bb56f82eb5..efb344c2d9 100644 --- a/Makefile +++ b/Makefile @@ -223,6 +223,9 @@ help: @echo " - lint-frontend-fix lint frontend files and fix issues" @echo " - lint-backend lint backend files" @echo " - lint-backend-fix lint backend files and fix issues" + @echo " - lint-codespell lint typos" + @echo " - lint-codespell-fix lint typos and fix them automatically" + @echo " - lint-codespell-fix-i lint typos and fix them interactively" @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" @@ -398,6 +401,18 @@ lint-backend: lint-go lint-go-vet lint-editorconfig .PHONY: lint-backend-fix lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig +.PHONY: lint-codespell +lint-codespell: + codespell + +.PHONY: lint-codespell-fix +lint-codespell-fix: + codespell -w + +.PHONY: lint-codespell-fix-i +lint-codespell-fix-i: + codespell -w -i 3 -C 2 + .PHONY: lint-js lint-js: node_modules npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) @@ -423,11 +438,11 @@ lint-md: node_modules npx markdownlint docs *.md .PHONY: lint-spell -lint-spell: +lint-spell: lint-codespell @go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES) .PHONY: lint-spell-fix -lint-spell-fix: +lint-spell-fix: lint-codespell-fix @go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES) .PHONY: lint-go diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 6d583f0eff..41ed009b37 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -512,7 +512,7 @@ This stable release contains a single bug fix for a regression introduced in v1. ## 1.21.11-0 -[The complete list of new commits included in the Forgejo v1.21.11-0 release can be reviewed here](https://codeberg.org/forgejo/forgejo/compare/v1.21.10-0...v1.21.11-0), or from the comand line with: +[The complete list of new commits included in the Forgejo v1.21.11-0 release can be reviewed here](https://codeberg.org/forgejo/forgejo/compare/v1.21.10-0...v1.21.11-0), or from the command line with: ```shell $ git clone https://codeberg.org/forgejo/forgejo @@ -580,7 +580,7 @@ Note that there is no `Forgejo v1.21.9-0` release. The release numbering of the * [Fix paths when finding files via the web interface that were not escaped](https://codeberg.org/forgejo/forgejo/commit/b22be0c03fa4814c1b8b892346de5d4547782ce7). * [Respect `DEFAULT_ORG_MEMBER_VISIBLE` setting when adding creator to org](https://codeberg.org/forgejo/forgejo/commit/5e5574c7b328e2c500d497517047b8d1fd0ca478). * [Fix duplicate migrated milestones](https://codeberg.org/forgejo/forgejo/commit/706ff7aa9fcfe4c43893dc12e27d064064e80635). - * [Fix inline math blocks can't be preceeded/followed by alphanumerical characters](https://codeberg.org/forgejo/forgejo/commit/0d3f446460b22a29c259e7d42ed89f90fd216ca7). + * [Fix inline math blocks can't be preceded/followed by alphanumerical characters](https://codeberg.org/forgejo/forgejo/commit/0d3f446460b22a29c259e7d42ed89f90fd216ca7). ## 1.21.8-0 @@ -687,7 +687,7 @@ This stable release contains bug fixes and a **security fix**, as explained in t * [Fix push to create with capitalize repo name](https://codeberg.org/forgejo/forgejo/commit/8782275c9c66ad6fc7c44503d7df9dae7196aa65). * In Markdown [don't try to make the link absolute if the link has a schema that's defined in `[markdown].CUSTOM_URL_SCHEMES`](https://codeberg.org/forgejo/forgejo/commit/6c100083c29fb0ccf0cc52e8767e540a260d9468), because they can't be made absolute. * [Fix Ctrl+Enter on submitting review comment](https://codeberg.org/forgejo/forgejo/commit/1c3a31d85112d10fb948d6f0b763191ed6f68e90). - * In Git version v2.43.1, the behavior of `GIT_FLUSH` was accidentially flipped. This causes Forgejo to hang on the `check-attr` command, because no output was being flushed. [Workaround this by detecting if Git v2.43.1 is used and set `GIT_FLUSH=0` thus getting the correct behavior](https://codeberg.org/forgejo/forgejo/commit/ff468ab5e426582b068586ce13d5a5348365e783). + * In Git version v2.43.1, the behavior of `GIT_FLUSH` was accidentally flipped. This causes Forgejo to hang on the `check-attr` command, because no output was being flushed. [Workaround this by detecting if Git v2.43.1 is used and set `GIT_FLUSH=0` thus getting the correct behavior](https://codeberg.org/forgejo/forgejo/commit/ff468ab5e426582b068586ce13d5a5348365e783). * [When setting `url.host` on a URL object with no port specified (like is the case of default port), the resulting URL's port will not change. Workaround this quirk in the URL standard by explicitly setting port for the http and https protocols](https://codeberg.org/forgejo/forgejo/commit/628e1036cfbcfae442cb6494249fe11410447056). * [Fix elasticsearch Request Entity Too Large](https://codeberg.org/forgejo/forgejo/commit/e6f59f6e1489d63d53de0da1de406a7a71a82adb). * [Do not send update/delete release notifications when it is in a draft state](https://codeberg.org/forgejo/forgejo/commit/3c54a1dbf62e56d948feb1008512900140033737). @@ -777,7 +777,7 @@ This stable release includes security and bug fixes as well as documentation imp * [Gracefully handle missing branches](https://codeberg.org/forgejo/forgejo/commit/c2fa9c308f5cdb08dd84fb8ec6623a57e75d5152) when a branch is missing from Git but still lingering in the database. * [Fix panic in `canSoftDeleteContentHistory`](https://codeberg.org/forgejo/forgejo/commit/ab1ccc55dca7fd05e59a01343e6dfe53be6195d0) * [Check for Commit in opengraph](https://codeberg.org/forgejo/forgejo/commit/b473a44a2bb59591f3e24bfcdeed1d8fbb0f9204) - * [Handle non-existant commit in Archive request](https://codeberg.org/forgejo/forgejo/commit/0fbf761d1930f9336be6da8d17ae6032203a9381) + * [Handle non-existent commit in Archive request](https://codeberg.org/forgejo/forgejo/commit/0fbf761d1930f9336be6da8d17ae6032203a9381) * [Fix NPE in `ToPullReviewList`](https://codeberg.org/forgejo/forgejo/commit/f5349b66b78968301d7dc4c45e8e08b46910aa6e) * [Fix URL in the mail to include the host](https://codeberg.org/forgejo/forgejo/commit/ac889d42903b2ce2129a02ace620a10a6f940920) * [Fix the event of a scheduled action](https://codeberg.org/forgejo/forgejo/commit/892a8e1f4a5cc09cc3136e0b0e6487c154c5ed2b) to be "schedule" instead of a semi-random event from the default branch. @@ -888,7 +888,7 @@ $ git clone https://codeberg.org/forgejo/forgejo/ $ git -C forgejo log --oneline --no-merges v1.21.1-0..v1.21.2-0 ``` -This stable release includes bug fixes. It was built with Go v1.21.5 that fixes [CVE-2023-39326](https://groups.google.com/g/golang-announce/c/iLGK3x6yuNo) which a malicious HTTP client can exploit to cause a server to automatically read a large amount of data. It allows for memory exhaustion in the situation that HTTP chuncked encoding requests can reach Forgejo. +This stable release includes bug fixes. It was built with Go v1.21.5 that fixes [CVE-2023-39326](https://groups.google.com/g/golang-announce/c/iLGK3x6yuNo) which a malicious HTTP client can exploit to cause a server to automatically read a large amount of data. It allows for memory exhaustion in the situation that HTTP chunked encoding requests can reach Forgejo. * Recommended Action @@ -953,7 +953,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.20/forgejo..origin/v1.21/fo - [Add](https://codeberg.org/forgejo/forgejo/commit/0d55f64e6cd3de2e1e5c0ee795605823efb14231) support for [recurring actions similar to cron jobs](https://forgejo.org/docs/v1.21/user/actions/#onschedule). - [Add](https://codeberg.org/forgejo/forgejo/commit/19872063a3c14256a1d89b2a104d63e7538a3a28) the possibility to [disable workflows from the user interface](https://forgejo.org/docs/v1.21/user/actions/#list-of-runners-and-their-tasks). - [Add](https://codeberg.org/forgejo/forgejo/commit/460a2b0edffe71d9e64633beaa1071fcf4a33369) automatic [cleanup of artificats](https://forgejo.org/docs/v1.21/user/actions/#artifacts). - - [Add](https://codeberg.org/forgejo/forgejo/commit/44781f9f5c4ede618660d8cfe42437f0e8dc22a0) automatic cancelation [of jobs when pushing new commits](https://forgejo.org/docs/v1.21/user/actions/#auto-cancelation-of-workflows) to a PR. + - [Add](https://codeberg.org/forgejo/forgejo/commit/44781f9f5c4ede618660d8cfe42437f0e8dc22a0) automatic cancellation [of jobs when pushing new commits](https://forgejo.org/docs/v1.21/user/actions/#auto-cancellation-of-workflows) to a PR. - [Add](https://codeberg.org/forgejo/forgejo/commit/f3d293d2bbe0b2eab047bdd403046069cffbc0c4) support for [uploading multiple artificats](https://forgejo.org/docs/v1.21/user/actions/#artifacts). - [Add](https://codeberg.org/forgejo/forgejo/commit/48e5a74f215d78813a816c57fc5a85a909a003d5) support for the [`pull_request_target` event](https://forgejo.org/docs/v1.21/user/actions/#onpull_request_target) which has access to secrets because it runs using the workflows from the base branch instead of the pull request. - [Add](https://codeberg.org/forgejo/forgejo/commit/8228751c55d6a4263f0fec2932ca16181c09c97d) support for reading labels from the runner [instead of specifying them during registration](https://forgejo.org/docs/v1.21/admin/actions/#registration). @@ -1268,7 +1268,7 @@ this situation, [follow the instructions in the companion blog post](https://for * [The CLI exit code now is different from zero when an error occurs](https://codeberg.org/forgejo/forgejo/commit/089af9ab1) * [Fix error when a Debian package has a double newline character at the end of the control block](https://codeberg.org/forgejo/forgejo/commit/dd7180846) * [Fix a condition that would cause git related tasks to hang for longer than necessary in the queues and use too many resources as a result](https://codeberg.org/forgejo/forgejo/commit/36f8fbe1b) - * [Fix the topic validation rule and suport dots](https://codeberg.org/forgejo/forgejo/commit/a578b75d7) + * [Fix the topic validation rule and support dots](https://codeberg.org/forgejo/forgejo/commit/a578b75d7) * [Fix pull request check list when there are more than 30](https://codeberg.org/forgejo/forgejo/commit/e226b9646) * [Fix attachment clipboard copy on insecure origin](https://codeberg.org/forgejo/forgejo/commit/12ac84c26) * [Fix the profile README rendering](https://codeberg.org/forgejo/forgejo/commit/84c3b60a4) that [was inconsistent with other markdown files renderings](https://codeberg.org/forgejo/forgejo/issues/833) @@ -1297,7 +1297,7 @@ This stable release includes bug fixes and displays [warnings in the administrat The most prominent ones are described here, others can be found in the list of commits included in the release as described above. - * [Add missing assets to the Forgejo sources tarbal](https://codeberg.org/forgejo/forgejo/commit/e14d239005) + * [Add missing assets to the Forgejo sources tarball](https://codeberg.org/forgejo/forgejo/commit/e14d239005) * [Fix user type selection error when creating a user](https://codeberg.org/forgejo/forgejo/commit/268569b462) and selecting `public` or `private`. * [Fix access check for org-level project](https://codeberg.org/forgejo/forgejo/commit/5afb0294f4) * [Warn instead of reporting an error when a webhook cannot be found](https://codeberg.org/forgejo/forgejo/commit/4c3dcdf815) @@ -1352,7 +1352,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.19/forgejo..origin/v1.20/fo - The storage settings were [refactored](https://codeberg.org/forgejo/forgejo/commit/d6dd6d641b593c54fe1a1041c153111ce81dbc20). Read more about [storage settings](https://forgejo.org/docs/v1.20/admin/storage/). - [The [repository.editor] PREVIEWABLE_FILE_MODES setting was removed](https://codeberg.org/forgejo/forgejo/commit/84daddc2fa74393cdc13371b0cc44f0444cfdae0). This setting served no practical purpose and was not working correctly. Instead a preview tab is always shown in the file editor when supported. - In addition to the already deprecated options inside [queue], many options have been dropped as well. Those are WRAP_IF_NECESSARY, MAX_ATTEMPTS, TIMEOUT, WORKERS, BLOCK_TIMEOUT, BOOST_TIMEOUT, BOOST_WORKERS. You can remove them from your app.ini now. Additionally, some default values have changed in this section. - - The default CSS and templates included in Forgejo were heavily refactored and a large number of variables renamed. These changes are not documented and there is a very high chance that a tempate extracted and modified for a particular Forgejo instance will no longer work as it did. Browsing through the git history of the template in the sources is the best way to figure out how and why it was modified. + - The default CSS and templates included in Forgejo were heavily refactored and a large number of variables renamed. These changes are not documented and there is a very high chance that a template extracted and modified for a particular Forgejo instance will no longer work as it did. Browsing through the git history of the template in the sources is the best way to figure out how and why it was modified. - **Moderation:** Blocking another user is desirable if they are acting maliciously or are spamming your repository. When you block a user, Forgejo does not explicitly notify them, but they may learn through an interaction with you that is blocked. [Read more about blocking users](https://forgejo.org/docs/v1.20/user/blocking-user/). - **Package:** @@ -1360,7 +1360,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.19/forgejo..origin/v1.20/fo - **Accessibility:** numerous improvements for [issue comments](https://codeberg.org/forgejo/forgejo/commit/6c354546547cd3a9595a7db119a6480d9cd506a7), [the menu on the navbar](https://codeberg.org/forgejo/forgejo/commit/a78e0b7dade16bc6509b943fe86e74962f1b95b6), [scoped labels](https://codeberg.org/forgejo/forgejo/commit/e8935606f5f1fff3c59222ebca6d4615ab06fb0b), [checkboxes and dropdowns](https://codeberg.org/forgejo/forgejo/commit/d4f35bd681af0632da988e15306f330e020422b2), [RTL rendering support to Markdown](https://codeberg.org/forgejo/forgejo/commit/32d9c47ec7706d8f06e09b42e09a28d7a0e3c526), [file (re-)views](https://codeberg.org/forgejo/forgejo/commit/e95b42e187cde9ac4bd541cd714bdb4f5c1fd8bc), [interactive tooltips](https://codeberg.org/forgejo/forgejo/commit/87f0f7e670c6c0e6aeab8c4458bfdb9d954eacec), [using a button element](https://codeberg.org/forgejo/forgejo/commit/81fe5d61851c0e586af7d32c29171ceff9a571bb), [repository list](https://codeberg.org/forgejo/forgejo/commit/e82f1b15c7120ad13fd3b67cf7e2c6cb9915c22d) and more. - **Time:** - The display and localization of time was improved for [tooltips](https://codeberg.org/forgejo/forgejo/commit/b7b58348317cbe0145dc453d45c886b8e2764b4c), [milestones](https://codeberg.org/forgejo/forgejo/commit/97176754beb4de23fa0f68df715c4737919c93b0), [due date and translations that contain dates](https://codeberg.org/forgejo/forgejo/commit/70bb4984cdad9a15d676708bd345b590aa42d72a), [commit graphs](https://codeberg.org/forgejo/forgejo/commit/5bc9f7fcf9aece92c3fa2a0ea56e5585261a7f28), [runners](https://codeberg.org/forgejo/forgejo/commit/62ca5825f73ad5a25ffeb6c3ef66f0eaf5d30cdf), [webhooks](https://codeberg.org/forgejo/forgejo/commit/dbb37367854d108ebfffcac27837c0afac199a8e), [tests](https://codeberg.org/forgejo/forgejo/commit/3d266dd0f3dbae7e417c0e790e266aebc0078814) and more. Previously each rendered timestamp would be static, now the real time since an event happend is show. If a comment was added 2 minutes before the page rendered it would show as "2 minutes ago" on the initial render and if another 8 minutes have passed, without a page refresh you'd see "10 minutes ago". + The display and localization of time was improved for [tooltips](https://codeberg.org/forgejo/forgejo/commit/b7b58348317cbe0145dc453d45c886b8e2764b4c), [milestones](https://codeberg.org/forgejo/forgejo/commit/97176754beb4de23fa0f68df715c4737919c93b0), [due date and translations that contain dates](https://codeberg.org/forgejo/forgejo/commit/70bb4984cdad9a15d676708bd345b590aa42d72a), [commit graphs](https://codeberg.org/forgejo/forgejo/commit/5bc9f7fcf9aece92c3fa2a0ea56e5585261a7f28), [runners](https://codeberg.org/forgejo/forgejo/commit/62ca5825f73ad5a25ffeb6c3ef66f0eaf5d30cdf), [webhooks](https://codeberg.org/forgejo/forgejo/commit/dbb37367854d108ebfffcac27837c0afac199a8e), [tests](https://codeberg.org/forgejo/forgejo/commit/3d266dd0f3dbae7e417c0e790e266aebc0078814) and more. Previously each rendered timestamp would be static, now the real time since an event happened is show. If a comment was added 2 minutes before the page rendered it would show as "2 minutes ago" on the initial render and if another 8 minutes have passed, without a page refresh you'd see "10 minutes ago". - **[Wiki](https://forgejo.org/docs/v1.20/user/wiki/)** - Improve the [display of the table of content](https://codeberg.org/forgejo/forgejo/commit/1ab16e48cccc086e7f97fb3ae8a293fe47a3a452) - Fixed a bug [preventing team users who have wiki write permission from deleting a page](https://codeberg.org/forgejo/forgejo/commit/284b41f45244bbe46fc8feee15bbfdf66d150e79) @@ -1701,7 +1701,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.18/forgejo..origin/v1.19/fo Forgejo access token, used with the [API](https://forgejo.org/docs/v1.19/admin/api-usage/) can now have a "scope" that limits what it can access. Existing tokens stored in the database and created before Forgejo v1.19 had unlimited access. For backward compatibility, their access will remain the same and they will continue to work as before. However, **newly created token that do not specify a scope will now only have read-only access to public user profile and public repositories**. - For instance, the `/users/{username}/tokens` API endpoint will require the `scopes: ['all', 'sudo']` parameter and the `forgejo admin user generate-access-token` will require the `--scopes all,sudo` argument obtain tokens with ulimited access as before for admin users. + For instance, the `/users/{username}/tokens` API endpoint will require the `scopes: ['all', 'sudo']` parameter and the `forgejo admin user generate-access-token` will require the `--scopes all,sudo` argument obtain tokens with unlimited access as before for admin users. [Read more about the scoped tokens](https://forgejo.org/docs/v1.19/user/oauth2-provider/#scoped-tokens). @@ -1818,7 +1818,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.18/forgejo..origin/v1.19/fo It appears for the first time in this Forgejo release but is not yet fit for production. It is not fully implemented and may be insecure. However, as long as it is not enabled, it presents no risk to existing Forgejo instances. - If a repository has a file such as `.forgejo/workflows/test.yml`, it will be interpreted, for instance to run tests and verify the code in the repository works as expected (Continuous Integration). It can also be used to create HTML pages for a website and publish them (Continous Deployment). The syntax is similar to GitHub Actions and the jobs can be controled from the Forgejo web interface. + If a repository has a file such as `.forgejo/workflows/test.yml`, it will be interpreted, for instance to run tests and verify the code in the repository works as expected (Continuous Integration). It can also be used to create HTML pages for a website and publish them (Continuous Deployment). The syntax is similar to GitHub Actions and the jobs can be controlled from the Forgejo web interface. [Read more about Forgejo Actions](https://forgejo.codeberg.page/2023-02-27-forgejo-actions/) diff --git a/contrib/backport/README b/contrib/backport/README index 1e84c1bb97..466b79c6d4 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -11,7 +11,7 @@ The default version will read from `docs/config.yml`. You can override this using the option `--version`. The upstream branches will be fetched, using the remote `origin`. This can -be overrided using `--upstream`, and fetching can be avoided using +be overridden using `--upstream`, and fetching can be avoided using `--no-fetch`. By default the branch created will be called `backport-$PR-$VERSION`. You diff --git a/contrib/legal/privacy.html.sample b/contrib/legal/privacy.html.sample index 50972b2a3e..adb3ea7ad4 100644 --- a/contrib/legal/privacy.html.sample +++ b/contrib/legal/privacy.html.sample @@ -150,7 +150,7 @@

In general, Your Gitea Instance retains User Personal Information for as long as your account is active, or as needed to provide you service.

-

If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the bassis of consent within 30 days.

+

If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the basis of consent within 30 days.

After an account has been deleted, certain data, such as contributions to other Users' repositories and comments in others' issues, will remain. However, we will delete or de-identify your User Personal Information, including your username and email address, from the author field of issues, pull requests, and comments by associating them with a ghost user.

diff --git a/models/actions/tasks_version.go b/models/actions/tasks_version.go index 5c0a86538d..d8df353593 100644 --- a/models/actions/tasks_version.go +++ b/models/actions/tasks_version.go @@ -13,7 +13,7 @@ import ( // ActionTasksVersion // If both ownerID and repoID is zero, its scope is global. -// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currrently). +// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currently). // If ownerID is zero and repoID is not zero, its scope is repo. type ActionTasksVersion struct { ID int64 `xorm:"pk autoincr"` diff --git a/models/auth/oauth2_test.go b/models/auth/oauth2_test.go index 6602f850cf..a6fbcdaa4f 100644 --- a/models/auth/oauth2_test.go +++ b/models/auth/oauth2_test.go @@ -60,7 +60,7 @@ func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) { // not loopback assert.False(t, app.ContainsRedirectURI("http://192.168.0.1:9954/")) assert.False(t, app.ContainsRedirectURI("http://intranet:3456/")) - // unparseable + // unparsable assert.False(t, app.ContainsRedirectURI(":")) } diff --git a/models/auth/session_test.go b/models/auth/session_test.go index 3475fdd2cd..8cc0abc737 100644 --- a/models/auth/session_test.go +++ b/models/auth/session_test.go @@ -85,7 +85,7 @@ func TestAuthSession(t *testing.T) { err = auth.DestroySession(db.DefaultContext, key) assert.NoError(t, err) - // Ensure it doens't exists. + // Ensure it doesn't exists. ok, err = auth.ExistSession(db.DefaultContext, key) assert.NoError(t, err) assert.False(t, ok) diff --git a/models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/pull_request.yml b/models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/pull_request.yml index 93f27c747c..7e7c0d1ccd 100644 --- a/models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/pull_request.yml +++ b/models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/pull_request.yml @@ -1,7 +1,7 @@ - id: 1001 type: 0 # pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 1001 index: 1001 head_repo_id: 1 diff --git a/models/fixtures/commit_status.yml b/models/fixtures/commit_status.yml index 20d57975ef..6b82e3fd67 100644 --- a/models/fixtures/commit_status.yml +++ b/models/fixtures/commit_status.yml @@ -15,7 +15,7 @@ repo_id: 1 state: "warning" sha: "1234123412341234123412341234123412341234" - target_url: https://example.com/converage/ + target_url: https://example.com/coverage/ description: My awesome Coverage service context: cov/awesomeness creator_id: 2 @@ -26,7 +26,7 @@ repo_id: 1 state: "success" sha: "1234123412341234123412341234123412341234" - target_url: https://example.com/converage/ + target_url: https://example.com/coverage/ description: My awesome Coverage service context: cov/awesomeness creator_id: 2 diff --git a/models/fixtures/pull_request.yml b/models/fixtures/pull_request.yml index 3fc8ce630d..9a16316e5a 100644 --- a/models/fixtures/pull_request.yml +++ b/models/fixtures/pull_request.yml @@ -1,7 +1,7 @@ - id: 1 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 2 index: 2 head_repo_id: 1 @@ -16,7 +16,7 @@ - id: 2 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 3 index: 3 head_repo_id: 1 @@ -29,7 +29,7 @@ - id: 3 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 8 index: 1 head_repo_id: 11 @@ -42,7 +42,7 @@ - id: 4 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 9 index: 1 head_repo_id: 48 @@ -55,7 +55,7 @@ - id: 5 # this PR is outdated (one commit behind branch1 ) type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 11 index: 5 head_repo_id: 1 @@ -68,7 +68,7 @@ - id: 6 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 12 index: 2 head_repo_id: 3 @@ -81,7 +81,7 @@ - id: 7 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 19 index: 1 head_repo_id: 58 @@ -94,7 +94,7 @@ - id: 8 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 20 index: 1 head_repo_id: 23 @@ -103,7 +103,7 @@ - id: 9 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 21 index: 1 head_repo_id: 60 @@ -112,7 +112,7 @@ - id: 10 type: 0 # gitea pull request - status: 2 # mergable + status: 2 # mergeable issue_id: 22 index: 1 head_repo_id: 61 diff --git a/models/issues/label_test.go b/models/issues/label_test.go index 517a3cf1ab..38e1560649 100644 --- a/models/issues/label_test.go +++ b/models/issues/label_test.go @@ -234,7 +234,7 @@ func TestGetLabelsByIssueID(t *testing.T) { func TestUpdateLabel(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) - // make sure update wont overwrite it + // make sure update won't overwrite it update := &issues_model.Label{ ID: label.ID, Color: "#ffff00", diff --git a/models/issues/pull.go b/models/issues/pull.go index dc1b1b956a..4194df2e3d 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -807,7 +807,7 @@ func UpdateAllowEdits(ctx context.Context, pr *PullRequest) error { // Mergeable returns if the pullrequest is mergeable. func (pr *PullRequest) Mergeable(ctx context.Context) bool { - // If a pull request isn't mergable if it's: + // If a pull request isn't mergeable if it's: // - Being conflict checked. // - Has a conflict. // - Received a error while being conflict checked. diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go index 4063ca043b..caa582a9fc 100644 --- a/models/issues/tracked_time.go +++ b/models/issues/tracked_time.go @@ -187,8 +187,8 @@ func AddTime(ctx context.Context, user *user_model.User, issue *Issue, amount in Issue: issue, Repo: issue.Repo, Doer: user, - // Content before v1.21 did store the formated string instead of seconds, - // so use "|" as delimeter to mark the new format + // Content before v1.21 did store the formatted string instead of seconds, + // so use "|" as delimiter to mark the new format Content: fmt.Sprintf("|%d", amount), Type: CommentTypeAddTimeManual, TimeID: t.ID, @@ -267,8 +267,8 @@ func DeleteIssueUserTimes(ctx context.Context, issue *Issue, user *user_model.Us Issue: issue, Repo: issue.Repo, Doer: user, - // Content before v1.21 did store the formated string instead of seconds, - // so use "|" as delimeter to mark the new format + // Content before v1.21 did store the formatted string instead of seconds, + // so use "|" as delimiter to mark the new format Content: fmt.Sprintf("|%d", removedTime), Type: CommentTypeDeleteTimeManual, }); err != nil { @@ -298,8 +298,8 @@ func DeleteTime(ctx context.Context, t *TrackedTime) error { Issue: t.Issue, Repo: t.Issue.Repo, Doer: t.User, - // Content before v1.21 did store the formated string instead of seconds, - // so use "|" as delimeter to mark the new format + // Content before v1.21 did store the formatted string instead of seconds, + // so use "|" as delimiter to mark the new format Content: fmt.Sprintf("|%d", t.Time), Type: CommentTypeDeleteTimeManual, }); err != nil { diff --git a/models/migrations/v1_17/v216.go b/models/migrations/v1_17/v216.go index 59b21d9b2c..268f472a42 100644 --- a/models/migrations/v1_17/v216.go +++ b/models/migrations/v1_17/v216.go @@ -4,4 +4,4 @@ package v1_17 //nolint // This migration added non-ideal indices to the action table which on larger datasets slowed things down -// it has been superceded by v218.go +// it has been superseded by v218.go diff --git a/models/repo/archive_download_count.go b/models/repo/archive_download_count.go index 9c1382e0ac..31f0399d53 100644 --- a/models/repo/archive_download_count.go +++ b/models/repo/archive_download_count.go @@ -36,7 +36,7 @@ func CountArchiveDownload(ctx context.Context, repoID, releaseID int64, tp git.A return nil } - // The archive does not esxists in the databse, so let's add it + // The archive does not esxists in the database, so let's add it newCounter := &RepoArchiveDownloadCount{ RepoID: repoID, ReleaseID: releaseID, diff --git a/models/user/setting_keys.go b/models/user/setting_keys.go index 72b3974eee..0e2c93695a 100644 --- a/models/user/setting_keys.go +++ b/models/user/setting_keys.go @@ -8,7 +8,7 @@ const ( SettingsKeyHiddenCommentTypes = "issue.hidden_comment_types" // SettingsKeyDiffWhitespaceBehavior is the setting key for whitespace behavior of diff SettingsKeyDiffWhitespaceBehavior = "diff.whitespace_behaviour" - // SettingsKeyShowOutdatedComments is the setting key wether or not to show outdated comments in PRs + // SettingsKeyShowOutdatedComments is the setting key whether or not to show outdated comments in PRs SettingsKeyShowOutdatedComments = "comment_code.show_outdated" // UserActivityPubPrivPem is user's private key UserActivityPubPrivPem = "activitypub.priv_pem" diff --git a/modules/avatar/identicon/identicon.go b/modules/avatar/identicon/identicon.go index 63926d5f19..40471565d6 100644 --- a/modules/avatar/identicon/identicon.go +++ b/modules/avatar/identicon/identicon.go @@ -69,7 +69,7 @@ func (i *Identicon) render(c, b1, b2, b1Angle, b2Angle, foreColor int) image.Ima /* # Algorithm -Origin: An image is splitted into 9 areas +Origin: An image is split into 9 areas ``` ------------- diff --git a/modules/git/ref.go b/modules/git/ref.go index ed801f20d5..2db630e2ea 100644 --- a/modules/git/ref.go +++ b/modules/git/ref.go @@ -184,7 +184,7 @@ func (ref RefName) RefGroup() string { } // RefType returns the simple ref type of the reference, e.g. branch, tag -// It's differrent from RefGroup, which is using the name of the directory under .git/refs +// It's different from RefGroup, which is using the name of the directory under .git/refs // Here we using branch but not heads, using tag but not tags func (ref RefName) RefType() string { var refType string diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go index a0d1e9cb4f..3ccc1b84a6 100644 --- a/modules/git/repo_attribute.go +++ b/modules/git/repo_attribute.go @@ -113,7 +113,7 @@ func (ca GitAttribute) Bool() optional.Option[bool] { } // gitCheckAttrCommand prepares the "git check-attr" command for later use as one-shot or streaming -// instanciation. +// instantiation. func (repo *Repository) gitCheckAttrCommand(treeish string, attributes ...string) (*Command, *RunOpts, context.CancelFunc, error) { if len(attributes) == 0 { return nil, nil, nil, fmt.Errorf("no provided attributes to check-attr") diff --git a/modules/gitgraph/graph_models.go b/modules/gitgraph/graph_models.go index e9c1001964..82f460ecf0 100644 --- a/modules/gitgraph/graph_models.go +++ b/modules/gitgraph/graph_models.go @@ -180,7 +180,7 @@ func (flow *Flow) AddGlyph(row, column int, glyph byte) { }) } -// Glyph represents a co-ordinate and glyph +// Glyph represents a coordinate and glyph type Glyph struct { Row int Column int @@ -234,7 +234,7 @@ func newRefsFromRefNames(refNames []byte) []git.Reference { return refs } -// Commit represents a commit at co-ordinate X, Y with the data +// Commit represents a commit at coordinate X, Y with the data type Commit struct { Commit *git.Commit User *user_model.User diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index bc345f2325..c5dfe43836 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -120,7 +120,7 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio } fields := strings.Split(line, "\t") if len(fields) < 2 { - log.Warn("Unparseable output for diff --name-status: `%s`)", line) + log.Warn("Unparsable output for diff --name-status: `%s`)", line) continue } filename := fields[1] @@ -140,12 +140,12 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio changes.RemovedFilenames = append(changes.RemovedFilenames, filename) case 'R', 'C': if len(fields) < 3 { - log.Warn("Unparseable output for diff --name-status: `%s`)", line) + log.Warn("Unparsable output for diff --name-status: `%s`)", line) continue } dest := fields[2] if len(dest) == 0 { - log.Warn("Unparseable output for diff --name-status: `%s`)", line) + log.Warn("Unparsable output for diff --name-status: `%s`)", line) continue } if dest[0] == '"' { diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index 9f56cb00f2..d7310529fc 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -27,7 +27,7 @@ import ( ) // IndexerMetadata is used to send data to the queue, so it contains only the ids. -// It may look weired, because it has to be compatible with the old queue data format. +// It may look weird, because it has to be compatible with the old queue data format. // If the IsDelete flag is true, the IDs specify the issues to delete from the index without querying the database. // If the IsDelete flag is false, the ID specify the issue to index, so Indexer will query the database to get the issue data. // It should be noted that if the id is not existing in the database, it's index will be deleted too even if IsDelete is false. diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index 7144174087..66e396e02c 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -138,7 +138,7 @@ var cases = []*testIndexerCase{ {ID: 1002, Comments: []string{"hi", "hello world"}}, }, SearchOptions: &internal.SearchOptions{ - Keyword: "hello wrold", + Keyword: "hello world", IsFuzzyKeyword: true, }, ExpectedIDs: []int64{1002, 1001, 1000}, diff --git a/modules/indexer/issues/meilisearch/meilisearch_test.go b/modules/indexer/issues/meilisearch/meilisearch_test.go index 81b825ae69..3c19ac85b3 100644 --- a/modules/indexer/issues/meilisearch/meilisearch_test.go +++ b/modules/indexer/issues/meilisearch/meilisearch_test.go @@ -66,7 +66,7 @@ func TestConvertHits(t *testing.T) { "id": float64(11), "title": "a title", "content": "issue body with no match", - "comments": []any{"hey whats up?", "I'm currently bowling", "nice"}, + "comments": []any{"hey what's up?", "I'm currently bowling", "nice"}, }, map[string]any{ "id": float64(22), diff --git a/modules/log/event_format.go b/modules/log/event_format.go index d9dbebf831..583ddf66dd 100644 --- a/modules/log/event_format.go +++ b/modules/log/event_format.go @@ -204,7 +204,7 @@ func EventFormatTextMessage(mode *WriterMode, event *Event, msgFormat string, ms msg = []byte(fmt.Sprintf(msgFormat, msgArgs...)) } } - // try to re-use the pre-formatted simple text message + // try to reuse the pre-formatted simple text message if len(msg) == 0 { msg = []byte(event.MsgSimpleText) } diff --git a/modules/markup/markdown/callout/github_legacy.go b/modules/markup/markdown/callout/github_legacy.go index ce86c10356..e9aaecccfb 100644 --- a/modules/markup/markdown/callout/github_legacy.go +++ b/modules/markup/markdown/callout/github_legacy.go @@ -51,7 +51,7 @@ func (g *GitHubLegacyCalloutTransformer) Transform(node *ast.Document, reader te // color the blockquote v.SetAttributeString("class", []byte("attention-header attention-"+calloutType)) - // Create new parargaph. + // Create new paragraph. attentionParagraph := ast.NewParagraph() attentionParagraph.SetAttributeString("class", []byte("attention-title")) diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 278494d95c..1e25df4320 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -470,7 +470,7 @@ func TestColorPreview(t *testing.T) { // no backticks "rgb(166, 32, 64)", // typo - "`hsI(0, 100%, 50%)`", + "`hsI(0, 100%, 50%)`", // codespell-ignore // looks like a color but not really "`hsl(40, 60, 80)`", } diff --git a/modules/process/manager.go b/modules/process/manager.go index 150179d89b..37098ad92f 100644 --- a/modules/process/manager.go +++ b/modules/process/manager.go @@ -134,7 +134,7 @@ func (pm *Manager) AddTypedContext(parent context.Context, description, processT // // Most processes will not need to use the cancel function but there will be cases whereby you want to cancel the process but not immediately remove it from the // process table. -func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finshed FinishedFunc) { +func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finished FinishedFunc) { if timeout <= 0 { // it's meaningless to use timeout <= 0, and it must be a bug! so we must panic here to tell developers to make the timeout correct panic("the timeout must be greater than zero, otherwise the context will be cancelled immediately") @@ -142,9 +142,9 @@ func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Durati ctx, cancel = context.WithTimeout(parent, timeout) - ctx, _, finshed = pm.Add(ctx, description, cancel, NormalProcessType, true) + ctx, _, finished = pm.Add(ctx, description, cancel, NormalProcessType, true) - return ctx, cancel, finshed + return ctx, cancel, finished } // Add create a new process diff --git a/modules/queue/queue.go b/modules/queue/queue.go index 577fd4d498..56835014a5 100644 --- a/modules/queue/queue.go +++ b/modules/queue/queue.go @@ -22,7 +22,7 @@ // // 4. Handler (represented by HandlerFuncT type): // - It's the function responsible for processing items. Each active worker will call it. -// - If an item or some items are not psuccessfully rocessed, the handler could return them as "unhandled items". +// - If an item or some items are not successfully processed, the handler could return them as "unhandled items". // In such scenarios, the queue system ensures these unhandled items are returned to the base queue after a brief delay. // This mechanism is particularly beneficial in cases where the processing entity (like a document indexer) is // temporarily unavailable. It ensures that no item is skipped or lost due to transient failures in the processing diff --git a/modules/templates/helper_test.go b/modules/templates/helper_test.go index 64f29d033e..0cefb7a6b2 100644 --- a/modules/templates/helper_test.go +++ b/modules/templates/helper_test.go @@ -49,9 +49,9 @@ func TestSubjectBodySeparator(t *testing.T) { test("Multiple\n---\n-------\n---\nSeparators", "Multiple\n", "\n-------\n---\nSeparators") - test("Insuficient\n--\nSeparators", + test("Insufficient\n--\nSeparators", "", - "Insuficient\n--\nSeparators") + "Insufficient\n--\nSeparators") } func TestJSEscapeSafe(t *testing.T) { diff --git a/modules/testlogger/testlogger.go b/modules/testlogger/testlogger.go index 2861f61adf..95cbb86591 100644 --- a/modules/testlogger/testlogger.go +++ b/modules/testlogger/testlogger.go @@ -248,11 +248,11 @@ var ignoredErrorMessage = []string{ // TestIssuePinMove `:IssuePinMove() [E] Issue does not belong to this repository`, // TestLinksLogin - `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, // TestLinksLogin - `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, // TestLinksLogin - `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + `:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, // TestLinksLogin `:GetIssuesAllCommitStatus() [E] Cannot open git repository for issue #1[20]. Error: no such file or directory`, // TestMigrate diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index 731fac11e7..da662ab99d 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -49,12 +49,12 @@ func TestIsSvgImage(t *testing.T) { `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `)).IsSvgImage()) diff --git a/modules/util/path.go b/modules/util/path.go index 1272f5af2e..185e7cf882 100644 --- a/modules/util/path.go +++ b/modules/util/path.go @@ -45,7 +45,7 @@ func PathJoinRel(elem ...string) string { } // PathJoinRelX joins the path elements into a single path like PathJoinRel, -// and covert all backslashes to slashes. (X means "extended", also means the combination of `\` and `/`). +// and convert all backslashes to slashes. (X means "extended", also means the combination of `\` and `/`). // It's caller's duty to make every element not bypass its own directly level, to avoid security issues. // It returns similar results as PathJoinRel except: // diff --git a/poetry.lock b/poetry.lock index 951a0fa7a8..b07d161a4c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,6 +14,23 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "codespell" +version = "2.2.6" +description = "Codespell" +optional = false +python-versions = ">=3.8" +files = [ + {file = "codespell-2.2.6-py3-none-any.whl", hash = "sha256:9ee9a3e5df0990604013ac2a9f22fa8e57669c827124a2e961fe8a1da4cacc07"}, + {file = "codespell-2.2.6.tar.gz", hash = "sha256:a8c65d8eb3faa03deabab6b3bbe798bea72e1799c7e9e955d57eca4096abcff9"}, +] + +[package.extras] +dev = ["Pygments", "build", "chardet", "pre-commit", "pytest", "pytest-cov", "pytest-dependency", "ruff", "tomli", "twine"] +hard-encoding-detection = ["chardet"] +toml = ["tomli"] +types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency"] + [[package]] name = "colorama" version = "0.4.6" @@ -158,6 +175,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -357,4 +375,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "cd2ff218e9f27a464dfbc8ec2387824a90f4360e04c3f2e58cc375796b7df33a" +content-hash = "758325127b0a863bf7d1f0dbc50e3740c47ffe0073ff60fc6d7dce9759879125" diff --git a/pyproject.toml b/pyproject.toml index 323307c1dc..fb92f611aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,21 @@ python = "^3.10" [tool.poetry.group.dev.dependencies] djlint = "1.34.1" yamllint = "1.35.1" +codespell = "^2.2.6" [tool.djlint] profile="golang" ignore="H005,H006,H013,H016,H020,H021,H030,H031" + +[tool.codespell] +skip = '.git,*.pdf,*.svg,package-lock.json,go.mod,locale,license,*.git,objects,*.fr-fr.*,*.de-de.*,*.css,go.sum,*.key,gitignore,pyproject.toml,diff_test.go,go-licenses.json,pyproject.toml,*.lock,venvs' +# precise hits for CamelCased words,various other curious cases which require regex to ignore +# entire line or some portion of it +# TODO: Resolve Treshold typo in API and remove from here +ignore-regex = '(\b(Treshold|mx claus|commitT|ReadBy|#afile|respOne|commitI|[cC]rossReference)\b|shouldbe\.|women’s.*womens|"emoji":.*|,bu,|assert\.Equal.*"fo\b|github\.com/unknwon|Copyright 2014 Unknwon|allowed\.noone|[hH]eadErr|atLeast|{"\\U.*)|Iif|FilterIn|.*codespell-ignore.*' +#|.*(Maskenpflicht|Geimpft),.*)' +# te - TreeEntry variable +# commiter - wrong spelling but seems used in API +# ALLWAYS - is a config var +# infact - other variable(s) +ignore-words-list = 'crate,te,commiter,befores,allways,infact,startd,unknow' diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index 416d7e5181..7225d67135 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -301,7 +301,7 @@ func (ar artifactRoutes) uploadArtifact(ctx *ArtifactContext) { }) } -// comfirmUploadArtifact comfirm upload artifact. +// comfirmUploadArtifact confirm upload artifact. // if all chunks are uploaded, merge them to one file. func (ar artifactRoutes) comfirmUploadArtifact(ctx *ArtifactContext) { _, runID, ok := validateRunID(ctx) diff --git a/routers/api/actions/runner/interceptor.go b/routers/api/actions/runner/interceptor.go index c2f4ade174..0e99f3deda 100644 --- a/routers/api/actions/runner/interceptor.go +++ b/routers/api/actions/runner/interceptor.go @@ -36,7 +36,7 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar uuid := request.Header().Get(uuidHeaderKey) token := request.Header().Get(tokenHeaderKey) // TODO: version will be removed from request header after Gitea 1.20 released. - // And Gitea will not try to read version from reuqest header + // And Gitea will not try to read version from request header version := request.Header().Get(versionHeaderKey) runner, err := actions_model.GetRunnerByUUID(ctx, uuid) @@ -53,7 +53,7 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar cols := []string{"last_online"} // TODO: version will be removed from request header after Gitea 1.20 released. - // And Gitea will not try to read version from reuqest header + // And Gitea will not try to read version from request header version, _ = util.SplitStringAtByteN(version, 64) if !util.IsEmptyString(version) && runner.Version != version { runner.Version = version diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index 1e1ed69011..bbffa9acfb 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -162,7 +162,7 @@ func (s *Service) FetchTask( if tasksVersion != latestVersion { // if the task version in request is not equal to the version in db, - // it means there may still be some tasks not be assgined. + // it means there may still be some tasks not be assigned. // try to pick a task for the runner that send the request. if t, ok, err := pickTask(ctx, runner); err != nil { log.Error("pick task failed: %v", err) diff --git a/routers/api/packages/README.md b/routers/api/packages/README.md index 533a0d32f0..74d14922cb 100644 --- a/routers/api/packages/README.md +++ b/routers/api/packages/README.md @@ -19,7 +19,7 @@ The package registry code is divided into multiple modules to split the function ## Models -Every package registry implementation uses the same underlaying models: +Every package registry implementation uses the same underlying models: | Model | Description | | - | - | diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index b62a386fd7..da4fc13ea1 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -805,7 +805,7 @@ func SearchTeam(ctx *context.APIContext) { ListOptions: listOptions, } - // Only admin is allowd to search for all teams + // Only admin is allowed to search for all teams if !ctx.Doer.IsAdmin { opts.UserID = ctx.Doer.ID } diff --git a/routers/api/v1/repo/git_ref.go b/routers/api/v1/repo/git_ref.go index 0fa58425b8..54da5eeaa7 100644 --- a/routers/api/v1/repo/git_ref.go +++ b/routers/api/v1/repo/git_ref.go @@ -33,7 +33,7 @@ func GetGitAllRefs(ctx *context.APIContext) { // required: true // responses: // "200": - // # "$ref": "#/responses/Reference" TODO: swagger doesnt support different output formats by ref + // # "$ref": "#/responses/Reference" TODO: swagger doesn't support different output formats by ref // "$ref": "#/responses/ReferenceList" // "404": // "$ref": "#/responses/notFound" @@ -66,7 +66,7 @@ func GetGitRefs(ctx *context.APIContext) { // required: true // responses: // "200": - // # "$ref": "#/responses/Reference" TODO: swagger doesnt support different output formats by ref + // # "$ref": "#/responses/Reference" TODO: swagger doesn't support different output formats by ref // "$ref": "#/responses/ReferenceList" // "404": // "$ref": "#/responses/notFound" diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 2b4342dbd1..83a02dcb0d 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -411,8 +411,8 @@ func ListIssues(ctx *context.APIContext) { } var labelIDs []int64 - if splitted := strings.Split(ctx.FormString("labels"), ","); len(splitted) > 0 { - labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, splitted) + if split := strings.Split(ctx.FormString("labels"), ","); len(split) > 0 { + labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, split) if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err) return diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go index a535172462..6b29218575 100644 --- a/routers/api/v1/repo/issue_subscription.go +++ b/routers/api/v1/repo/issue_subscription.go @@ -138,7 +138,7 @@ func setIssueSubscription(ctx *context.APIContext, watch bool) { return } - // If watch state wont change + // If watch state won't change if current == watch { ctx.Status(http.StatusOK) return diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index da9fa20082..f06f6071e9 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -420,7 +420,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r }) return } - log.Error("Unable to check if mergable: protected branch %s in %-v and pr #%d. Error: %v", ctx.opts.UserID, branchName, repo, pr.Index, err) + log.Error("Unable to check if mergeable: protected branch %s in %-v and pr #%d. Error: %v", ctx.opts.UserID, branchName, repo, pr.Index, err) ctx.JSON(http.StatusInternalServerError, private.Response{ Err: fmt.Sprintf("Unable to get status of pull request %d. Error: %v", ctx.opts.PullRequestID, err), }) diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go index c5454db71e..cea28f8220 100644 --- a/routers/web/admin/orgs.go +++ b/routers/web/admin/orgs.go @@ -30,7 +30,7 @@ func Organizations(ctx *context.Context) { explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{ Actor: ctx.Doer, Type: user_model.UserTypeOrganization, - IncludeReserved: true, // administrator needs to list all acounts include reserved + IncludeReserved: true, // administrator needs to list all accounts include reserved ListOptions: db.ListOptions{ PageSize: setting.UI.Admin.OrgPagingNum, }, diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 15bd667a4f..ddd7045eb7 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -81,7 +81,7 @@ func Users(ctx *context.Context) { IsRestricted: util.OptionalBoolParse(statusFilterMap["is_restricted"]), IsTwoFactorEnabled: util.OptionalBoolParse(statusFilterMap["is_2fa_enabled"]), IsProhibitLogin: util.OptionalBoolParse(statusFilterMap["is_prohibit_login"]), - IncludeReserved: true, // administrator needs to list all acounts include reserved, bot, remote ones + IncludeReserved: true, // administrator needs to list all accounts include reserved, bot, remote ones ExtraParamStrings: extraParamStrings, }, tplUsers) } diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index dc21f1a4ed..e3e0fce3b2 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -200,7 +200,7 @@ func ViewPost(ctx *context_module.Context) { resp.State.Run.CanRerun = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions) resp.State.Run.CanDeleteArtifact = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions) resp.State.Run.Done = run.Status.IsDone() - resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json + resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead of 'null' in json resp.State.Run.Status = run.Status.String() for _, v := range jobs { resp.State.Run.Jobs = append(resp.State.Run.Jobs, &ViewJob{ @@ -250,8 +250,8 @@ func ViewPost(ctx *context_module.Context) { if run.NeedApproval { resp.State.CurrentJob.Detail = ctx.Locale.TrString("actions.need_approval_desc") } - resp.State.CurrentJob.Steps = make([]*ViewJobStep, 0) // marshal to '[]' instead fo 'null' in json - resp.Logs.StepsLog = make([]*ViewStepLog, 0) // marshal to '[]' instead fo 'null' in json + resp.State.CurrentJob.Steps = make([]*ViewJobStep, 0) // marshal to '[]' instead of 'null' in json + resp.Logs.StepsLog = make([]*ViewStepLog, 0) // marshal to '[]' instead of 'null' in json if task != nil { steps := actions.FullSteps(task) @@ -270,7 +270,7 @@ func ViewPost(ctx *context_module.Context) { step := steps[cursor.Step] - logLines := make([]*ViewStepLogLine, 0) // marshal to '[]' instead fo 'null' in json + logLines := make([]*ViewStepLogLine, 0) // marshal to '[]' instead of 'null' in json index := step.LogIndex + cursor.Cursor validCursor := cursor.Cursor >= 0 && diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index a61e23add3..2a9f60891e 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -812,7 +812,7 @@ func CompareDiff(ctx *context.Context) { // applicable if you have one commit to compare and that commit has a message. // In that case the commit message will be prepend to the template body. if templateContent, ok := ctx.Data[pullRequestTemplateKey].(string); ok && templateContent != "" { - // Re-use the same key as that's priortized over the "content" key. + // Reuse the same key as that's prioritized over the "content" key. // Add two new lines between the content to ensure there's always at least // one empty line between them. ctx.Data[pullRequestTemplateKey] = content + "\n\n" + templateContent diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 97f2195116..9f4979cb67 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1759,8 +1759,8 @@ func ViewIssue(ctx *context.Context) { // drop error since times could be pruned from DB.. _ = comment.LoadTime(ctx) if comment.Content != "" { - // Content before v1.21 did store the formated string instead of seconds, - // so "|" is used as delimeter to mark the new format + // Content before v1.21 did store the formatted string instead of seconds, + // so "|" is used as delimiter to mark the new format if comment.Content[0] != '|' { // handle old time comments that have formatted text stored comment.RenderedContent = templates.SanitizeHTML(comment.Content) @@ -2752,8 +2752,8 @@ func ListIssues(ctx *context.Context) { } var labelIDs []int64 - if splitted := strings.Split(ctx.FormString("labels"), ","); len(splitted) > 0 { - labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, splitted) + if split := strings.Split(ctx.FormString("labels"), ","); len(split) > 0 { + labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, split) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 1893e91221..64ce93b6cf 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -392,6 +392,6 @@ func Action(ctx *context.Context) { ctx.HTML(http.StatusOK, tplFollowUnfollow) return } - log.Error("Failed to apply action %q: unsupport context user type: %s", ctx.FormString("action"), ctx.ContextUser.Type) + log.Error("Failed to apply action %q: unsupported context user type: %s", ctx.FormString("action"), ctx.ContextUser.Type) ctx.Error(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action"))) } diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 2f5d76a293..8fb569939c 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -75,7 +75,7 @@ type ErrWontSign struct { } func (e *ErrWontSign) Error() string { - return fmt.Sprintf("wont sign: %s", e.Reason) + return fmt.Sprintf("won't sign: %s", e.Reason) } // IsErrWontSign checks if an error is a ErrWontSign diff --git a/services/context/csrf.go b/services/context/csrf.go index 9b0dc2923b..57c55e6550 100644 --- a/services/context/csrf.go +++ b/services/context/csrf.go @@ -179,7 +179,7 @@ func PrepareCSRFProtector(opt CsrfOptions, ctx *Context) CSRFProtector { if uidChanged { _ = ctx.Session.Set(opt.oldSessionKey, x.ID) } else if cookieToken != "" { - // If cookie token presents, re-use existing unexpired token, else generate a new one. + // If cookie token presents, reuse existing unexpired token, else generate a new one. if issueTime, ok := ParseCsrfToken(cookieToken); ok { dur := time.Since(issueTime) // issueTime is not a monotonic-clock, the server time may change a lot to an early time. if dur >= -CsrfTokenRegenerationInterval && dur <= CsrfTokenRegenerationInterval { diff --git a/services/convert/issue_comment.go b/services/convert/issue_comment.go index 9ffaf1e84c..9ec9ac7684 100644 --- a/services/convert/issue_comment.go +++ b/services/convert/issue_comment.go @@ -72,8 +72,8 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu c.Type == issues_model.CommentTypeStopTracking || c.Type == issues_model.CommentTypeDeleteTimeManual) && c.Content[0] == '|' { - // TimeTracking Comments from v1.21 on store the seconds instead of an formated string - // so we check for the "|" delimeter and convert new to legacy format on demand + // TimeTracking Comments from v1.21 on store the seconds instead of an formatted string + // so we check for the "|" delimiter and convert new to legacy format on demand c.Content = util.SecToTime(c.Content[1:]) } } diff --git a/services/doctor/dbconsistency.go b/services/doctor/dbconsistency.go index 6b931b7036..e3992a5ba5 100644 --- a/services/doctor/dbconsistency.go +++ b/services/doctor/dbconsistency.go @@ -76,7 +76,7 @@ func genericOrphanCheck(name, subject, refobject, joincond string) consistencyCh } func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) error { - // make sure DB version is uptodate + // make sure DB version is up-to-date if err := db.InitEngineWithMigration(ctx, migrations.EnsureUpToDate); err != nil { logger.Critical("Model version on the database does not match the current Gitea version. Model consistency will not be checked until the database is upgraded") return err diff --git a/services/issue/assignee.go b/services/issue/assignee.go index 8740a6664a..9c2ef74bb0 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -231,8 +231,8 @@ func TeamReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *use func ReviewRequestNotify(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, reviewNotifers []*ReviewRequestNotifier) { for _, reviewNotifer := range reviewNotifers { - if reviewNotifer.Reviwer != nil { - notify_service.PullRequestReviewRequest(ctx, issue.Poster, issue, reviewNotifer.Reviwer, reviewNotifer.IsAdd, reviewNotifer.Comment) + if reviewNotifer.Reviewer != nil { + notify_service.PullRequestReviewRequest(ctx, issue.Poster, issue, reviewNotifer.Reviewer, reviewNotifer.IsAdd, reviewNotifer.Comment) } else if reviewNotifer.ReviewTeam != nil { if err := teamReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifer.ReviewTeam, reviewNotifer.IsAdd, reviewNotifer.Comment); err != nil { log.Error("teamReviewRequestNotify: %v", err) diff --git a/services/issue/pull.go b/services/issue/pull.go index b7b63a7024..c5a12ce7c4 100644 --- a/services/issue/pull.go +++ b/services/issue/pull.go @@ -36,7 +36,7 @@ func getMergeBase(repo *git.Repository, pr *issues_model.PullRequest, baseBranch type ReviewRequestNotifier struct { Comment *issues_model.Comment IsAdd bool - Reviwer *user_model.User + Reviewer *user_model.User ReviewTeam *org_model.Team } @@ -124,9 +124,9 @@ func PullRequestCodeOwnersReview(ctx context.Context, issue *issues_model.Issue, return nil, err } notifiers = append(notifiers, &ReviewRequestNotifier{ - Comment: comment, - IsAdd: true, - Reviwer: u, + Comment: comment, + IsAdd: true, + Reviewer: u, }) } } diff --git a/services/mailer/incoming/incoming_handler.go b/services/mailer/incoming/incoming_handler.go index 325b94ae09..c7e2193fc5 100644 --- a/services/mailer/incoming/incoming_handler.go +++ b/services/mailer/incoming/incoming_handler.go @@ -104,7 +104,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u } if content.Content == "" && len(attachmentIDs) == 0 { - log.Trace("incoming mail has no content and no attachement", ref) + log.Trace("incoming mail has no content and no attachment", ref) return nil } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 21a9c53a5c..1704b2330e 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -885,7 +885,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { } for _, comment := range review.Comments { - // Skip code comment if it doesn't have a diff it is commeting on. + // Skip code comment if it doesn't have a diff it is commenting on. if comment.DiffHunk == "" { continue } diff --git a/services/migrations/github.go b/services/migrations/github.go index be573b33b3..78abe9dbbb 100644 --- a/services/migrations/github.go +++ b/services/migrations/github.go @@ -305,7 +305,7 @@ func (g *GithubDownloaderV3) GetLabels() ([]*base.Label, error) { } func (g *GithubDownloaderV3) convertGithubRelease(rel *github.RepositoryRelease) *base.Release { - // GitHub allows commitish to be a reference. + // GitHub allows committish to be a reference. // In this case, we need to remove the prefix, i.e. convert "refs/heads/main" to "main". targetCommitish := strings.TrimPrefix(rel.GetTargetCommitish(), git.BranchPrefix) diff --git a/services/pull/check.go b/services/pull/check.go index 9aab3c94f3..5cca0e1f28 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -66,7 +66,7 @@ const ( MergeCheckTypeAuto // Auto Merge (Scheduled Merge) After Checks Succeed ) -// CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...) +// CheckPullMergable check if the pull mergeable based on all conditions (branch protection, merge options, ...) func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error { return db.WithTx(stdCtx, func(ctx context.Context) error { if pr.HasMerged { diff --git a/services/pull/comment.go b/services/pull/comment.go index d538b118d5..53587d4f54 100644 --- a/services/pull/comment.go +++ b/services/pull/comment.go @@ -46,7 +46,7 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC return commitIDs, isForcePush, err } - // Find commits between new and old commit exclusing base branch commits + // Find commits between new and old commit excluding base branch commits commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch) if err != nil { return nil, false, err diff --git a/services/pull/pull.go b/services/pull/pull.go index 5fa426483f..a38522977b 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -881,7 +881,7 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList statuses, lastStatus, err := getAllCommitStatus(ctx, gitRepo, issue.PullRequest) if err != nil { - log.Error("getAllCommitStatus: cant get commit statuses of pull [%d]: %v", issue.PullRequest.ID, err) + log.Error("getAllCommitStatus: can't get commit statuses of pull [%d]: %v", issue.PullRequest.ID, err) continue } res[issue.PullRequest.ID] = statuses diff --git a/services/remote/promote.go b/services/remote/promote.go index 6709b4cc1d..5402c946d7 100644 --- a/services/remote/promote.go +++ b/services/remote/promote.go @@ -57,7 +57,7 @@ func getUsersByLoginName(ctx context.Context, name string) ([]*user_model.User, // LoginName set to the unique identifier of the originating authentication source // LoginSource set to the Remote source that can be matched against an OAuth2 source // -// If the source from which an authentification happens is OAuth2, an existing +// If the source from which an authentication happens is OAuth2, an existing // remote user will be promoted to an OAuth2 user provided: // // user.LoginName is the same as goth.UserID (argument loginName) diff --git a/services/repository/commitstatus/commitstatus.go b/services/repository/commitstatus/commitstatus.go index 1944f11f03..f0f8450b03 100644 --- a/services/repository/commitstatus/commitstatus.go +++ b/services/repository/commitstatus/commitstatus.go @@ -125,7 +125,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato return nil } -// FindReposLastestCommitStatuses loading repository default branch latest combinded commit status with cache +// FindReposLastestCommitStatuses loading repository default branch latest combined commit status with cache func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Repository) ([]*git_model.CommitStatus, error) { if len(repos) == 0 { return nil, nil diff --git a/services/repository/contributors_graph.go b/services/repository/contributors_graph.go index 7241d3d655..f26a87e6ac 100644 --- a/services/repository/contributors_graph.go +++ b/services/repository/contributors_graph.go @@ -86,7 +86,7 @@ func GetContributorStats(ctx context.Context, cache cache.Cache, repo *repo_mode if !cache.IsExist(cacheKey) { genReady := make(chan struct{}) - // dont start multible async generations + // dont start multiple async generations _, run := generateLock.Load(cacheKey) if run { return nil, ErrAwaitGeneration diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index ad3419793e..c0caf34d53 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -2,7 +2,7 @@ - {{/* Display `- .Repsository.FullName` only if `.Title` does not already start with that. */}} + {{/* Display `- .Repository.FullName` only if `.Title` does not already start with that. */}} {{if .Title}}{{.Title}} - {{end}}{{if and (.Repository.Name) (not (StringUtils.HasPrefix .Title .Repository.FullName))}}{{.Repository.FullName}} - {{end}}{{AppName}} {{if .ManifestData}}{{end}} diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index 77cccd65b7..b047e74d81 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -106,7 +106,7 @@
{{.CommitsBehind}}
- {{/* old code bears 0/0.0 = NaN output, so it might output invalid "width: NaNpx", it just works and doesn't caues any problem. */}} + {{/* old code bears 0/0.0 = NaN output, so it might output invalid "width: NaNpx", it just works and doesn't cause any problem. */}}
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl index c8e2fbe845..ed2f1ae0cd 100644 --- a/templates/repo/issue/milestone_issues.tmpl +++ b/templates/repo/issue/milestone_issues.tmpl @@ -29,7 +29,7 @@
-
+
{{$closedDate:= TimeSinceUnix .Milestone.ClosedDateUnix ctx.Locale}} {{if .IsClosed}} {{svg "octicon-clock"}} {{ctx.Locale.Tr "repo.milestones.closed" $closedDate}} diff --git a/tests/integration/README.md b/tests/integration/README.md index d659d51b20..c40f47452b 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -21,7 +21,7 @@ make clean build act_runner exec -W ./.github/workflows/pull-db-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest ``` -Warning: This file defines many jobs, so it will be resource-intensive and therefor not recommended. +Warning: This file defines many jobs, so it will be resource-intensive and therefore not recommended. ### Run single job diff --git a/tests/integration/actions_commit_status_test.go b/tests/integration/actions_commit_status_test.go index 3d191a283f..1bd1e325b6 100644 --- a/tests/integration/actions_commit_status_test.go +++ b/tests/integration/actions_commit_status_test.go @@ -31,7 +31,7 @@ func TestActionsAutomerge(t *testing.T) { job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: 292}) assert.False(t, pr.HasMerged, "PR should not be merged") - assert.Equal(t, issues_model.PullRequestStatusMergeable, pr.Status, "PR should be mergable") + assert.Equal(t, issues_model.PullRequestStatusMergeable, pr.Status, "PR should be mergeable") scheduled, err := automerge.ScheduleAutoMerge(ctx, user, pr, repo_model.MergeStyleMerge, "Dummy") diff --git a/tests/integration/api_issue_config_test.go b/tests/integration/api_issue_config_test.go index d37036381e..245114700f 100644 --- a/tests/integration/api_issue_config_test.go +++ b/tests/integration/api_issue_config_test.go @@ -134,9 +134,9 @@ func TestAPIRepoIssueConfigPaths(t *testing.T) { ".github/issue_template/config", } - for _, canidate := range templateConfigCandidates { + for _, candidate := range templateConfigCandidates { for _, extension := range []string{".yaml", ".yml"} { - fullPath := canidate + extension + fullPath := candidate + extension t.Run(fullPath, func(t *testing.T) { defer tests.PrintCurrentTest(t)() diff --git a/tests/integration/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go index c7ed554a9d..b6c213abcf 100644 --- a/tests/integration/api_packages_maven_test.go +++ b/tests/integration/api_packages_maven_test.go @@ -107,7 +107,7 @@ func TestPackageMaven(t *testing.T) { t.Run("UploadVerifySHA1", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - t.Run("Missmatch", func(t *testing.T) { + t.Run("Mismatch", func(t *testing.T) { defer tests.PrintCurrentTest(t)() putFile(t, fmt.Sprintf("/%s/%s.sha1", packageVersion, filename), "test", http.StatusBadRequest) diff --git a/tests/integration/compare_test.go b/tests/integration/compare_test.go index 0929e8938e..88a7c761dc 100644 --- a/tests/integration/compare_test.go +++ b/tests/integration/compare_test.go @@ -75,7 +75,7 @@ func TestCompareBranches(t *testing.T) { session := loginUser(t, "user2") - // Inderect compare remove-files-b (head) with add-csv (base) branch + // Indirect compare remove-files-b (head) with add-csv (base) branch // // 'link_hi' and 'test.csv' are deleted, 'test.txt' is added req := NewRequest(t, "GET", "/user2/repo20/compare/add-csv...remove-files-b") @@ -87,7 +87,7 @@ func TestCompareBranches(t *testing.T) { inspectCompare(t, htmlDoc, diffCount, diffChanges) - // Inderect compare remove-files-b (head) with remove-files-a (base) branch + // Indirect compare remove-files-b (head) with remove-files-a (base) branch // // 'link_hi' and 'test.csv' are deleted, 'test.txt' is added @@ -100,7 +100,7 @@ func TestCompareBranches(t *testing.T) { inspectCompare(t, htmlDoc, diffCount, diffChanges) - // Inderect compare remove-files-a (head) with remove-files-b (base) branch + // Indirect compare remove-files-a (head) with remove-files-b (base) branch // // 'link_hi' and 'test.csv' are deleted @@ -138,7 +138,7 @@ func TestCompareWithPRsDisabled(t *testing.T) { assert.NoError(t, err) defer func() { - // Reenable PRs on the repo + // Re-enable PRs on the repo err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, []repo_model.RepoUnit{{ RepoID: repo.ID, diff --git a/tests/integration/editor_test.go b/tests/integration/editor_test.go index ae0aea237b..5c9595b802 100644 --- a/tests/integration/editor_test.go +++ b/tests/integration/editor_test.go @@ -405,7 +405,7 @@ func TestCommitMail(t *testing.T) { defer tests.PrintCurrentTest(t)() // Upload two separate times, so we have two different 'uploads' that can - // be used indepently of each other. + // be used independently of each other. uploadFile := func(t *testing.T, name, content string) string { t.Helper() diff --git a/tests/integration/pull_reopen_test.go b/tests/integration/pull_reopen_test.go index a4be38ab64..8faba5e742 100644 --- a/tests/integration/pull_reopen_test.go +++ b/tests/integration/pull_reopen_test.go @@ -103,7 +103,7 @@ func TestPullrequestReopen(t *testing.T) { }) assert.NoError(t, err) - // Create the pull reuqest. + // Create the pull request. pullIssue := &issues_model.Issue{ RepoID: baseRepo.ID, Title: "Testing reopen functionality", diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index bcdb352612..ff94850cda 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -433,7 +433,7 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) { t.Run("Submit approve/reject review on closed PR", func(t *testing.T) { // Created a closed PR (made by user1) in the upstream repo1. - testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Editied...again)\n") + testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Edited...again)\n") resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "a-test-branch", "This is a pull title") elem := strings.Split(test.RedirectURL(resp), "/") assert.EqualValues(t, "pulls", elem[3]) diff --git a/tests/integration/rename_branch_test.go b/tests/integration/rename_branch_test.go index 27be77f71a..a96cbf5623 100644 --- a/tests/integration/rename_branch_test.go +++ b/tests/integration/rename_branch_test.go @@ -54,7 +54,7 @@ func testRenameBranch(t *testing.T, u *url.URL) { assert.Equal(t, "main", repo1.DefaultBranch) }) - t.Run("Database syncronization", func(t *testing.T) { + t.Run("Database synchronization", func(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/rename_branch", map[string]string{ diff --git a/tests/integration/repo_fork_test.go b/tests/integration/repo_fork_test.go index 23b3c26649..7b92bcda4b 100644 --- a/tests/integration/repo_fork_test.go +++ b/tests/integration/repo_fork_test.go @@ -115,7 +115,7 @@ func TestRepoFork(t *testing.T) { defer tests.PrintCurrentTest(t)() // Make sure the repo we try to fork is private. - // We're also choosing user15/big_test_private_2, becase it has the Code unit disabled. + // We're also choosing user15/big_test_private_2, because it has the Code unit disabled. repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 20, IsPrivate: true}) // user1, even though an admin, can't fork a repo without a code unit. diff --git a/web_src/fomantic/build/semantic.js b/web_src/fomantic/build/semantic.js index c150c8d9db..affd6a4bd0 100644 --- a/web_src/fomantic/build/semantic.js +++ b/web_src/fomantic/build/semantic.js @@ -142,7 +142,7 @@ $.api = $.fn.api = function(parameters) { response = JSON.parse(response); } catch(e) { - // isnt json string + // isn't json string } } return response; @@ -344,7 +344,7 @@ $.api = $.fn.api = function(parameters) { cancelled: function() { return (module.cancelled || false); }, - succesful: function() { + succesful: function() { // codespell-ignore module.verbose('This behavior will be deleted due to typo. Use "was successful" instead.'); return module.was.successful(); }, @@ -1343,7 +1343,7 @@ $.fn.dimmer = function(parameters) { event: { click: function(event) { - module.verbose('Determining if event occured on dimmer', event); + module.verbose('Determining if event occurred on dimmer', event); if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) { module.hide(); event.stopImmediatePropagation(); @@ -2491,7 +2491,7 @@ $.fn.dropdown = function(parameters) { if(settings.onHide.call(element) !== false) { module.animate.hide(function() { module.remove.visible(); - // hidding search focus + // hiding search focus if ( module.is.focusedOnSearch() && preventBlur !== true ) { $search.blur(); } diff --git a/web_src/js/bootstrap.js b/web_src/js/bootstrap.js index 3034478190..6cca37f7ca 100644 --- a/web_src/js/bootstrap.js +++ b/web_src/js/bootstrap.js @@ -50,7 +50,7 @@ function processWindowErrorEvent({error, reason, message, type, filename, lineno const assetBaseUrl = String(new URL(__webpack_public_path__, window.location.origin)); const {runModeIsProd} = window.config ?? {}; - // `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likly a + // `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likely a // non-critical event from the browser. We log them but don't show them to users. Examples: // - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors // - https://github.com/mozilla-mobile/firefox-ios/issues/10817 From 9cb2aa989a4c331f9085126e5a88b5095b45ae54 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 9 May 2024 18:33:33 +0200 Subject: [PATCH 36/99] Teach activities.GetFeeds() how to avoid returning duplicates Before explaining the fix itself, lets look at the `action` table, and how it is populated. Data is only ever inserted into it via `activities_model.NotifyWatchers`, which will: - Insert a row for each activity with `UserID` set to the acting user's ID - this is the original activity, and is always inserted if anything is to be inserted at all. - It will insert a copy of each activity with the `UserID` set to the repo's owner, if the owner is an Organization, and isn't the acting user. - It will insert a copy of each activity for every watcher of the repo, as long as the watcher in question has read permission to the repo unit the activity is about. This means that if a repository belongs to an organizations, for most activities, it will have at least two rows in the table. For repositories watched by people other than their owner, an additional row for each watcher. These are useful duplicates, because they record which activities are relevant for a particular user. However, for cases where we wish to see the activities that happen around a repository, without limiting the results to a particular user, we're *not* interested in the duplicates stored for the watchers and the org. We only need the originals. And this is what this change does: it introduces an additional option to `GetFeedsOptions`: `OnlyPerformedByActor`. When this option is set, `activities.GetFeeds()` will only return the original activities, where the user id and the acting user id are the same. As these are *always* inserted, we're not missing out on any activities. We're just getting rid of the duplicates. As this is an additional `AND` condition, it can never introduce items that would not have been included in the result set before, it can only reduce, not extend. These duplicates were only affecting call sites where `RequestedRepo` was set, but `RequestedUser` and `RequestedTeam` were not. Both of those call sites were updated to set `OnlyPerformedByActor`. As a result, repository RSS feeds, and the `/repos/{owner}/{repo}/activities/feeds` API end points no longer return dupes, only the original activities. Rather than hardcoding this behaviour into `GetFeeds()` itself, I chose to implement it as an explicit option, for the sake of clarity. Fixes Codeberg/Community#684, and addresses gitea#20986. Signed-off-by: Gergely Nagy --- models/activities/action.go | 21 +++-- release-notes/8.0.0/fix/3598.md | 1 + routers/api/v1/repo/repo.go | 11 +-- routers/web/feed/repo.go | 9 +- tests/integration/api_repo_activities_test.go | 88 +++++++++++++++++++ 5 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 release-notes/8.0.0/fix/3598.md create mode 100644 tests/integration/api_repo_activities_test.go diff --git a/models/activities/action.go b/models/activities/action.go index f85a493e22..b6c816f096 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -431,14 +431,15 @@ func (a *Action) GetIssueContent(ctx context.Context) string { // GetFeedsOptions options for retrieving feeds type GetFeedsOptions struct { db.ListOptions - RequestedUser *user_model.User // the user we want activity for - RequestedTeam *organization.Team // the team we want activity for - RequestedRepo *repo_model.Repository // the repo we want activity for - Actor *user_model.User // the user viewing the activity - IncludePrivate bool // include private actions - OnlyPerformedBy bool // only actions performed by requested user - IncludeDeleted bool // include deleted actions - Date string // the day we want activity for: YYYY-MM-DD + RequestedUser *user_model.User // the user we want activity for + RequestedTeam *organization.Team // the team we want activity for + RequestedRepo *repo_model.Repository // the repo we want activity for + Actor *user_model.User // the user viewing the activity + IncludePrivate bool // include private actions + OnlyPerformedBy bool // only actions performed by requested user + OnlyPerformedByActor bool // only actions performed by the original actor + IncludeDeleted bool // include deleted actions + Date string // the day we want activity for: YYYY-MM-DD } // GetFeeds returns actions according to the provided options @@ -481,6 +482,10 @@ func ActivityReadable(user, doer *user_model.User) bool { func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.Cond, error) { cond := builder.NewCond() + if opts.OnlyPerformedByActor { + cond = cond.And(builder.Expr("`action`.user_id = `action`.act_user_id")) + } + if opts.RequestedTeam != nil && opts.RequestedUser == nil { org, err := user_model.GetUserByID(ctx, opts.RequestedTeam.OrgID) if err != nil { diff --git a/release-notes/8.0.0/fix/3598.md b/release-notes/8.0.0/fix/3598.md new file mode 100644 index 0000000000..9d6b4ae0a4 --- /dev/null +++ b/release-notes/8.0.0/fix/3598.md @@ -0,0 +1 @@ +Fixed an issue that resulted in repository activity feeds (including RSS and Atom feeds) containing repeated activities. diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 66eb227c19..4be8c8ee72 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -1307,11 +1307,12 @@ func ListRepoActivityFeeds(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ - RequestedRepo: ctx.Repo.Repository, - Actor: ctx.Doer, - IncludePrivate: true, - Date: ctx.FormString("date"), - ListOptions: listOptions, + RequestedRepo: ctx.Repo.Repository, + OnlyPerformedByActor: true, + Actor: ctx.Doer, + IncludePrivate: true, + Date: ctx.FormString("date"), + ListOptions: listOptions, } feeds, count, err := activities_model.GetFeeds(ctx, opts) diff --git a/routers/web/feed/repo.go b/routers/web/feed/repo.go index bfcc3a37d6..a0033c7d45 100644 --- a/routers/web/feed/repo.go +++ b/routers/web/feed/repo.go @@ -16,10 +16,11 @@ import ( // ShowRepoFeed shows user activity on the repo as RSS / Atom feed func ShowRepoFeed(ctx *context.Context, repo *repo_model.Repository, formatType string) { actions, _, err := activities_model.GetFeeds(ctx, activities_model.GetFeedsOptions{ - RequestedRepo: repo, - Actor: ctx.Doer, - IncludePrivate: true, - Date: ctx.FormString("date"), + OnlyPerformedByActor: true, + RequestedRepo: repo, + Actor: ctx.Doer, + IncludePrivate: true, + Date: ctx.FormString("date"), }) if err != nil { ctx.ServerError("GetFeeds", err) diff --git a/tests/integration/api_repo_activities_test.go b/tests/integration/api_repo_activities_test.go new file mode 100644 index 0000000000..2b23ffc30e --- /dev/null +++ b/tests/integration/api_repo_activities_test.go @@ -0,0 +1,88 @@ +// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "testing" + + auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPIRepoActivitiyFeeds(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + repo, _, f := CreateDeclarativeRepoWithOptions(t, owner, DeclarativeRepoOptions{}) + defer f() + + feedURL := fmt.Sprintf("/api/v1/repos/%s/activities/feeds", repo.FullName()) + assertAndReturnActivities := func(t *testing.T, length int) []api.Activity { + t.Helper() + + req := NewRequest(t, "GET", feedURL) + resp := MakeRequest(t, req, http.StatusOK) + var activities []api.Activity + DecodeJSON(t, resp, &activities) + + assert.Len(t, activities, length) + + return activities + } + createIssue := func(t *testing.T) { + session := loginUser(t, owner.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue) + urlStr := fmt.Sprintf("/api/v1/repos/%s/issues?state=all", repo.FullName()) + req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{ + Title: "ActivityFeed test", + Body: "Nothing to see here!", + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + } + + t.Run("repo creation", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + // Upon repo creation, there's a single activity. + assertAndReturnActivities(t, 1) + }) + + t.Run("single watcher, single issue", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + // After creating an issue, we'll have two activities. + createIssue(t) + assertAndReturnActivities(t, 2) + }) + + t.Run("a new watcher, no new activities", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + watcher := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + watcherSession := loginUser(t, watcher.Name) + watcherToken := getTokenForLoggedInUser(t, watcherSession, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadUser) + + req := NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/subscription", repo.FullName())). + AddTokenAuth(watcherToken) + MakeRequest(t, req, http.StatusOK) + + assertAndReturnActivities(t, 2) + }) + + t.Run("multiple watchers, new issue", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + // After creating a second issue, we'll have three activities, even + // though we have multiple watchers. + createIssue(t) + assertAndReturnActivities(t, 3) + }) +} From 0dc35c9df96f024e147291c17dec5242c13ecfb4 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Thu, 9 May 2024 21:58:23 +0500 Subject: [PATCH 37/99] [THEME] Fix some 7.0 missing variables --- web_src/css/themes/theme-forgejo-dark.css | 2 ++ web_src/css/themes/theme-forgejo-light.css | 3 +++ 2 files changed, 5 insertions(+) diff --git a/web_src/css/themes/theme-forgejo-dark.css b/web_src/css/themes/theme-forgejo-dark.css index 95d35ddec0..2c11df45ed 100644 --- a/web_src/css/themes/theme-forgejo-dark.css +++ b/web_src/css/themes/theme-forgejo-dark.css @@ -226,6 +226,8 @@ --color-tooltip-bg: #000000f0; --color-nav-bg: var(--steel-900); --color-nav-hover-bg: var(--steel-600); + --color-nav-text: var(--color-text); + --color-secondary-nav-bg: var(--color-body); --color-label-text: #fff; --color-label-bg: var(--steel-600); --color-label-hover-bg: var(--steel-550); diff --git a/web_src/css/themes/theme-forgejo-light.css b/web_src/css/themes/theme-forgejo-light.css index ea988e67fa..6d4d06c1fd 100644 --- a/web_src/css/themes/theme-forgejo-light.css +++ b/web_src/css/themes/theme-forgejo-light.css @@ -243,6 +243,9 @@ --color-tooltip-bg: #000000f0; --color-nav-bg: var(--zinc-100); --color-nav-hover-bg: var(--zinc-300); + --color-nav-text: var(--color-text); + --color-secondary-nav-bg: var(--color-body); + --color-label-text: var(--color-text); --color-label-bg: #cacaca5b; --color-label-hover-bg: #cacacaa0; --color-label-active-bg: #cacacaff; From f81890fa950f8d8758889baeef2583251564359f Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Sun, 5 May 2024 11:10:20 +0900 Subject: [PATCH 38/99] Add result check in TestAPIEditUser (#29674) Fix #29514 There are too many usage of `NewRequestWithValues`, so there's no need to check all of them. Just one is enough I think. (cherry picked from commit ecd1d96f494d2400f7659165ff9376354edda395) Conflicts: - tests/integration/api_admin_test.go Conflict resolved by manually applying the change to `full_name`. --- tests/integration/api_admin_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index 0e97e606f9..5f8d360dec 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -195,10 +195,13 @@ func TestAPIEditUser(t *testing.T) { token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin) urlStr := fmt.Sprintf("/api/v1/admin/users/%s", "user2") + fullNameToChange := "Full Name User 2" req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{ - "full_name": "Full Name User 2", + "full_name": fullNameToChange, }).AddTokenAuth(token) MakeRequest(t, req, http.StatusOK) + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) + assert.Equal(t, fullNameToChange, user2.FullName) empty := "" req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ @@ -210,7 +213,7 @@ func TestAPIEditUser(t *testing.T) { json.Unmarshal(resp.Body.Bytes(), &errMap) assert.EqualValues(t, "e-mail invalid [email: ]", errMap["message"].(string)) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) + user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{LoginName: "user2"}) assert.False(t, user2.IsRestricted) bTrue := true req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ From 1148206fc87723344b26bf94712bacf96194339a Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 10 May 2024 00:08:05 +0000 Subject: [PATCH 39/99] Update dependency swagger-ui-dist to v5.17.7 --- 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 a4c3b97c7d..9f5f28137a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "postcss-nesting": "12.1.2", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", - "swagger-ui-dist": "5.17.6", + "swagger-ui-dist": "5.17.7", "tailwindcss": "3.4.3", "temporal-polyfill": "0.2.4", "throttle-debounce": "5.0.0", @@ -11497,9 +11497,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.17.6", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.6.tgz", - "integrity": "sha512-8P48+WvFKDF7YoDqmWq3EItwdOh7tJlPSZ7y6CNqQIPMQ+qZVI0iNlBMSzyU+PXOd1M8ndRiNKWOvfItREBvHg==" + "version": "5.17.7", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.7.tgz", + "integrity": "sha512-hKnq2Dss6Nvqxzj+tToBz0IJvKXgp7FExxX0Zj0rMajXJp8CJ98yLAwbKwKu8rxQf+2iIDUTGir84SCA8AN+fQ==" }, "node_modules/sync-fetch": { "version": "0.4.5", diff --git a/package.json b/package.json index 5faa8a6e6b..b370539bab 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "postcss-nesting": "12.1.2", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", - "swagger-ui-dist": "5.17.6", + "swagger-ui-dist": "5.17.7", "tailwindcss": "3.4.3", "temporal-polyfill": "0.2.4", "throttle-debounce": "5.0.0", From 9a812f16bdad67529944fcb8cc356f9086ef359c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 10 May 2024 02:05:33 +0000 Subject: [PATCH 40/99] Update dependency eslint-plugin-vue to v9.26.0 --- 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 a4c3b97c7d..1e62b12c64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,7 +83,7 @@ "eslint-plugin-unicorn": "52.0.0", "eslint-plugin-vitest": "0.5.4", "eslint-plugin-vitest-globals": "1.5.0", - "eslint-plugin-vue": "9.25.0", + "eslint-plugin-vue": "9.26.0", "eslint-plugin-vue-scoped-css": "2.8.0", "eslint-plugin-wc": "2.1.0", "happy-dom": "14.7.1", @@ -5966,9 +5966,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.25.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.25.0.tgz", - "integrity": "sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz", + "integrity": "sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", diff --git a/package.json b/package.json index 5faa8a6e6b..ebce02e02b 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "eslint-plugin-unicorn": "52.0.0", "eslint-plugin-vitest": "0.5.4", "eslint-plugin-vitest-globals": "1.5.0", - "eslint-plugin-vue": "9.25.0", + "eslint-plugin-vue": "9.26.0", "eslint-plugin-vue-scoped-css": "2.8.0", "eslint-plugin-wc": "2.1.0", "happy-dom": "14.7.1", From 7a5f0faf0c44e4325793e4197320afe81c7be739 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 10 May 2024 02:06:06 +0000 Subject: [PATCH 41/99] Update dependency happy-dom to v14.10.1 --- 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 a4c3b97c7d..ae6ba37bc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -86,7 +86,7 @@ "eslint-plugin-vue": "9.25.0", "eslint-plugin-vue-scoped-css": "2.8.0", "eslint-plugin-wc": "2.1.0", - "happy-dom": "14.7.1", + "happy-dom": "14.10.1", "markdownlint-cli": "0.40.0", "postcss-html": "1.6.0", "stylelint": "16.5.0", @@ -6775,9 +6775,9 @@ } }, "node_modules/happy-dom": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.7.1.tgz", - "integrity": "sha512-v60Q0evZ4clvMcrAh5/F8EdxDdfHdFrtffz/CNe10jKD+nFweZVxM91tW+UyY2L4AtpgIaXdZ7TQmiO1pfcwbg==", + "version": "14.10.1", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.10.1.tgz", + "integrity": "sha512-GRbrZYIezi8+tTtffF4v2QcF8bk1h2loUTO5VYQz3GZdrL08Vk0fI+bwf/vFEBf4C/qVf/easLJ/MY1wwdhytA==", "dev": true, "dependencies": { "entities": "^4.5.0", diff --git a/package.json b/package.json index 5faa8a6e6b..389469f066 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "eslint-plugin-vue": "9.25.0", "eslint-plugin-vue-scoped-css": "2.8.0", "eslint-plugin-wc": "2.1.0", - "happy-dom": "14.7.1", + "happy-dom": "14.10.1", "markdownlint-cli": "0.40.0", "postcss-html": "1.6.0", "stylelint": "16.5.0", From 7dd3c01606925eefe99fdcb5d543aa5197cde79f Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 19 Apr 2024 00:45:50 +0800 Subject: [PATCH 42/99] Refactor and fix archive link bug (#30535) Regression of #29920 Fixes: #30569 Also this is a rewriting to eliminate the remaining jQuery usages from code. Co-authored-by: Giteabot (cherry picked from commit d0e07083559180b124a08359fcc72f9ef695e723) Conflicts: - web_src/js/features/repo-common.js Conflict resolved in favour of Gitea. --- web_src/js/features/repo-common.js | 54 ++++++++++++------------------ web_src/js/utils/dom.js | 4 +++ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/web_src/js/features/repo-common.js b/web_src/js/features/repo-common.js index d6c47d8512..88aa93d850 100644 --- a/web_src/js/features/repo-common.js +++ b/web_src/js/features/repo-common.js @@ -1,45 +1,35 @@ import $ from 'jquery'; -import {hideElem, showElem} from '../utils/dom.js'; +import {hideElem, queryElems, showElem} from '../utils/dom.js'; import {POST} from '../modules/fetch.js'; +import {showErrorToast} from '../modules/toast.js'; +import {sleep} from '../utils.js'; -async function getArchive($target, url, first) { - const dropdownBtn = $target[0].closest('.ui.dropdown.button') ?? $target[0].closest('.ui.dropdown.btn') ?? $target[0].closest('details.download'); - +async function onDownloadArchive(e) { + e.preventDefault(); + // there are many places using the "archive-link", eg: the dropdown on the repo code page, the release list + const el = e.target.closest('a.archive-link[href]'); + const targetLoading = el.closest('.ui.dropdown') ?? el; + targetLoading.classList.add('is-loading', 'loading-icon-2px'); try { - dropdownBtn.classList.add('is-loading'); - const response = await POST(url); - if (response.status === 200) { - const data = await response.json(); - if (!data) { - // XXX Shouldn't happen? - dropdownBtn.classList.remove('is-loading'); - return; - } + for (let tryCount = 0; ;tryCount++) { + const response = await POST(el.href); + if (!response.ok) throw new Error(`Invalid server response: ${response.status}`); - if (!data.complete) { - // Wait for only three quarters of a second initially, in case it's - // quickly archived. - setTimeout(() => { - getArchive($target, url, false); - }, first ? 750 : 2000); - } else { - // We don't need to continue checking. - dropdownBtn.classList.remove('is-loading'); - window.location.href = url; - } + const data = await response.json(); + if (data.complete) break; + await sleep(Math.min((tryCount + 1) * 750, 2000)); } - } catch { - dropdownBtn.classList.remove('is-loading'); + window.location.href = el.href; // the archive is ready, start real downloading + } catch (e) { + console.error(e); + showErrorToast(`Failed to download the archive: ${e}`, {duration: 2500}); + } finally { + targetLoading.classList.remove('is-loading', 'loading-icon-2px'); } } export function initRepoArchiveLinks() { - $('.archive-link').on('click', function (event) { - event.preventDefault(); - const url = this.getAttribute('href'); - if (!url) return; - getArchive($(event.target), url, true); - }); + queryElems('a.archive-link[href]', (el) => el.addEventListener('click', onDownloadArchive)); } export function initRepoCloneLink() { diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js index 82993e897c..a2a79e91e2 100644 --- a/web_src/js/utils/dom.js +++ b/web_src/js/utils/dom.js @@ -69,6 +69,10 @@ export function queryElemChildren(parent, selector = '*', fn) { return applyElemsCallback(parent.querySelectorAll(`:scope > ${selector}`), fn); } +export function queryElems(selector, fn) { + return applyElemsCallback(document.querySelectorAll(selector), fn); +} + export function onDomReady(cb) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', cb); From 9d1ceee797c179394493bd75ecb25e535a99a24f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 10 May 2024 09:32:07 +0200 Subject: [PATCH 43/99] Add a release note for #3285 Signed-off-by: Gergely Nagy --- release-notes/8.0.0/3285.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 release-notes/8.0.0/3285.md diff --git a/release-notes/8.0.0/3285.md b/release-notes/8.0.0/3285.md new file mode 100644 index 0000000000..5ba8b7d33a --- /dev/null +++ b/release-notes/8.0.0/3285.md @@ -0,0 +1 @@ +The default for `[repository].USE_COMPAT_SSH_URI` has been changed to `true`. With this change, Forgejo defaults to using the same URL style for SSH clone URLs as for HTTPS ones, instead of the former scp-style. From a5c038f5e84bc9030fdb56af23fcbb112690c84f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 10 May 2024 09:39:52 +0200 Subject: [PATCH 44/99] Add a release note for #3464 Signed-off-by: Gergely Nagy --- release-notes/8.0.0/fix/3464.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 release-notes/8.0.0/fix/3464.md diff --git a/release-notes/8.0.0/fix/3464.md b/release-notes/8.0.0/fix/3464.md new file mode 100644 index 0000000000..cc15862863 --- /dev/null +++ b/release-notes/8.0.0/fix/3464.md @@ -0,0 +1 @@ +Fixed a bug where API endpoints that return a `Repository` did not properly include the repository's object format. From ac4d535dbf6b669997dd01560e692dd215b1321b Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 10 May 2024 11:12:41 +0200 Subject: [PATCH 45/99] templates: Be more forgiving about missing package metadata When rendering templates for packages, be more forgiving about missing metadata. For some repository types - like maven - metadata is uploaded separately. If that upload fails, or does not happen, there will be no metadata. In that case, Forgejo should handle it gracefully, and render as much of the information as possible, without erroring out. Rendering without metadata allows one to delete a partial package, while if we throw errors, that becomes a whole lot harder. This patch adjusts the generic metadata template, and also the maven template. There may be more cases of the same problem lying around. Fixes #3663. Signed-off-by: Gergely Nagy --- templates/package/content/maven.tmpl | 76 ++++++++++---------- templates/package/metadata/maven.tmpl | 2 +- tests/integration/api_packages_maven_test.go | 11 +++ 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/templates/package/content/maven.tmpl b/templates/package/content/maven.tmpl index 49ada6a3a3..7f7e3fafcc 100644 --- a/templates/package/content/maven.tmpl +++ b/templates/package/content/maven.tmpl @@ -23,49 +23,53 @@ </snapshotRepository> </distributionManagement>
-
- -
<dependency>
+			{{if .PackageDescriptor.Metadata}}
+				
+ +
<dependency>
 	<groupId>{{.PackageDescriptor.Metadata.GroupID}}</groupId>
 	<artifactId>{{.PackageDescriptor.Metadata.ArtifactID}}</artifactId>
 	<version>{{.PackageDescriptor.Version.Version}}</version>
 </dependency>
-
-
- -
mvn install
-
-
- -
mvn dependency:get -DremoteRepositories= -Dartifact={{.PackageDescriptor.Metadata.GroupID}}:{{.PackageDescriptor.Metadata.ArtifactID}}:{{.PackageDescriptor.Version.Version}}
-
-
- -
+
+
+ +
mvn install
+
+
+ +
mvn dependency:get -DremoteRepositories= -Dartifact={{.PackageDescriptor.Metadata.GroupID}}:{{.PackageDescriptor.Metadata.ArtifactID}}:{{.PackageDescriptor.Version.Version}}
+
+
+ +
+ {{end}}
- {{if .PackageDescriptor.Metadata.Description}} -

{{ctx.Locale.Tr "packages.about"}}

-
- {{.PackageDescriptor.Metadata.Description}} -
- {{end}} - - {{if .PackageDescriptor.Metadata.Dependencies}} -

{{ctx.Locale.Tr "packages.dependencies"}}

-
-
- {{range .PackageDescriptor.Metadata.Dependencies}} -
- {{svg "octicon-package-dependencies" 16 ""}} -
-
{{.GroupID}}:{{.ArtifactID}}
-
{{.Version}}
-
-
- {{end}} + {{if .PackageDescriptor.Metadata}} + {{if .PackageDescriptor.Metadata.Description}} +

{{ctx.Locale.Tr "packages.about"}}

+
+ {{.PackageDescriptor.Metadata.Description}}
-
+ {{end}} + + {{if .PackageDescriptor.Metadata.Dependencies}} +

{{ctx.Locale.Tr "packages.dependencies"}}

+
+
+ {{range .PackageDescriptor.Metadata.Dependencies}} +
+ {{svg "octicon-package-dependencies" 16 ""}} +
+
{{.GroupID}}:{{.ArtifactID}}
+
{{.Version}}
+
+
+ {{end}} +
+
+ {{end}} {{end}} {{end}} diff --git a/templates/package/metadata/maven.tmpl b/templates/package/metadata/maven.tmpl index 548be61790..62573a146a 100644 --- a/templates/package/metadata/maven.tmpl +++ b/templates/package/metadata/maven.tmpl @@ -1,4 +1,4 @@ -{{if eq .PackageDescriptor.Package.Type "maven"}} +{{if and (eq .PackageDescriptor.Package.Type "maven") .PackageDescriptor.Metadata}} {{if .PackageDescriptor.Metadata.Name}}
{{svg "octicon-note" 16 "tw-mr-2"}} {{.PackageDescriptor.Metadata.Name}}
{{end}} {{if .PackageDescriptor.Metadata.ProjectURL}}
{{svg "octicon-link-external" 16 "tw-mr-2"}} {{ctx.Locale.Tr "packages.details.project_site"}}
{{end}} {{range .PackageDescriptor.Metadata.Licenses}}
{{svg "octicon-law" 16 "tw-mr-2"}} {{.}}
{{end}} diff --git a/tests/integration/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go index b6c213abcf..2fc4a0f6de 100644 --- a/tests/integration/api_packages_maven_test.go +++ b/tests/integration/api_packages_maven_test.go @@ -241,4 +241,15 @@ func TestPackageMaven(t *testing.T) { putFile(t, fmt.Sprintf("/%s/maven-metadata.xml", snapshotVersion), "test", http.StatusCreated) putFile(t, fmt.Sprintf("/%s/maven-metadata.xml", snapshotVersion), "test-overwrite", http.StatusCreated) }) + + t.Run("Partial upload", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + partialVersion := packageVersion + "-PARTIAL" + putFile(t, fmt.Sprintf("/%s/%s", partialVersion, filename), "test", http.StatusCreated) + pkgUIURL := fmt.Sprintf("/%s/-/packages/maven/%s-%s/%s", user.Name, groupID, artifactID, partialVersion) + req := NewRequest(t, "GET", pkgUIURL) + resp := MakeRequest(t, req, http.StatusOK) + assert.NotContains(t, resp.Body.String(), "Internal server error") + }) } From 33648f2a4c86c45e38d69cd1cf3a65256ec1e5cd Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Fri, 10 May 2024 17:30:34 +0200 Subject: [PATCH 46/99] add second federated instance to integration test --- .../api_activitypub_repository_test.go | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tests/integration/api_activitypub_repository_test.go b/tests/integration/api_activitypub_repository_test.go index 19bf1cf094..e237ffeb1e 100644 --- a/tests/integration/api_activitypub_repository_test.go +++ b/tests/integration/api_activitypub_repository_test.go @@ -9,8 +9,11 @@ import ( "net/http/httptest" "net/url" "testing" + "time" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/forgefed" + "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/activitypub" forgefed_modules "code.gitea.io/gitea/modules/forgefed" @@ -70,6 +73,31 @@ func TestActivityPubRepositoryInboxValid(t *testing.T) { srv := httptest.NewServer(testWebRoutes) defer srv.Close() + federatedRoutes := http.NewServeMux() + federatedRoutes.HandleFunc("/.well-known/nodeinfo", + func(res http.ResponseWriter, req *http.Request) { + // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo + responseBody := fmt.Sprintf(`{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host) + t.Logf("response: %s", responseBody) + // TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8 + fmt.Fprint(res, responseBody) + }) + federatedRoutes.HandleFunc("/api/v1/nodeinfo", + func(res http.ResponseWriter, req *http.Request) { + // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo + responseBody := fmt.Sprintf(`{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",` + + `"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},` + + `"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},` + + `"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`) + fmt.Fprint(res, responseBody) + }) + federatedRoutes.HandleFunc("/", + func(res http.ResponseWriter, req *http.Request) { + t.Errorf("Unhandled request: %q", req.URL.EscapedPath()) + }) + federatedSrv := httptest.NewServer(federatedRoutes) + defer federatedSrv.Close() + onGiteaRun(t, func(*testing.T, *url.URL) { appURL := setting.AppURL setting.AppURL = srv.URL + "/" @@ -81,14 +109,26 @@ func TestActivityPubRepositoryInboxValid(t *testing.T) { repositoryID := 2 c, err := activitypub.NewClient(db.DefaultContext, actionsUser, "not used") assert.NoError(t, err) - repoInboxURL := fmt.Sprintf("%s/api/v1/activitypub/repository-id/%v/inbox", + repoInboxURL := fmt.Sprintf( + "%s/api/v1/activitypub/repository-id/%v/inbox", srv.URL, repositoryID) - activity := []byte(fmt.Sprintf(`{"type":"Like","startTime":"2024-03-27T00:00:00Z","actor":"%s/api/v1/activitypub/user-id/2","object":"%s/api/v1/activitypub/repository-id/%v"}`, - srv.URL, srv.URL, repositoryID)) + activity := []byte(fmt.Sprintf( + `{"type":"Like",`+ + `"startTime":"%s",`+ + `"actor":"%s/api/v1/activitypub/user-id/2",`+ + `"object":"%s/api/v1/activitypub/repository-id/%v"}`, + time.Now().UTC().Format(time.RFC3339), + federatedSrv.URL, srv.URL, repositoryID)) + t.Logf("activity: %s", activity) resp, err := c.Post(activity, repoInboxURL) + assert.NoError(t, err) assert.Equal(t, http.StatusNoContent, resp.StatusCode) + + federationHost := unittest.AssertExistsAndLoadBean(t, &forgefed.FederationHost{ID: 1}) + assert.Equal(t, "127.0.0.1", federationHost.HostFqdn) + }) } From b1a239cdc40e39348e214ff6e13366ca1f2ea789 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Fri, 10 May 2024 23:19:35 +0500 Subject: [PATCH 47/99] Improve how icon colors are defined - define specific colors for icons for themes - fix related contrast issues on Forgejo dark theme --- web_src/css/base.css | 14 ++++++++++++++ web_src/css/themes/theme-forgejo-dark.css | 7 ++++--- web_src/css/themes/theme-forgejo-light.css | 7 ++++--- web_src/css/themes/theme-gitea-dark.css | 4 ++++ web_src/css/themes/theme-gitea-light.css | 4 ++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/web_src/css/base.css b/web_src/css/base.css index 3d91586934..a43ba031e0 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -1143,6 +1143,20 @@ overflow-menu .ui.label { color: var(--color-secondary-dark-2) !important; } +/* colors of colorful icons */ +svg.text.green, +.text.green svg { + color: var(--color-icon-green) !important; +} +svg.text.red, +.text.red svg { + color: var(--color-icon-red) !important; +} +svg.text.purple, +.text.purple svg { + color: var(--color-icon-purple) !important; +} + .oauth2-authorize-application-box { margin-top: 3em !important; } diff --git a/web_src/css/themes/theme-forgejo-dark.css b/web_src/css/themes/theme-forgejo-dark.css index 95d35ddec0..2093e8b768 100644 --- a/web_src/css/themes/theme-forgejo-dark.css +++ b/web_src/css/themes/theme-forgejo-dark.css @@ -178,6 +178,10 @@ --color-orange-badge-bg: #ea580c22; --color-orange-badge-hover-bg: #ea580c44; --color-git: #f05133; + /* Icon colors (PR/Issue/...) */ + --color-icon-green: #3fb950; + --color-icon-red: #f85149; + --color-icon-purple: #aa76ff; /* target-based colors */ --color-body: var(--steel-800); --color-box-header: var(--steel-700); @@ -262,9 +266,6 @@ .emoji[aria-label="musical notes"] { filter: invert(100%) hue-rotate(180deg); } -.text.green.svg { - color: var(--color-green-light) !important; -} i.grey.icon.icon.icon.icon { color: var(--steel-350) !important; } diff --git a/web_src/css/themes/theme-forgejo-light.css b/web_src/css/themes/theme-forgejo-light.css index ea988e67fa..466e01510a 100644 --- a/web_src/css/themes/theme-forgejo-light.css +++ b/web_src/css/themes/theme-forgejo-light.css @@ -195,6 +195,10 @@ --color-orange-badge-bg: #ea580c22; --color-orange-badge-hover-bg: #ea580c44; --color-git: #f05133; + /* Icon colors (PR/Issue/...) */ + --color-icon-green: var(--color-green-light); + --color-icon-red: var(--color-red-light); + --color-icon-purple: var(--color-purple-light); /* target-based colors */ --color-body: #fff; --color-box-header: var(--zinc-100); @@ -255,9 +259,6 @@ accent-color: var(--color-accent); color-scheme: light; } -.text.green.svg { - color: var(--color-green-light) !important; -} .ui.secondary.vertical.menu { border-radius: 0.28571429rem !important; overflow: hidden; diff --git a/web_src/css/themes/theme-gitea-dark.css b/web_src/css/themes/theme-gitea-dark.css index c74f334c2d..325d31ea14 100644 --- a/web_src/css/themes/theme-gitea-dark.css +++ b/web_src/css/themes/theme-gitea-dark.css @@ -179,6 +179,10 @@ --color-orange-badge-bg: #f2711c1a; --color-orange-badge-hover-bg: #f2711c4d; --color-git: #f05133; + /* Icon colors (PR/Issue/...) */ + --color-icon-green: var(--color-green); + --color-icon-red: var(--color-red); + --color-icon-purple: var(--color-purple); /* target-based colors */ --color-body: #1c1f25; --color-box-header: #1a1d1f; diff --git a/web_src/css/themes/theme-gitea-light.css b/web_src/css/themes/theme-gitea-light.css index 01dd8ba4f7..695645aaa5 100644 --- a/web_src/css/themes/theme-gitea-light.css +++ b/web_src/css/themes/theme-gitea-light.css @@ -179,6 +179,10 @@ --color-orange-badge-bg: #f2711c1a; --color-orange-badge-hover-bg: #f2711c4d; --color-git: #f05133; + /* Icon colors (PR/Issue/...) */ + --color-icon-green: var(--color-green); + --color-icon-red: var(--color-red); + --color-icon-purple: var(--color-purple); /* target-based colors */ --color-body: #ffffff; --color-box-header: #f1f3f5; From 84d01b182842f1435cc0099642306f16610e1b20 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 11 May 2024 02:04:33 +0000 Subject: [PATCH 48/99] Update ghcr.io/devcontainers/features/git-lfs Docker tag to v1.2.0 --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1b1b66c7dd..4e944dfb10 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "ghcr.io/devcontainers/features/node:1": { "version": "20" }, - "ghcr.io/devcontainers/features/git-lfs:1.1.0": {}, + "ghcr.io/devcontainers/features/git-lfs:1.2.0": {}, "ghcr.io/devcontainers-contrib/features/poetry:2": {}, "ghcr.io/devcontainers/features/python:1": { "version": "3.12" From 2db58b786d71aec779a7676c163e6b5eb1da2945 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 11 May 2024 02:04:41 +0000 Subject: [PATCH 49/99] Update mcr.microsoft.com/devcontainers/go Docker tag to v1.22 --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1b1b66c7dd..d391cf78cf 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "Gitea DevContainer", - "image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye", + "image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye", "features": { // installs nodejs into container "ghcr.io/devcontainers/features/node:1": { From 6f3c50e75d80e2de8cbb077a95b1e76ad88ebbd7 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 11 May 2024 12:03:36 +0000 Subject: [PATCH 50/99] Update postcss packages --- package-lock.json | 38 ++++++++++++++++---------------------- package.json | 4 ++-- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index acc6e05034..bd56edf516 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "pdfobject": "2.3.0", "postcss": "8.4.38", "postcss-loader": "8.1.1", - "postcss-nesting": "12.1.2", + "postcss-nesting": "12.1.3", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", "swagger-ui-dist": "5.17.7", @@ -88,7 +88,7 @@ "eslint-plugin-wc": "2.1.0", "happy-dom": "14.10.1", "markdownlint-cli": "0.40.0", - "postcss-html": "1.6.0", + "postcss-html": "1.7.0", "stylelint": "16.5.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.4", @@ -482,9 +482,9 @@ } }, "node_modules/@csstools/selector-specificity": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", - "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.0.tgz", + "integrity": "sha512-tGDFEHZ4XJeIt5NF7/nAfLGqPckmDZSnYne5gl67p4agQolE5s4rofdQ3e+VkeukfR91lVtSQ/Jt9DqM1ICiIQ==", "funding": [ { "type": "github", @@ -7719,9 +7719,9 @@ "dev": true }, "node_modules/js-tokens": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", - "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", "dev": true }, "node_modules/js-types": { @@ -9715,13 +9715,13 @@ } }, "node_modules/postcss-html": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.6.0.tgz", - "integrity": "sha512-OWgQ9/Pe23MnNJC0PL4uZp8k0EDaUvqpJFSiwFxOLClAhmD7UEisyhO3x5hVsD4xFrjReVTXydlrMes45dJ71w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-1.7.0.tgz", + "integrity": "sha512-MfcMpSUIaR/nNgeVS8AyvyDugXlADjN9AcV7e5rDfrF1wduIAGSkL4q2+wgrZgA3sHVAHLDO9FuauHhZYW2nBw==", "dev": true, "dependencies": { "htmlparser2": "^8.0.0", - "js-tokens": "^8.0.0", + "js-tokens": "^9.0.0", "postcss": "^8.4.0", "postcss-safe-parser": "^6.0.0" }, @@ -9867,9 +9867,9 @@ } }, "node_modules/postcss-nesting": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.2.tgz", - "integrity": "sha512-FUmTHGDNundodutB4PUBxt/EPuhgtpk8FJGRsBhOuy+6FnkR2A8RZWIsyyy6XmhvX2DZQQWIkvu+HB4IbJm+Ew==", + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.3.tgz", + "integrity": "sha512-8XVmgNNYlmIg1qxSP7O5n76nm0I71noCzlSCl7oqaL2opJ5nSB7r8/726yObKrUTRt6ipjiqHB1wYrMVTM66Sg==", "funding": [ { "type": "github", @@ -9882,7 +9882,7 @@ ], "dependencies": { "@csstools/selector-resolve-nested": "^1.1.0", - "@csstools/selector-specificity": "^3.0.3", + "@csstools/selector-specificity": "^3.1.0", "postcss-selector-parser": "^6.0.13" }, "engines": { @@ -11120,12 +11120,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", diff --git a/package.json b/package.json index f12aba390e..154c35849e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "pdfobject": "2.3.0", "postcss": "8.4.38", "postcss-loader": "8.1.1", - "postcss-nesting": "12.1.2", + "postcss-nesting": "12.1.3", "pretty-ms": "9.0.0", "sortablejs": "1.15.2", "swagger-ui-dist": "5.17.7", @@ -87,7 +87,7 @@ "eslint-plugin-wc": "2.1.0", "happy-dom": "14.10.1", "markdownlint-cli": "0.40.0", - "postcss-html": "1.6.0", + "postcss-html": "1.7.0", "stylelint": "16.5.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.4", From b45fbe1dcc296252b5c9927e401acd7670800572 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Sat, 11 May 2024 18:15:29 +0500 Subject: [PATCH 51/99] Add class tw-break-anywhere very partial port of https://github.com/go-gitea/gitea/commit/99463532820d7a88cdea88e66e0606b996cc9fc7#diff-38f10be6b48c74bcacbf9f6e15cc8582a45b7a6cbd1cdd8efec8e592575290c5 to fix a few picked areas where lack of it causes bugs. --- web_src/css/helpers.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index 118c058b19..cf2e73572c 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -52,6 +52,9 @@ only use: */ .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 95b282182465ab41ad9b411cc40ae7f9da6511fa Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 12 May 2024 00:05:15 +0000 Subject: [PATCH 52/99] Update module github.com/go-enry/go-enry/v2 to v2.8.8 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a87de37d4c..624806121c 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/go-chi/chi/v5 v5.0.11 github.com/go-chi/cors v1.2.1 github.com/go-co-op/gocron v1.37.0 - github.com/go-enry/go-enry/v2 v2.8.7 + github.com/go-enry/go-enry/v2 v2.8.8 github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.11.0 diff --git a/go.sum b/go.sum index a7a9b18963..8fa9bda94a 100644 --- a/go.sum +++ b/go.sum @@ -292,8 +292,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= -github.com/go-enry/go-enry/v2 v2.8.7 h1:vbab0pcf5Yo1cHQLzbWZ+QomUh3EfEU8EiR5n7W0lnQ= -github.com/go-enry/go-enry/v2 v2.8.7/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= +github.com/go-enry/go-enry/v2 v2.8.8 h1:EhfxWpw4DQ3WEFB1Y77X8vKqZL0D0EDUUWYDUAIv9/4= +github.com/go-enry/go-enry/v2 v2.8.8/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= From 0a67dbffb0f9622710381196d90350e89895ac58 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sun, 12 May 2024 15:58:52 +0200 Subject: [PATCH 53/99] chore(renovate): manually upgrade xgo, oapi-codegen & kin-openapi --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index efb344c2d9..4e4bb78207 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1. GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 # renovate: datasource=go SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.6-0.20240201115257-bcc7c78b7786 # renovate: datasource=go -XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest # renovate: datasource=go +XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.27 # renovate: datasource=go @@ -337,8 +337,8 @@ ifneq "$(TAGS)" "$(shell cat $(TAGS_EVIDENCE) 2>/dev/null)" TAGS_PREREQ := $(TAGS_EVIDENCE) endif -OAPI_CODEGEN_PACKAGE ?= github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4 # renovate: datasource=go -KIN_OPENAPI_CODEGEN_PACKAGE ?= github.com/getkin/kin-openapi/cmd/validate@v0.114.0 # renovate: datasource=go +OAPI_CODEGEN_PACKAGE ?= github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4 +KIN_OPENAPI_CODEGEN_PACKAGE ?= github.com/getkin/kin-openapi/cmd/validate@v0.114.0 FORGEJO_API_SERVER = routers/api/forgejo/v1/generated.go .PHONY: generate-forgejo-api From 8672ad12b151bde998c52ec1a21268bacb354c1e Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 12 May 2024 14:56:39 +0000 Subject: [PATCH 54/99] Update module github.com/caddyserver/certmagic to v0.21.0 (#3724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github.com/caddyserver/certmagic](https://github.com/caddyserver/certmagic) | require | minor | `v0.20.0` -> `v0.21.0` | --- ### Release Notes
caddyserver/certmagic (github.com/caddyserver/certmagic) ### [`v0.21.0`](https://github.com/caddyserver/certmagic/releases/tag/v0.21.0) [Compare Source](https://github.com/caddyserver/certmagic/compare/v0.20.0...v0.21.0) CertMagic v0.21 introduces some big changes: - Draft support for draft-03 of [ACME Renewal Information (ARI)](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/) which assists with deciding when to renew certificates. This augments CertMagic's already-advanced logic using cert lifetime and OCSP/revocation status. - New [`ZeroSSLIssuer`](https://pkg.go.dev/github.com/caddyserver/certmagic@v0.21.0#ZeroSSLIssuer) uses the [ZeroSSL API](https://zerossl.com/documentation/api/) to get certificates. ZeroSSL also has an ACME endpoint, which can still be accesed using the existing ACMEIssuer, as always. Their proprietary API is paid, but has extra features like IP certificates, better reliability, and support. - DNS challenges should be smoother in some cases as we've improved propagation checking. - In the odd case your ACME account disappears from the ACME server, CertMagic will automatically retry with a new account. (This happens in some test/dev environments.) - ACME accounts are identified only by their public keys, but CertMagic maps accounts by CA+email for practical/storage reasons. So now you can "pin" an account key to use by specifying your email and the account public key in your config, which is useful if you need to absolutely be sure to use a specific account (like if you get rate limit exemptions from a CA). Please try it out and report any issues! Thanks to [@​Framer](https://github.com/Framer) for their contributions to this release! #### What's Changed - Bump golang.org/x/crypto from 0.14.0 to 0.17.0 by [@​dependabot](https://github.com/dependabot) in https://github.com/caddyserver/certmagic/pull/264 - Demote "storage cleaning happened too recently" from WARN to INFO by [@​francislavoie](https://github.com/francislavoie) in https://github.com/caddyserver/certmagic/pull/270 - Check DNS propagation at authoritative nameservers only with default resolvers by [@​pgeh](https://github.com/pgeh) in https://github.com/caddyserver/certmagic/pull/274 - Retry with new account if account disappeared remotely by [@​mholt](https://github.com/mholt) in https://github.com/caddyserver/certmagic/pull/269 - Update readme examples to use TLS-ALPN const from ACMEz by [@​goksan](https://github.com/goksan) in https://github.com/caddyserver/certmagic/pull/277 - Initial implementation of ZeroSSL API issuer by [@​mholt](https://github.com/mholt) in https://github.com/caddyserver/certmagic/pull/279 - Allow deleting directories via FileStorage by [@​goksan](https://github.com/goksan) in https://github.com/caddyserver/certmagic/pull/282 - Use the `email` configuration in the ACME issuer to "pin" an account to a key by [@​ankon](https://github.com/ankon) in https://github.com/caddyserver/certmagic/pull/283 - Initial implementation of ARI by [@​mholt](https://github.com/mholt) in https://github.com/caddyserver/certmagic/pull/286 #### New Contributors - [@​pgeh](https://github.com/pgeh) made their first contribution in https://github.com/caddyserver/certmagic/pull/274 - [@​goksan](https://github.com/goksan) made their first contribution in https://github.com/caddyserver/certmagic/pull/277 **Full Changelog**: https://github.com/caddyserver/certmagic/compare/v0.20.0...v0.21.0
--- ### Configuration 📅 **Schedule**: Branch creation - "before 4am" (UTC), Automerge - "before 4am" (UTC). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). Co-authored-by: Earl Warren Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3724 Reviewed-by: Earl Warren Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- assets/go-licenses.json | 11 +++++-- go.mod | 27 ++++++++-------- go.sum | 61 +++++++++++++++++++------------------ release-notes/8.0.0/3724.md | 6 ++++ 4 files changed, 60 insertions(+), 45 deletions(-) create mode 100644 release-notes/8.0.0/3724.md diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 026321b3fa..0e8673145a 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -249,6 +249,11 @@ "path": "github.com/caddyserver/certmagic/LICENSE.txt", "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {yyyy} {name of copyright owner}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, + { + "name": "github.com/caddyserver/zerossl", + "path": "github.com/caddyserver/zerossl/LICENSE", + "licenseText": "MIT License\n\nCopyright (c) 2024 Matthew Holt\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE." + }, { "name": "github.com/cention-sany/utf7", "path": "github.com/cention-sany/utf7/LICENSE", @@ -725,8 +730,8 @@ "licenseText": "MIT License\n\nCopyright (c) 2020-2024 Meili SAS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" }, { - "name": "github.com/mholt/acmez", - "path": "github.com/mholt/acmez/LICENSE", + "name": "github.com/mholt/acmez/v2", + "path": "github.com/mholt/acmez/v2/LICENSE", "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, { @@ -1041,7 +1046,7 @@ }, { "name": "go.uber.org/zap", - "path": "go.uber.org/zap/LICENSE.txt", + "path": "go.uber.org/zap/LICENSE", "licenseText": "Copyright (c) 2016-2017 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n" }, { diff --git a/go.mod b/go.mod index a87de37d4c..637e0d0bea 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/blevesearch/bleve/v2 v2.4.0 github.com/buildkite/terminal-to-html/v3 v3.10.1 - github.com/caddyserver/certmagic v0.20.0 + github.com/caddyserver/certmagic v0.21.0 github.com/chi-middleware/proxy v1.1.1 github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 github.com/djherbis/buffer v1.2.0 @@ -67,7 +67,7 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 github.com/klauspost/compress v1.17.8 - github.com/klauspost/cpuid/v2 v2.2.6 + github.com/klauspost/cpuid/v2 v2.2.7 github.com/lib/pq v1.10.9 github.com/markbates/goth v1.78.0 github.com/mattn/go-isatty v0.0.20 @@ -101,13 +101,13 @@ require ( github.com/yuin/goldmark v1.7.0 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-meta v1.1.0 - golang.org/x/crypto v0.22.0 + golang.org/x/crypto v0.23.0 golang.org/x/image v0.15.0 - golang.org/x/net v0.24.0 + golang.org/x/net v0.25.0 golang.org/x/oauth2 v0.16.0 - golang.org/x/sys v0.19.0 - golang.org/x/text v0.14.0 - golang.org/x/tools v0.17.0 + golang.org/x/sys v0.20.0 + golang.org/x/text v0.15.0 + golang.org/x/tools v0.21.0 google.golang.org/grpc v1.60.1 google.golang.org/protobuf v1.33.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df @@ -159,6 +159,7 @@ require ( github.com/blevesearch/zapx/v16 v16.0.12 // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect + github.com/caddyserver/zerossl v0.1.2 // indirect github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect @@ -218,14 +219,14 @@ require ( github.com/klauspost/pgzip v1.2.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/libdns/libdns v0.2.1 // indirect + github.com/libdns/libdns v0.2.2 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/markbates/going v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mholt/acmez v1.2.0 // indirect - github.com/miekg/dns v1.1.58 // indirect + github.com/mholt/acmez/v2 v2.0.1 // indirect + github.com/miekg/dns v1.1.59 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -281,10 +282,10 @@ require ( go.opentelemetry.io/otel/trace v1.22.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/mod v0.16.0 // indirect - golang.org/x/sync v0.6.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect diff --git a/go.sum b/go.sum index a7a9b18963..3c0706e449 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,10 @@ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0 github.com/buildkite/terminal-to-html/v3 v3.10.1 h1:znT9eD26LQ59dDJJEpMCwkP4wEptEAPi74hsTBuHdEo= github.com/buildkite/terminal-to-html/v3 v3.10.1/go.mod h1:qtuRyYs6/Sw3FS9jUyVEaANHgHGqZsGqMknPLyau5cQ= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= -github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= +github.com/caddyserver/certmagic v0.21.0 h1:yDoifClc4hIxhHer3AxUj4buhF+NzRR6torw/AOnuUE= +github.com/caddyserver/certmagic v0.21.0/go.mod h1:OgUZNXYV/ylYoFJNmoYVR5nntydLNMQISePPgqZTyhc= +github.com/caddyserver/zerossl v0.1.2 h1:tlEu1VzWGoqcCpivs9liKAKhfpJWYJkHEMmlxRbVAxE= +github.com/caddyserver/zerossl v0.1.2/go.mod h1:wtiJEHbdvunr40ZzhXlnIkOB8Xj4eKtBKizCcZitJiQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI= github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8= @@ -561,8 +563,8 @@ github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -585,8 +587,8 @@ github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmt github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= -github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= +github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= +github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ= github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0= github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI= @@ -613,14 +615,14 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/meilisearch/meilisearch-go v0.26.1 h1:3bmo2uLijX7kvBmiZ9LupVfC95TFcRJDgrRTzbOoE4A= github.com/meilisearch/meilisearch-go v0.26.1/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= -github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= -github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= +github.com/mholt/acmez/v2 v2.0.1 h1:3/3N0u1pLjMK4sNEAFSI+bcvzbPhRpY383sy1kLHJ6k= +github.com/mholt/acmez/v2 v2.0.1/go.mod h1:fX4c9r5jYwMyMsC+7tkYRxHibkOTgta5DIFGoe67e1U= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.70 h1:1u9NtMgfK1U42kUxcsl5v0yj6TEOPR497OAQxpJnn2g= @@ -873,12 +875,12 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -894,8 +896,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -932,8 +934,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -974,8 +976,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -996,8 +998,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1053,8 +1055,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1065,8 +1067,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1080,8 +1082,9 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1137,8 +1140,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/release-notes/8.0.0/3724.md b/release-notes/8.0.0/3724.md new file mode 100644 index 0000000000..8af3bc893c --- /dev/null +++ b/release-notes/8.0.0/3724.md @@ -0,0 +1,6 @@ +- [CERT management was improved](https://codeberg.org/forgejo/forgejo/pulls/3724) when [`ENABLE_ACME=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#server-server) + - Draft support for draft-03 of [ACME Renewal Information (ARI)](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/) which assists with deciding when to renew certificates. This augments CertMagic's already-advanced logic using cert lifetime and OCSP/revocation status. + - New [`ZeroSSLIssuer`](https://pkg.go.dev/github.com/caddyserver/certmagic@v0.21.0#ZeroSSLIssuer) uses the [ZeroSSL API](https://zerossl.com/documentation/api/) to get certificates. ZeroSSL also has an ACME endpoint, which can still be accesed using the existing ACMEIssuer, as always. Their proprietary API is paid, but has extra features like IP certificates, better reliability, and support. + - DNS challenges should be smoother in some cases as we've improved propagation checking. + - In the odd case your ACME account disappears from the ACME server, CertMagic will automatically retry with a new account. (This happens in some test/dev environments.) + - ACME accounts are identified only by their public keys, but CertMagic maps accounts by CA+email for practical/storage reasons. So now you can "pin" an account key to use by specifying your email and the account public key in your config, which is useful if you need to absolutely be sure to use a specific account (like if you get rate limit exemptions from a CA). From 16eb85adfb6814ed4953efb976e4a21acc22c5ad Mon Sep 17 00:00:00 2001 From: Kemal Zebari <60799661+kemzeb@users.noreply.github.com> Date: Sun, 5 May 2024 18:36:53 -0700 Subject: [PATCH 55/99] Have time.js use UTC-related getters/setters (#30857) Before this patch, we were using `Date` getter/setter methods that worked with local time to get a list of Sundays that are in the range of some start date and end date. The problem with this was that the Sundays are in Unix epoch time and when we changed the "startDate" argument that was passed to make sure it is on a Sunday, this change would be reflected when we convert it to Unix epoch time. More specifically, I observed that we may get different Unix epochs depending on your timezone when the returned list should rather be timezone-agnostic. This led to issues in US timezones that caused the contributor, code frequency, and recent commit charts to not show any chart data. This fix resolves this by using getter/setter methods that work with UTC since it isn't dependent on timezones. Fixes #30851. --------- Co-authored-by: Sam Fisher (cherry picked from commit 22c7b3a74459833b86783e84d4708c8934d34e58) --- web_src/js/components/RepoCodeFrequency.vue | 2 +- web_src/js/components/RepoContributors.vue | 2 +- web_src/js/components/RepoRecentCommits.vue | 2 +- web_src/js/utils/time.js | 37 ++++++++++++--------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/web_src/js/components/RepoCodeFrequency.vue b/web_src/js/components/RepoCodeFrequency.vue index adce431264..1d40d6d417 100644 --- a/web_src/js/components/RepoCodeFrequency.vue +++ b/web_src/js/components/RepoCodeFrequency.vue @@ -67,7 +67,7 @@ export default { const weekValues = Object.values(this.data); const start = weekValues[0].week; const end = firstStartDateAfterDate(new Date()); - const startDays = startDaysBetween(new Date(start), new Date(end)); + const startDays = startDaysBetween(start, end); this.data = fillEmptyStartDaysWithZeroes(startDays, this.data); this.errorText = ''; } else { diff --git a/web_src/js/components/RepoContributors.vue b/web_src/js/components/RepoContributors.vue index 2347c41ae4..f7b05831e0 100644 --- a/web_src/js/components/RepoContributors.vue +++ b/web_src/js/components/RepoContributors.vue @@ -114,7 +114,7 @@ export default { const weekValues = Object.values(total.weeks); this.xAxisStart = weekValues[0].week; this.xAxisEnd = firstStartDateAfterDate(new Date()); - const startDays = startDaysBetween(new Date(this.xAxisStart), new Date(this.xAxisEnd)); + const startDays = startDaysBetween(this.xAxisStart, this.xAxisEnd); total.weeks = fillEmptyStartDaysWithZeroes(startDays, total.weeks); this.xAxisMin = this.xAxisStart; this.xAxisMax = this.xAxisEnd; diff --git a/web_src/js/components/RepoRecentCommits.vue b/web_src/js/components/RepoRecentCommits.vue index 502af533da..8759978e78 100644 --- a/web_src/js/components/RepoRecentCommits.vue +++ b/web_src/js/components/RepoRecentCommits.vue @@ -62,7 +62,7 @@ export default { const data = await response.json(); const start = Object.values(data)[0].week; const end = firstStartDateAfterDate(new Date()); - const startDays = startDaysBetween(new Date(start), new Date(end)); + const startDays = startDaysBetween(start, end); this.data = fillEmptyStartDaysWithZeroes(startDays, data).slice(-52); this.errorText = ''; } else { diff --git a/web_src/js/utils/time.js b/web_src/js/utils/time.js index 1848792c98..7c7eabd1a3 100644 --- a/web_src/js/utils/time.js +++ b/web_src/js/utils/time.js @@ -1,25 +1,30 @@ import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc.js'; import {getCurrentLocale} from '../utils.js'; -// Returns an array of millisecond-timestamps of start-of-week days (Sundays) -export function startDaysBetween(startDate, endDate) { - // Ensure the start date is a Sunday - while (startDate.getDay() !== 0) { - startDate.setDate(startDate.getDate() + 1); - } +dayjs.extend(utc); - const start = dayjs(startDate); - const end = dayjs(endDate); - const startDays = []; +/** + * Returns an array of millisecond-timestamps of start-of-week days (Sundays) + * + * @param startConfig The start date. Can take any type that `Date` accepts. + * @param endConfig The end date. Can take any type that `Date` accepts. + */ +export function startDaysBetween(startDate, endDate) { + const start = dayjs.utc(startDate); + const end = dayjs.utc(endDate); let current = start; + + // Ensure the start date is a Sunday + while (current.day() !== 0) { + current = current.add(1, 'day'); + } + + const startDays = []; while (current.isBefore(end)) { startDays.push(current.valueOf()); - // we are adding 7 * 24 hours instead of 1 week because we don't want - // date library to use local time zone to calculate 1 week from now. - // local time zone is problematic because of daylight saving time (dst) - // used on some countries - current = current.add(7 * 24, 'hour'); + current = current.add(1, 'week'); } return startDays; @@ -29,10 +34,10 @@ export function firstStartDateAfterDate(inputDate) { if (!(inputDate instanceof Date)) { throw new Error('Invalid date'); } - const dayOfWeek = inputDate.getDay(); + const dayOfWeek = inputDate.getUTCDay(); const daysUntilSunday = 7 - dayOfWeek; const resultDate = new Date(inputDate.getTime()); - resultDate.setDate(resultDate.getDate() + daysUntilSunday); + resultDate.setUTCDate(resultDate.getUTCDate() + daysUntilSunday); return resultDate.valueOf(); } From eb4c6f3f094a97ae6a03a10645df62d89caa63df Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 6 May 2024 16:36:02 +0200 Subject: [PATCH 56/99] Get repo list with OrderBy alpha should respect owner too (#30784) instead of: - zowner/gcode - awesome/nul - zowner/nul - zowner/zzz we will get: - awesome/nul - zowner/gcode - zowner/nul - zowner/zzz (cherry picked from commit 8e8ca6c6530e49e39f970bdfa84716ffda8973d0) --- models/repo/search.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/repo/search.go b/models/repo/search.go index 4d64acf8cf..54d6dcfb44 100644 --- a/models/repo/search.go +++ b/models/repo/search.go @@ -8,14 +8,14 @@ import "code.gitea.io/gitea/models/db" // SearchOrderByMap represents all possible search order var SearchOrderByMap = map[string]map[string]db.SearchOrderBy{ "asc": { - "alpha": db.SearchOrderByAlphabetically, + "alpha": "owner_name ASC, name ASC", "created": db.SearchOrderByOldest, "updated": db.SearchOrderByLeastUpdated, "size": db.SearchOrderBySize, "id": db.SearchOrderByID, }, "desc": { - "alpha": db.SearchOrderByAlphabeticallyReverse, + "alpha": "owner_name DESC, name DESC", "created": db.SearchOrderByNewest, "updated": db.SearchOrderByRecentUpdated, "size": db.SearchOrderBySizeReverse, From 8cb854753288e57cdc429c2346ac8badd0d7ce78 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 7 May 2024 01:02:30 +0800 Subject: [PATCH 57/99] Make "sync branch" also sync object format and add tests (#30878) (cherry picked from commit 9c08637eae8c3a44d15e62d85144e07ae9dabbec) --- modules/git/repo.go | 27 --------------------------- modules/repository/branch.go | 10 ++++++++++ modules/repository/branch_test.go | 31 +++++++++++++++++++++++++++++++ services/repository/adopt.go | 4 ++++ 4 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 modules/repository/branch_test.go diff --git a/modules/git/repo.go b/modules/git/repo.go index e8a7016d99..857424fcd4 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -7,7 +7,6 @@ package git import ( "bytes" "context" - "errors" "fmt" "io" "net/url" @@ -63,32 +62,6 @@ func IsRepoURLAccessible(ctx context.Context, url string) bool { return err == nil } -// GetObjectFormatOfRepo returns the hash type of repository at a given path -func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat, error) { - var stdout, stderr strings.Builder - - err := NewCommand(ctx, "hash-object", "--stdin").Run(&RunOpts{ - Dir: repoPath, - Stdout: &stdout, - Stderr: &stderr, - Stdin: &strings.Reader{}, - }) - if err != nil { - return nil, err - } - - if stderr.Len() > 0 { - return nil, errors.New(stderr.String()) - } - - h, err := NewIDFromString(strings.TrimRight(stdout.String(), "\n")) - if err != nil { - return nil, err - } - - return h.Type(), nil -} - // InitRepository initializes a new Git repository. func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error { err := os.MkdirAll(repoPath, os.ModePerm) diff --git a/modules/repository/branch.go b/modules/repository/branch.go index e448490f4a..a3fca7c7ce 100644 --- a/modules/repository/branch.go +++ b/modules/repository/branch.go @@ -5,6 +5,7 @@ package repository import ( "context" + "fmt" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" @@ -36,6 +37,15 @@ func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) } func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, doerID int64) (int64, error) { + objFmt, err := gitRepo.GetObjectFormat() + if err != nil { + return 0, fmt.Errorf("GetObjectFormat: %w", err) + } + _, err = db.GetEngine(ctx).ID(repo.ID).Update(&repo_model.Repository{ObjectFormatName: objFmt.Name()}) + if err != nil { + return 0, fmt.Errorf("UpdateRepository: %w", err) + } + allBranches := container.Set[string]{} { branches, _, err := gitRepo.GetBranchNames(0, 0) diff --git a/modules/repository/branch_test.go b/modules/repository/branch_test.go new file mode 100644 index 0000000000..acf75a1ac0 --- /dev/null +++ b/modules/repository/branch_test.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestSyncRepoBranches(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + _, err := db.GetEngine(db.DefaultContext).ID(1).Update(&repo_model.Repository{ObjectFormatName: "bad-fmt"}) + assert.NoError(t, db.TruncateBeans(db.DefaultContext, &git_model.Branch{})) + assert.NoError(t, err) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + assert.Equal(t, "bad-fmt", repo.ObjectFormatName) + _, err = SyncRepoBranches(db.DefaultContext, 1, 0) + assert.NoError(t, err) + repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + assert.Equal(t, "sha1", repo.ObjectFormatName) + branch, err := git_model.GetBranch(db.DefaultContext, 1, "master") + assert.NoError(t, err) + assert.EqualValues(t, "master", branch.Name) +} diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 914cd9047b..f4d0da67a5 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -195,6 +195,10 @@ func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repo } defer gitRepo.Close() + if _, err = repo_module.SyncRepoBranchesWithRepo(ctx, repo, gitRepo, 0); err != nil { + return fmt.Errorf("SyncRepoBranches: %w", err) + } + if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { return fmt.Errorf("SyncReleasesWithTags: %w", err) } From 7028fe0b4d89c045b64ae891d2716e89965bc012 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 7 May 2024 14:45:30 +0800 Subject: [PATCH 58/99] Fix missing migrate actions artifacts (#30874) The actions artifacts should be able to be migrate to the new storage place. (cherry picked from commit 6ad77125cabe53a943d46b50e8cb79cfcea5491f) --- cmd/migrate_storage.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/cmd/migrate_storage.go b/cmd/migrate_storage.go index aa49445a89..357416fc33 100644 --- a/cmd/migrate_storage.go +++ b/cmd/migrate_storage.go @@ -34,7 +34,7 @@ var CmdMigrateStorage = &cli.Command{ Name: "type", Aliases: []string{"t"}, Value: "", - Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'", + Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts", }, &cli.StringFlag{ Name: "storage", @@ -160,6 +160,13 @@ 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 + }) +} + func runMigrateStorage(ctx *cli.Context) error { stdCtx, cancel := installSignals() defer cancel() @@ -223,13 +230,14 @@ func runMigrateStorage(ctx *cli.Context) error { } migratedMethods := map[string]func(context.Context, storage.ObjectStorage) error{ - "attachments": migrateAttachments, - "lfs": migrateLFS, - "avatars": migrateAvatars, - "repo-avatars": migrateRepoAvatars, - "repo-archivers": migrateRepoArchivers, - "packages": migratePackages, - "actions-log": migrateActionsLog, + "attachments": migrateAttachments, + "lfs": migrateLFS, + "avatars": migrateAvatars, + "repo-avatars": migrateRepoAvatars, + "repo-archivers": migrateRepoArchivers, + "packages": migratePackages, + "actions-log": migrateActionsLog, + "actions-artifacts": migrateActionsArtifacts, } tp := strings.ToLower(ctx.String("type")) From 12b6bcaf05e81e3ef615a0a3af8a76981ee21a9e Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 8 May 2024 04:42:33 +0200 Subject: [PATCH 59/99] Remove obsolete monaco workaround (#30893) This workaround is not neccessary any more since monaco 0.35.0. Ref: https://github.com/microsoft/monaco-editor/issues/2962 Ref: https://github.com/microsoft/vscode/pull/173688 (cherry picked from commit d9b37d085acb7e93409061e541b6a3aa53261bb0) --- web_src/js/features/codeeditor.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/web_src/js/features/codeeditor.js b/web_src/js/features/codeeditor.js index f5e4e74dc6..07a686f459 100644 --- a/web_src/js/features/codeeditor.js +++ b/web_src/js/features/codeeditor.js @@ -101,10 +101,6 @@ export async function createMonaco(textarea, filename, editorOpts) { }, }); - // Quick fix: https://github.com/microsoft/monaco-editor/issues/2962 - monaco.languages.register({id: 'vs.editor.nullLanguage'}); - monaco.languages.setLanguageConfiguration('vs.editor.nullLanguage', {}); - const editor = monaco.editor.create(container, { value: textarea.value, theme: 'gitea', From 9bc391250d8f758b1d8bc8005405d3ee08f46217 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 May 2024 21:17:11 +0800 Subject: [PATCH 60/99] Fix wrong transfer hint (#30889) Fix #30187 (cherry picked from commit f5f921c09555f5b31226fc31bbbb463649d0bfdc) --- routers/web/repo/setting/setting.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index e2c6a9902e..a7d4e75ff6 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -798,6 +798,7 @@ func SettingsPost(ctx *context.Context) { ctx.Repo.GitRepo = nil } + oldFullname := repo.FullName() if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil { if errors.Is(err, user_model.ErrBlockedByUser) { ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_blocked_doer"), tplSettingsOptions, nil) @@ -812,8 +813,13 @@ func SettingsPost(ctx *context.Context) { return } - log.Trace("Repository transfer process was started: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner) - ctx.Flash.Success(ctx.Tr("repo.settings.transfer_started", newOwner.DisplayName())) + if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer { + log.Trace("Repository transfer process was started: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner) + ctx.Flash.Success(ctx.Tr("repo.settings.transfer_started", newOwner.DisplayName())) + } else { + log.Trace("Repository transferred: %s -> %s", oldFullname, ctx.Repo.Repository.FullName()) + ctx.Flash.Success(ctx.Tr("repo.settings.transfer_succeed")) + } ctx.Redirect(repo.Link() + "/settings") case "cancel_transfer": From 7d3ca90dfed142ce62c75fbe041382b5f4334c01 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 May 2024 21:44:57 +0800 Subject: [PATCH 61/99] Fix various problems around projects board view (#30696) The previous implementation will start multiple POST requests from the frontend when moving a column and another bug is moving the default column will never be remembered in fact. - [x] This PR will allow the default column to move to a non-first position - [x] And it also uses one request instead of multiple requests when moving the columns - [x] Use a star instead of a pin as the icon for setting the default column action - [x] Inserted new column will be append to the end - [x] Fix #30701 the newly added issue will be append to the end of the default column - [x] Fix when deleting a column, all issues in it will be displayed from UI but database records exist. - [x] Add a limitation for columns in a project to 20. So the sorting will not be overflow because it's int8. --------- Co-authored-by: silverwind Co-authored-by: wxiaoguang (cherry picked from commit a303c973e0264dab45a787c4afa200e183e0d953) Conflicts: routers/web/web.go e91733468ef726fc9365aa4820cdd5f2ddfdaa23 Add missing database transaction for new issue (#29490) was not cherry-picked services/issue/issue.go fe6792dff3 Enable/disable owner and repo projects independently (#28805) was not cherry-picked --- models/db/engine.go | 1 + models/issues/issue_project.go | 107 +++++++++++++++----------- models/project/board.go | 95 ++++++++++++++++++++--- models/project/board_test.go | 87 ++++++++++++++++++++- models/project/issue.go | 51 ++++++++++-- models/project/project.go | 7 ++ routers/web/org/projects.go | 69 ----------------- routers/web/repo/issue.go | 4 +- routers/web/repo/projects.go | 17 ++-- routers/web/repo/pull.go | 14 ++-- routers/web/shared/project/column.go | 48 ++++++++++++ routers/web/web.go | 3 + templates/projects/view.tmpl | 2 +- tests/integration/org_project_test.go | 6 +- tests/integration/project_test.go | 60 +++++++++++++++ web_src/js/features/repo-projects.js | 26 ++++--- 16 files changed, 428 insertions(+), 169 deletions(-) create mode 100644 routers/web/shared/project/column.go diff --git a/models/db/engine.go b/models/db/engine.go index b7146e87f2..61649592e7 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -58,6 +58,7 @@ type Engine interface { SumInt(bean any, columnName string) (res int64, err error) Sync(...any) error Select(string) *xorm.Session + SetExpr(string, any) *xorm.Session NotIn(string, ...any) *xorm.Session OrderBy(any, ...any) *xorm.Session Exist(...any) (bool, error) diff --git a/models/issues/issue_project.go b/models/issues/issue_project.go index 907a5a17b9..e31d2ef151 100644 --- a/models/issues/issue_project.go +++ b/models/issues/issue_project.go @@ -5,11 +5,11 @@ package issues import ( "context" - "fmt" "code.gitea.io/gitea/models/db" project_model "code.gitea.io/gitea/models/project" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/util" ) // LoadProject load the project the issue was assigned to @@ -90,58 +90,73 @@ func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (m return issuesMap, nil } -// ChangeProjectAssign changes the project associated with an issue -func ChangeProjectAssign(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() +// IssueAssignOrRemoveProject changes the project associated with an issue +// If newProjectID is 0, the issue is removed from the project +func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID, newColumnID int64) error { + return db.WithTx(ctx, func(ctx context.Context) error { + oldProjectID := issue.projectID(ctx) - if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil { - return err - } - - return committer.Commit() -} - -func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error { - oldProjectID := issue.projectID(ctx) - - if err := issue.LoadRepo(ctx); err != nil { - return err - } - - // Only check if we add a new project and not remove it. - if newProjectID > 0 { - newProject, err := project_model.GetProjectByID(ctx, newProjectID) - if err != nil { + if err := issue.LoadRepo(ctx); err != nil { return err } - if newProject.RepoID != issue.RepoID && newProject.OwnerID != issue.Repo.OwnerID { - return fmt.Errorf("issue's repository is not the same as project's repository") + + // Only check if we add a new project and not remove it. + if newProjectID > 0 { + newProject, err := project_model.GetProjectByID(ctx, newProjectID) + if err != nil { + return err + } + if !newProject.CanBeAccessedByOwnerRepo(issue.Repo.OwnerID, issue.Repo) { + return util.NewPermissionDeniedErrorf("issue %d can't be accessed by project %d", issue.ID, newProject.ID) + } + if newColumnID == 0 { + newDefaultColumn, err := newProject.GetDefaultBoard(ctx) + if err != nil { + return err + } + newColumnID = newDefaultColumn.ID + } } - } - if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil { - return err - } - - if oldProjectID > 0 || newProjectID > 0 { - if _, err := CreateComment(ctx, &CreateCommentOptions{ - Type: CommentTypeProject, - Doer: doer, - Repo: issue.Repo, - Issue: issue, - OldProjectID: oldProjectID, - ProjectID: newProjectID, - }); err != nil { + if _, err := db.GetEngine(ctx).Where("project_issue.issue_id=?", issue.ID).Delete(&project_model.ProjectIssue{}); err != nil { return err } - } - return db.Insert(ctx, &project_model.ProjectIssue{ - IssueID: issue.ID, - ProjectID: newProjectID, + if oldProjectID > 0 || newProjectID > 0 { + if _, err := CreateComment(ctx, &CreateCommentOptions{ + Type: CommentTypeProject, + Doer: doer, + Repo: issue.Repo, + Issue: issue, + OldProjectID: oldProjectID, + ProjectID: newProjectID, + }); err != nil { + return err + } + } + if newProjectID == 0 { + return nil + } + if newColumnID == 0 { + panic("newColumnID must not be zero") // shouldn't happen + } + + res := struct { + MaxSorting int64 + IssueCount int64 + }{} + if _, err := db.GetEngine(ctx).Select("max(sorting) as max_sorting, count(*) as issue_count").Table("project_issue"). + Where("project_id=?", newProjectID). + And("project_board_id=?", newColumnID). + Get(&res); err != nil { + return err + } + newSorting := util.Iif(res.IssueCount > 0, res.MaxSorting+1, 0) + return db.Insert(ctx, &project_model.ProjectIssue{ + IssueID: issue.ID, + ProjectID: newProjectID, + ProjectBoardID: newColumnID, + Sorting: newSorting, + }) }) } diff --git a/models/project/board.go b/models/project/board.go index 7faabc52c5..a52baa0c18 100644 --- a/models/project/board.go +++ b/models/project/board.go @@ -5,12 +5,14 @@ package project import ( "context" + "errors" "fmt" "regexp" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) @@ -82,6 +84,17 @@ func (b *Board) NumIssues(ctx context.Context) int { return int(c) } +func (b *Board) GetIssues(ctx context.Context) ([]*ProjectIssue, error) { + issues := make([]*ProjectIssue, 0, 5) + if err := db.GetEngine(ctx).Where("project_id=?", b.ProjectID). + And("project_board_id=?", b.ID). + OrderBy("sorting, id"). + Find(&issues); err != nil { + return nil, err + } + return issues, nil +} + func init() { db.RegisterModel(new(Board)) } @@ -150,12 +163,27 @@ func createBoardsForProjectsType(ctx context.Context, project *Project) error { return db.Insert(ctx, boards) } +// maxProjectColumns max columns allowed in a project, this should not bigger than 127 +// because sorting is int8 in database +const maxProjectColumns = 20 + // NewBoard adds a new project board to a given project func NewBoard(ctx context.Context, board *Board) error { if len(board.Color) != 0 && !BoardColorPattern.MatchString(board.Color) { return fmt.Errorf("bad color code: %s", board.Color) } - + res := struct { + MaxSorting int64 + ColumnCount int64 + }{} + if _, err := db.GetEngine(ctx).Select("max(sorting) as max_sorting, count(*) as column_count").Table("project_board"). + Where("project_id=?", board.ProjectID).Get(&res); err != nil { + return err + } + if res.ColumnCount >= maxProjectColumns { + return fmt.Errorf("NewBoard: maximum number of columns reached") + } + board.Sorting = int8(util.Iif(res.ColumnCount > 0, res.MaxSorting+1, 0)) _, err := db.GetEngine(ctx).Insert(board) return err } @@ -189,7 +217,17 @@ func deleteBoardByID(ctx context.Context, boardID int64) error { return fmt.Errorf("deleteBoardByID: cannot delete default board") } - if err = board.removeIssues(ctx); err != nil { + // move all issues to the default column + project, err := GetProjectByID(ctx, board.ProjectID) + if err != nil { + return err + } + defaultColumn, err := project.GetDefaultBoard(ctx) + if err != nil { + return err + } + + if err = board.moveIssuesToAnotherColumn(ctx, defaultColumn); err != nil { return err } @@ -242,21 +280,15 @@ func UpdateBoard(ctx context.Context, board *Board) error { // GetBoards fetches all boards related to a project func (p *Project) GetBoards(ctx context.Context) (BoardList, error) { boards := make([]*Board, 0, 5) - - if err := db.GetEngine(ctx).Where("project_id=? AND `default`=?", p.ID, false).OrderBy("sorting").Find(&boards); err != nil { + if err := db.GetEngine(ctx).Where("project_id=?", p.ID).OrderBy("sorting, id").Find(&boards); err != nil { return nil, err } - defaultB, err := p.getDefaultBoard(ctx) - if err != nil { - return nil, err - } - - return append([]*Board{defaultB}, boards...), nil + return boards, nil } -// getDefaultBoard return default board and ensure only one exists -func (p *Project) getDefaultBoard(ctx context.Context) (*Board, error) { +// GetDefaultBoard return default board and ensure only one exists +func (p *Project) GetDefaultBoard(ctx context.Context) (*Board, error) { var board Board has, err := db.GetEngine(ctx). Where("project_id=? AND `default` = ?", p.ID, true). @@ -316,3 +348,42 @@ func UpdateBoardSorting(ctx context.Context, bs BoardList) error { return nil }) } + +func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (BoardList, error) { + columns := make([]*Board, 0, 5) + if err := db.GetEngine(ctx). + Where("project_id =?", projectID). + In("id", columnsIDs). + OrderBy("sorting").Find(&columns); err != nil { + return nil, err + } + return columns, nil +} + +// MoveColumnsOnProject sorts columns in a project +func MoveColumnsOnProject(ctx context.Context, project *Project, sortedColumnIDs map[int64]int64) error { + return db.WithTx(ctx, func(ctx context.Context) error { + sess := db.GetEngine(ctx) + columnIDs := util.ValuesOfMap(sortedColumnIDs) + movedColumns, err := GetColumnsByIDs(ctx, project.ID, columnIDs) + if err != nil { + return err + } + if len(movedColumns) != len(sortedColumnIDs) { + return errors.New("some columns do not exist") + } + + for _, column := range movedColumns { + if column.ProjectID != project.ID { + return fmt.Errorf("column[%d]'s projectID is not equal to project's ID [%d]", column.ProjectID, project.ID) + } + } + + for sorting, columnID := range sortedColumnIDs { + if _, err := sess.Exec("UPDATE `project_board` SET sorting=? WHERE id=?", sorting, columnID); err != nil { + return err + } + } + return nil + }) +} diff --git a/models/project/board_test.go b/models/project/board_test.go index 71ba29a589..da922ff7ad 100644 --- a/models/project/board_test.go +++ b/models/project/board_test.go @@ -4,6 +4,8 @@ package project import ( + "fmt" + "strings" "testing" "code.gitea.io/gitea/models/db" @@ -19,7 +21,7 @@ func TestGetDefaultBoard(t *testing.T) { assert.NoError(t, err) // check if default board was added - board, err := projectWithoutDefault.getDefaultBoard(db.DefaultContext) + board, err := projectWithoutDefault.GetDefaultBoard(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, int64(5), board.ProjectID) assert.Equal(t, "Uncategorized", board.Title) @@ -28,7 +30,7 @@ func TestGetDefaultBoard(t *testing.T) { assert.NoError(t, err) // check if multiple defaults were removed - board, err = projectWithMultipleDefaults.getDefaultBoard(db.DefaultContext) + board, err = projectWithMultipleDefaults.GetDefaultBoard(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, int64(6), board.ProjectID) assert.Equal(t, int64(9), board.ID) @@ -42,3 +44,84 @@ func TestGetDefaultBoard(t *testing.T) { assert.Equal(t, int64(6), board.ProjectID) assert.False(t, board.Default) } + +func Test_moveIssuesToAnotherColumn(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + column1 := unittest.AssertExistsAndLoadBean(t, &Board{ID: 1, ProjectID: 1}) + + issues, err := column1.GetIssues(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, issues, 1) + assert.EqualValues(t, 1, issues[0].ID) + + column2 := unittest.AssertExistsAndLoadBean(t, &Board{ID: 2, ProjectID: 1}) + issues, err = column2.GetIssues(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, issues, 1) + assert.EqualValues(t, 3, issues[0].ID) + + err = column1.moveIssuesToAnotherColumn(db.DefaultContext, column2) + assert.NoError(t, err) + + issues, err = column1.GetIssues(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, issues, 0) + + issues, err = column2.GetIssues(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, issues, 2) + assert.EqualValues(t, 3, issues[0].ID) + assert.EqualValues(t, 0, issues[0].Sorting) + assert.EqualValues(t, 1, issues[1].ID) + assert.EqualValues(t, 1, issues[1].Sorting) +} + +func Test_MoveColumnsOnProject(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + columns, err := project1.GetBoards(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, columns, 3) + assert.EqualValues(t, 0, columns[0].Sorting) // even if there is no default sorting, the code should also work + assert.EqualValues(t, 0, columns[1].Sorting) + assert.EqualValues(t, 0, columns[2].Sorting) + + err = MoveColumnsOnProject(db.DefaultContext, project1, map[int64]int64{ + 0: columns[1].ID, + 1: columns[2].ID, + 2: columns[0].ID, + }) + assert.NoError(t, err) + + columnsAfter, err := project1.GetBoards(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, columnsAfter, 3) + assert.EqualValues(t, columns[1].ID, columnsAfter[0].ID) + assert.EqualValues(t, columns[2].ID, columnsAfter[1].ID) + assert.EqualValues(t, columns[0].ID, columnsAfter[2].ID) +} + +func Test_NewBoard(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + columns, err := project1.GetBoards(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, columns, 3) + + for i := 0; i < maxProjectColumns-3; i++ { + err := NewBoard(db.DefaultContext, &Board{ + Title: fmt.Sprintf("board-%d", i+4), + ProjectID: project1.ID, + }) + assert.NoError(t, err) + } + err = NewBoard(db.DefaultContext, &Board{ + Title: "board-21", + ProjectID: project1.ID, + }) + assert.Error(t, err) + assert.True(t, strings.Contains(err.Error(), "maximum number of columns reached")) +} diff --git a/models/project/issue.go b/models/project/issue.go index ebc9719de5..32e72e909d 100644 --- a/models/project/issue.go +++ b/models/project/issue.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" ) // ProjectIssue saves relation from issue to a project @@ -17,7 +18,7 @@ type ProjectIssue struct { //revive:disable-line:exported IssueID int64 `xorm:"INDEX"` ProjectID int64 `xorm:"INDEX"` - // If 0, then it has not been added to a specific board in the project + // ProjectBoardID should not be zero since 1.22. If it's zero, the issue will not be displayed on UI and it might result in errors. ProjectBoardID int64 `xorm:"INDEX"` // the sorting order on the board @@ -79,11 +80,8 @@ func (p *Project) NumOpenIssues(ctx context.Context) int { func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs map[int64]int64) error { return db.WithTx(ctx, func(ctx context.Context) error { sess := db.GetEngine(ctx) + issueIDs := util.ValuesOfMap(sortedIssueIDs) - issueIDs := make([]int64, 0, len(sortedIssueIDs)) - for _, issueID := range sortedIssueIDs { - issueIDs = append(issueIDs, issueID) - } count, err := sess.Table(new(ProjectIssue)).Where("project_id=?", board.ProjectID).In("issue_id", issueIDs).Count() if err != nil { return err @@ -102,7 +100,44 @@ func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs }) } -func (b *Board) removeIssues(ctx context.Context) error { - _, err := db.GetEngine(ctx).Exec("UPDATE `project_issue` SET project_board_id = 0 WHERE project_board_id = ? ", b.ID) - return err +func (b *Board) moveIssuesToAnotherColumn(ctx context.Context, newColumn *Board) error { + if b.ProjectID != newColumn.ProjectID { + return fmt.Errorf("columns have to be in the same project") + } + + if b.ID == newColumn.ID { + return nil + } + + res := struct { + MaxSorting int64 + IssueCount int64 + }{} + if _, err := db.GetEngine(ctx).Select("max(sorting) as max_sorting, count(*) as issue_count"). + Table("project_issue"). + Where("project_id=?", newColumn.ProjectID). + And("project_board_id=?", newColumn.ID). + Get(&res); err != nil { + return err + } + + issues, err := b.GetIssues(ctx) + if err != nil { + return err + } + if len(issues) == 0 { + return nil + } + + nextSorting := util.Iif(res.IssueCount > 0, res.MaxSorting+1, 0) + return db.WithTx(ctx, func(ctx context.Context) error { + for i, issue := range issues { + issue.ProjectBoardID = newColumn.ID + issue.Sorting = nextSorting + int64(i) + if _, err := db.GetEngine(ctx).ID(issue.ID).Cols("project_board_id", "sorting").Update(issue); err != nil { + return err + } + } + return nil + }) } diff --git a/models/project/project.go b/models/project/project.go index 8f9ee2a99e..8be38694c5 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -161,6 +161,13 @@ func (p *Project) IsRepositoryProject() bool { return p.Type == TypeRepository } +func (p *Project) CanBeAccessedByOwnerRepo(ownerID int64, repo *repo_model.Repository) bool { + if p.Type == TypeRepository { + return repo != nil && p.RepoID == repo.ID // if a project belongs to a repository, then its OwnerID is 0 and can be ignored + } + return p.OwnerID == ownerID && p.RepoID == 0 +} + func init() { db.RegisterModel(new(Project)) } diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 821228b347..e6f3a19625 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "net/http" - "strconv" "strings" "code.gitea.io/gitea/models/db" @@ -390,74 +389,6 @@ func ViewProject(ctx *context.Context) { ctx.HTML(http.StatusOK, tplProjectsView) } -func getActionIssues(ctx *context.Context) issues_model.IssueList { - commaSeparatedIssueIDs := ctx.FormString("issue_ids") - if len(commaSeparatedIssueIDs) == 0 { - return nil - } - issueIDs := make([]int64, 0, 10) - for _, stringIssueID := range strings.Split(commaSeparatedIssueIDs, ",") { - issueID, err := strconv.ParseInt(stringIssueID, 10, 64) - if err != nil { - ctx.ServerError("ParseInt", err) - return nil - } - issueIDs = append(issueIDs, issueID) - } - issues, err := issues_model.GetIssuesByIDs(ctx, issueIDs) - if err != nil { - ctx.ServerError("GetIssuesByIDs", err) - return nil - } - // Check access rights for all issues - issueUnitEnabled := ctx.Repo.CanRead(unit.TypeIssues) - prUnitEnabled := ctx.Repo.CanRead(unit.TypePullRequests) - for _, issue := range issues { - if issue.RepoID != ctx.Repo.Repository.ID { - ctx.NotFound("some issue's RepoID is incorrect", errors.New("some issue's RepoID is incorrect")) - return nil - } - if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled { - ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil) - return nil - } - if err = issue.LoadAttributes(ctx); err != nil { - ctx.ServerError("LoadAttributes", err) - return nil - } - } - return issues -} - -// UpdateIssueProject change an issue's project -func UpdateIssueProject(ctx *context.Context) { - issues := getActionIssues(ctx) - if ctx.Written() { - return - } - - if err := issues.LoadProjects(ctx); err != nil { - ctx.ServerError("LoadProjects", err) - return - } - - projectID := ctx.FormInt64("id") - for _, issue := range issues { - if issue.Project != nil { - if issue.Project.ID == projectID { - continue - } - } - - if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) - return - } - } - - ctx.JSONOK() -} - // DeleteProjectBoard allows for the deletion of a project board func DeleteProjectBoard(ctx *context.Context) { if ctx.Doer == nil { diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 9f4979cb67..350e577ede 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1266,8 +1266,8 @@ func NewIssuePost(ctx *context.Context) { ctx.Error(http.StatusBadRequest, "user hasn't permissions to read projects") return } - if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) + if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, 0); err != nil { + ctx.ServerError("IssueAssignOrRemoveProject", err) return } } diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index a0c044fd64..934cf8873b 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" @@ -382,17 +383,21 @@ func UpdateIssueProject(ctx *context.Context) { ctx.ServerError("LoadProjects", err) return } + if _, err := issues.LoadRepositories(ctx); err != nil { + ctx.ServerError("LoadProjects", err) + return + } projectID := ctx.FormInt64("id") for _, issue := range issues { - if issue.Project != nil { - if issue.Project.ID == projectID { + if issue.Project != nil && issue.Project.ID == projectID { + continue + } + if err := issues_model.IssueAssignOrRemoveProject(ctx, issue, ctx.Doer, projectID, 0); err != nil { + if errors.Is(err, util.ErrPermissionDenied) { continue } - } - - if err := issues_model.ChangeProjectAssign(ctx, issue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) + ctx.ServerError("IssueAssignOrRemoveProject", err) return } } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index a0dd36927f..b63817d266 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1537,14 +1537,12 @@ func CompareAndPullRequestPost(ctx *context.Context) { return } - if projectID > 0 { - if !ctx.Repo.CanWrite(unit.TypeProjects) { - ctx.Error(http.StatusBadRequest, "user hasn't the permission to write to projects") - return - } - if err := issues_model.ChangeProjectAssign(ctx, pullIssue, ctx.Doer, projectID); err != nil { - ctx.ServerError("ChangeProjectAssign", err) - return + if projectID > 0 && ctx.Repo.CanWrite(unit.TypeProjects) { + if err := issues_model.IssueAssignOrRemoveProject(ctx, pullIssue, ctx.Doer, projectID, 0); err != nil { + if !errors.Is(err, util.ErrPermissionDenied) { + ctx.ServerError("IssueAssignOrRemoveProject", err) + return + } } } diff --git a/routers/web/shared/project/column.go b/routers/web/shared/project/column.go new file mode 100644 index 0000000000..599842ea9e --- /dev/null +++ b/routers/web/shared/project/column.go @@ -0,0 +1,48 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package project + +import ( + project_model "code.gitea.io/gitea/models/project" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/services/context" +) + +// MoveColumns moves or keeps columns in a project and sorts them inside that project +func MoveColumns(ctx *context.Context) { + project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) + if err != nil { + ctx.NotFoundOrServerError("GetProjectByID", project_model.IsErrProjectNotExist, err) + return + } + if !project.CanBeAccessedByOwnerRepo(ctx.ContextUser.ID, ctx.Repo.Repository) { + ctx.NotFound("CanBeAccessedByOwnerRepo", nil) + return + } + + type movedColumnsForm struct { + Columns []struct { + ColumnID int64 `json:"columnID"` + Sorting int64 `json:"sorting"` + } `json:"columns"` + } + + form := &movedColumnsForm{} + if err = json.NewDecoder(ctx.Req.Body).Decode(&form); err != nil { + ctx.ServerError("DecodeMovedColumnsForm", err) + return + } + + sortedColumnIDs := make(map[int64]int64) + for _, column := range form.Columns { + sortedColumnIDs[column.Sorting] = column.ColumnID + } + + if err = project_model.MoveColumnsOnProject(ctx, project, sortedColumnIDs); err != nil { + ctx.ServerError("MoveColumnsOnProject", err) + return + } + + ctx.JSONOK() +} diff --git a/routers/web/web.go b/routers/web/web.go index 8faedca178..78c88fb938 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -39,6 +39,7 @@ import ( "code.gitea.io/gitea/routers/web/repo/badges" repo_flags "code.gitea.io/gitea/routers/web/repo/flags" repo_setting "code.gitea.io/gitea/routers/web/repo/setting" + "code.gitea.io/gitea/routers/web/shared/project" "code.gitea.io/gitea/routers/web/user" user_setting "code.gitea.io/gitea/routers/web/user/setting" "code.gitea.io/gitea/routers/web/user/setting/security" @@ -976,6 +977,7 @@ func registerRoutes(m *web.Route) { m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost) m.Group("/{id}", func() { m.Post("", web.Bind(forms.EditProjectBoardForm{}), org.AddBoardToProjectPost) + m.Post("/move", project.MoveColumns) m.Post("/delete", org.DeleteProject) m.Get("/edit", org.RenderEditProject) @@ -1349,6 +1351,7 @@ func registerRoutes(m *web.Route) { m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost) m.Group("/{id}", func() { m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost) + m.Post("/move", project.MoveColumns) m.Post("/delete", repo.DeleteProject) m.Get("/edit", repo.RenderEditProject) diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 3e000660e2..47f214a44e 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -64,7 +64,7 @@
-
+
{{range .Columns}}
diff --git a/tests/integration/org_project_test.go b/tests/integration/org_project_test.go index a14004f6b0..ca39cf5130 100644 --- a/tests/integration/org_project_test.go +++ b/tests/integration/org_project_test.go @@ -5,17 +5,17 @@ package integration import ( "net/http" + "slices" "testing" unit_model "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/tests" ) func TestOrgProjectAccess(t *testing.T) { defer tests.PrepareTestEnv(t)() - - // disable repo project unit - unit_model.DisabledRepoUnits = []unit_model.Type{unit_model.TypeProjects} + defer test.MockVariableValue(&unit_model.DisabledRepoUnits, append(slices.Clone(unit_model.DisabledRepoUnits), unit_model.TypeProjects))() // repo project, 404 req := NewRequest(t, "GET", "/user2/repo1/projects") diff --git a/tests/integration/project_test.go b/tests/integration/project_test.go index 45061c5b24..5ddea4314a 100644 --- a/tests/integration/project_test.go +++ b/tests/integration/project_test.go @@ -4,10 +4,17 @@ package integration import ( + "fmt" "net/http" "testing" + "code.gitea.io/gitea/models/db" + project_model "code.gitea.io/gitea/models/project" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" ) func TestPrivateRepoProject(t *testing.T) { @@ -21,3 +28,56 @@ func TestPrivateRepoProject(t *testing.T) { req = NewRequest(t, "GET", "/user31/-/projects") sess.MakeRequest(t, req, http.StatusOK) } + +func TestMoveRepoProjectColumns(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + + project1 := project_model.Project{ + Title: "new created project", + RepoID: repo2.ID, + Type: project_model.TypeRepository, + BoardType: project_model.BoardTypeNone, + } + err := project_model.NewProject(db.DefaultContext, &project1) + assert.NoError(t, err) + + for i := 0; i < 3; i++ { + err = project_model.NewBoard(db.DefaultContext, &project_model.Board{ + Title: fmt.Sprintf("column %d", i+1), + ProjectID: project1.ID, + }) + assert.NoError(t, err) + } + + columns, err := project1.GetBoards(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, columns, 3) + assert.EqualValues(t, 0, columns[0].Sorting) + assert.EqualValues(t, 1, columns[1].Sorting) + assert.EqualValues(t, 2, columns[2].Sorting) + + sess := loginUser(t, "user1") + req := NewRequest(t, "GET", fmt.Sprintf("/%s/projects/%d", repo2.FullName(), project1.ID)) + resp := sess.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s/projects/%d/move?_csrf="+htmlDoc.GetCSRF(), repo2.FullName(), project1.ID), map[string]any{ + "columns": []map[string]any{ + {"columnID": columns[1].ID, "sorting": 0}, + {"columnID": columns[2].ID, "sorting": 1}, + {"columnID": columns[0].ID, "sorting": 2}, + }, + }) + sess.MakeRequest(t, req, http.StatusOK) + + columnsAfter, err := project1.GetBoards(db.DefaultContext) + assert.NoError(t, err) + assert.Len(t, columns, 3) + assert.EqualValues(t, columns[1].ID, columnsAfter[0].ID) + assert.EqualValues(t, columns[2].ID, columnsAfter[1].ID) + assert.EqualValues(t, columns[0].ID, columnsAfter[2].ID) + + assert.NoError(t, project_model.DeleteProjectByID(db.DefaultContext, project1.ID)) +} diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js index a869c24c82..a1cc4b346b 100644 --- a/web_src/js/features/repo-projects.js +++ b/web_src/js/features/repo-projects.js @@ -2,7 +2,6 @@ import $ from 'jquery'; import {contrastColor} from '../utils/color.js'; import {createSortable} from '../modules/sortable.js'; import {POST, DELETE, PUT} from '../modules/fetch.js'; -import tinycolor from 'tinycolor2'; function updateIssueCount(cards) { const parent = cards.parentElement; @@ -63,17 +62,20 @@ async function initRepoProjectSortable() { delay: 500, onSort: async () => { boardColumns = mainBoard.getElementsByClassName('project-column'); - for (let i = 0; i < boardColumns.length; i++) { - const column = boardColumns[i]; - if (parseInt(column.getAttribute('data-sorting')) !== i) { - try { - const bgColor = column.style.backgroundColor; // will be rgb() string - const color = bgColor ? tinycolor(bgColor).toHexString() : ''; - await PUT(column.getAttribute('data-url'), {data: {sorting: i, color}}); - } catch (error) { - console.error(error); - } - } + + const columnSorting = { + columns: Array.from(boardColumns, (column, i) => ({ + columnID: parseInt(column.getAttribute('data-id')), + sorting: i, + })), + }; + + try { + await POST(mainBoard.getAttribute('data-url'), { + data: columnSorting, + }); + } catch (error) { + console.error(error); } }, }); From 8f0f6bf89cdcd12cd4daa761aa259fdba7e32b50 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 8 May 2024 22:45:15 +0800 Subject: [PATCH 62/99] Update issue indexer after merging a PR (#30715) Fix #30684 (cherry picked from commit f09e68ec33262d5356779572a0b1c66e6e86590f) Conflicts: tests/integration/pull_merge_test.go trivial context conflict --- services/indexer/notify.go | 16 ++++++++ tests/integration/pull_merge_test.go | 61 ++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/services/indexer/notify.go b/services/indexer/notify.go index f1e21a2d40..e2cfe477d3 100644 --- a/services/indexer/notify.go +++ b/services/indexer/notify.go @@ -152,3 +152,19 @@ func (r *indexerNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode func (r *indexerNotifier) IssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) { issue_indexer.UpdateIssueIndexer(ctx, issue.ID) } + +func (r *indexerNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + issue_indexer.UpdateIssueIndexer(ctx, pr.Issue.ID) +} + +func (r *indexerNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) { + if err := pr.LoadIssue(ctx); err != nil { + log.Error("LoadIssue: %v", err) + return + } + issue_indexer.UpdateIssueIndexer(ctx, pr.Issue.ID) +} diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 3bd4f57410..6dddb84bcd 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/hostmatcher" + "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" @@ -600,3 +601,63 @@ func TestPullDontRetargetChildOnWrongRepo(t *testing.T) { assert.EqualValues(t, "Closed", prStatus) }) } + +func TestPullMergeIndexerNotifier(t *testing.T) { + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // create a pull request + session := loginUser(t, "user1") + testRepoFork(t, session, "user2", "repo1", "user1", "repo1") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") + createPullResp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "Indexer notifier test pull") + + assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0)) + time.Sleep(time.Second) + + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ + OwnerName: "user2", + Name: "repo1", + }) + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ + RepoID: repo1.ID, + Title: "Indexer notifier test pull", + IsPull: true, + IsClosed: false, + }) + + // build the request for searching issues + link, _ := url.Parse("/api/v1/repos/issues/search") + query := url.Values{} + query.Add("state", "closed") + query.Add("type", "pulls") + query.Add("q", "notifier") + link.RawQuery = query.Encode() + + // search issues + searchIssuesResp := session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + var apiIssuesBefore []*api.Issue + DecodeJSON(t, searchIssuesResp, &apiIssuesBefore) + assert.Len(t, apiIssuesBefore, 0) + + // merge the pull request + elem := strings.Split(test.RedirectURL(createPullResp), "/") + assert.EqualValues(t, "pulls", elem[3]) + testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + + // check if the issue is closed + issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ + ID: issue.ID, + }) + assert.True(t, issue.IsClosed) + + assert.NoError(t, queue.GetManager().FlushAll(context.Background(), 0)) + time.Sleep(time.Second) + + // search issues again + searchIssuesResp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + var apiIssuesAfter []*api.Issue + DecodeJSON(t, searchIssuesResp, &apiIssuesAfter) + if assert.Len(t, apiIssuesAfter, 1) { + assert.Equal(t, issue.ID, apiIssuesAfter[0].ID) + } + }) +} From 6c9b8401f9e711ab4d235b484e7fee362ea50305 Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Thu, 9 May 2024 01:11:43 +0900 Subject: [PATCH 63/99] Fix misspelling of mergable (#30896) https://github.com/go-gitea/gitea/pull/25812#issuecomment-2099833692 Follow #30573 (cherry picked from commit f7d2f695a4c57b245830a526e77fa62e99e00254) Conflicts: services/pull/check.go trivial conflict because 9b2536b78fdcd3cf444a2f54857d9871e153858f Update misspell to 0.5.1 and add `misspellings.csv` (#30573) was not cherry-picked --- routers/api/v1/repo/pull.go | 4 ++-- routers/web/repo/pull.go | 4 ++-- services/automerge/automerge.go | 4 ++-- services/pull/check.go | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index dbb7de6e66..e3d3665ebe 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -878,7 +878,7 @@ func MergePullRequest(ctx *context.APIContext) { } // start with merging by checking - if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil { + if err := pull_service.CheckPullMergeable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil { if errors.Is(err, pull_service.ErrIsClosed) { ctx.NotFound() } else if errors.Is(err, pull_service.ErrUserNotAllowedToMerge) { @@ -887,7 +887,7 @@ func MergePullRequest(ctx *context.APIContext) { ctx.Error(http.StatusMethodNotAllowed, "PR already merged", "") } else if errors.Is(err, pull_service.ErrIsWorkInProgress) { ctx.Error(http.StatusMethodNotAllowed, "PR is a work in progress", "Work in progress PRs cannot be merged") - } else if errors.Is(err, pull_service.ErrNotMergableState) { + } else if errors.Is(err, pull_service.ErrNotMergeableState) { ctx.Error(http.StatusMethodNotAllowed, "PR not in mergeable state", "Please try again later") } else if models.IsErrDisallowedToMerge(err) { ctx.Error(http.StatusMethodNotAllowed, "PR is not ready to be merged", err) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index b63817d266..be6511afaa 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1218,7 +1218,7 @@ func MergePullRequest(ctx *context.Context) { } // start with merging by checking - if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil { + if err := pull_service.CheckPullMergeable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil { switch { case errors.Is(err, pull_service.ErrIsClosed): if issue.IsPull { @@ -1232,7 +1232,7 @@ func MergePullRequest(ctx *context.Context) { ctx.JSONError(ctx.Tr("repo.pulls.has_merged")) case errors.Is(err, pull_service.ErrIsWorkInProgress): ctx.JSONError(ctx.Tr("repo.pulls.no_merge_wip")) - case errors.Is(err, pull_service.ErrNotMergableState): + case errors.Is(err, pull_service.ErrNotMergeableState): ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready")) case models.IsErrDisallowedToMerge(err): ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready")) diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index bd427bef9f..bd1317c7f4 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -229,12 +229,12 @@ func handlePull(pullID int64, sha string) { return } - if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, pull_service.MergeCheckTypeGeneral, false); err != nil { + if err := pull_service.CheckPullMergeable(ctx, doer, &perm, pr, pull_service.MergeCheckTypeGeneral, false); err != nil { if errors.Is(pull_service.ErrUserNotAllowedToMerge, err) { log.Info("%-v was scheduled to automerge by an unauthorized user", pr) return } - log.Error("%-v CheckPullMergable: %v", pr, err) + log.Error("%-v CheckPullMergeable: %v", pr, err) return } diff --git a/services/pull/check.go b/services/pull/check.go index 5cca0e1f28..765f7580cb 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -39,7 +39,7 @@ var ( ErrHasMerged = errors.New("has already been merged") ErrIsWorkInProgress = errors.New("work in progress PRs cannot be merged") ErrIsChecking = errors.New("cannot merge while conflict checking is in progress") - ErrNotMergableState = errors.New("not in mergeable state") + ErrNotMergeableState = errors.New("not in mergeable state") ErrDependenciesLeft = errors.New("is blocked by an open dependency") ) @@ -66,8 +66,8 @@ const ( MergeCheckTypeAuto // Auto Merge (Scheduled Merge) After Checks Succeed ) -// CheckPullMergable check if the pull mergeable based on all conditions (branch protection, merge options, ...) -func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error { +// CheckPullMergeable check if the pull mergeable based on all conditions (branch protection, merge options, ...) +func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error { return db.WithTx(stdCtx, func(ctx context.Context) error { if pr.HasMerged { return ErrHasMerged @@ -97,7 +97,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce } if !pr.CanAutoMerge() && !pr.IsEmpty() { - return ErrNotMergableState + return ErrNotMergeableState } if pr.IsChecking() { From 1a250c7b2b821547e1ae3b049f4e56368bf9494e Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Thu, 9 May 2024 17:44:26 +0900 Subject: [PATCH 64/99] Fix incorrect default branch when adopt a repository (#30912) Fix #30521 we should sync branches first, then detect default branch, or `git_model.FindBranchNames` will always return empty list, and the detection will be wrong. (cherry picked from commit e94723f2de7d9bf12d870f5ce9ffb291a99ba090) Conflicts: services/repository/adopt.go trivial conflict because e80466f734 Resolve lint for unused parameter and unnecessary type arguments (#30750) was not cherry-picked --- services/repository/adopt.go | 37 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/services/repository/adopt.go b/services/repository/adopt.go index f4d0da67a5..3d6fe71a09 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -36,10 +36,6 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR } } - if len(opts.DefaultBranch) == 0 { - opts.DefaultBranch = setting.Repository.DefaultBranch - } - repo := &repo_model.Repository{ OwnerID: u.ID, Owner: u, @@ -81,7 +77,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR } if err := adoptRepository(ctx, repoPath, repo, opts.DefaultBranch); err != nil { - return fmt.Errorf("createDelegateHooks: %w", err) + return fmt.Errorf("adoptRepository: %w", err) } if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil { @@ -143,6 +139,21 @@ func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repo } } + // Don't bother looking this repo in the context it won't be there + gitRepo, err := gitrepo.OpenRepository(ctx, repo) + if err != nil { + return fmt.Errorf("openRepository: %w", err) + } + defer gitRepo.Close() + + if _, err = repo_module.SyncRepoBranchesWithRepo(ctx, repo, gitRepo, 0); err != nil { + return fmt.Errorf("SyncRepoBranchesWithRepo: %w", err) + } + + if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { + return fmt.Errorf("SyncReleasesWithTags: %w", err) + } + branches, _ := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{ RepoID: repo.ID, ListOptions: db.ListOptionsAll, @@ -183,26 +194,10 @@ func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repo return fmt.Errorf("setDefaultBranch: %w", err) } } - if err = repo_module.UpdateRepository(ctx, repo, false); err != nil { return fmt.Errorf("updateRepository: %w", err) } - // Don't bother looking this repo in the context it won't be there - gitRepo, err := gitrepo.OpenRepository(ctx, repo) - if err != nil { - return fmt.Errorf("openRepository: %w", err) - } - defer gitRepo.Close() - - if _, err = repo_module.SyncRepoBranchesWithRepo(ctx, repo, gitRepo, 0); err != nil { - return fmt.Errorf("SyncRepoBranches: %w", err) - } - - if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { - return fmt.Errorf("SyncReleasesWithTags: %w", err) - } - return nil } From 38ea77ebbebaedd6f0df5312639e336b61bb655c Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 10 May 2024 16:23:47 +0800 Subject: [PATCH 65/99] Remove deprecated stuff for runners (#30930) It's time (maybe somewhat late) to remove some deprecated stuff for the runner. - `x-runner-version`: runners needn't to report version in every request, they will call `Declare`. - `AgentLabels`: runners will report them as `Labels`. (cherry picked from commit b9396a9b852e4fea0e2c39ef3ef2fdfbc9ea248a) Conflicts: routers/api/actions/runner/interceptor.go trivial conflict because e80466f734 Resolve lint for unused parameter and unnecessary type arguments (#30750) was not cherry-picked --- routers/api/actions/runner/interceptor.go | 13 ------------- routers/api/actions/runner/runner.go | 6 ------ 2 files changed, 19 deletions(-) diff --git a/routers/api/actions/runner/interceptor.go b/routers/api/actions/runner/interceptor.go index 0e99f3deda..521ba910e3 100644 --- a/routers/api/actions/runner/interceptor.go +++ b/routers/api/actions/runner/interceptor.go @@ -23,8 +23,6 @@ import ( const ( uuidHeaderKey = "x-runner-uuid" tokenHeaderKey = "x-runner-token" - // Deprecated: will be removed after Gitea 1.20 released. - versionHeaderKey = "x-runner-version" ) var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unaryFunc connect.UnaryFunc) connect.UnaryFunc { @@ -35,9 +33,6 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar } uuid := request.Header().Get(uuidHeaderKey) token := request.Header().Get(tokenHeaderKey) - // TODO: version will be removed from request header after Gitea 1.20 released. - // And Gitea will not try to read version from request header - version := request.Header().Get(versionHeaderKey) runner, err := actions_model.GetRunnerByUUID(ctx, uuid) if err != nil { @@ -51,14 +46,6 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar } cols := []string{"last_online"} - - // TODO: version will be removed from request header after Gitea 1.20 released. - // And Gitea will not try to read version from request header - version, _ = util.SplitStringAtByteN(version, 64) - if !util.IsEmptyString(version) && runner.Version != version { - runner.Version = version - cols = append(cols, "version") - } runner.LastOnline = timeutil.TimeStampNow() if methodName == "UpdateTask" || methodName == "UpdateLog" { runner.LastActive = timeutil.TimeStampNow() diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index bbffa9acfb..017bdf6324 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -69,12 +69,6 @@ func (s *Service) Register( } labels := req.Msg.Labels - // TODO: agent_labels should be removed from pb after Gitea 1.20 released. - // Old version runner's agent_labels slice is not empty and labels slice is empty. - // And due to compatibility with older versions, it is temporarily marked as Deprecated in pb, so use `//nolint` here. - if len(req.Msg.AgentLabels) > 0 && len(req.Msg.Labels) == 0 { //nolint:staticcheck - labels = req.Msg.AgentLabels //nolint:staticcheck - } // create new runner name, _ := util.SplitStringAtByteN(req.Msg.Name, 255) From 51f6c3a059f61d801707921b864591695f6f97f7 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 10 May 2024 14:25:49 +0200 Subject: [PATCH 66/99] Forbid deprecated `break-word` in CSS (#30934) Forbid [deprecated](https://drafts.csswg.org/css-text-3/#word-break-property) `break-word` and fix all occurences. Regarding `overflow-wrap: break-word` vs `overflow-wrap: anywhere`: Example of difference: https://jsfiddle.net/silverwind/1va6972r/ [Here](https://stackoverflow.com/questions/77651244) it says: > The differences between normal, break-word and anywhere are only clear if you are using width: min-content on the element containing the text, and you also set a max-width. A pretty rare scenario. I don't think this difference will make any practical impact as we are not hitting this rare scenario. (cherry picked from commit 5556782ebeb1ca4d17e2fff434b11651887b9899) --- stylelint.config.js | 2 +- web_src/css/features/console.css | 3 +-- web_src/css/helpers.css | 1 - web_src/css/repo.css | 2 +- web_src/css/shared/flex-list.css | 4 ++-- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/stylelint.config.js b/stylelint.config.js index 523b18841e..22c7feb485 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -150,7 +150,7 @@ export default { 'declaration-property-unit-allowed-list': null, 'declaration-property-unit-disallowed-list': {'line-height': ['em']}, 'declaration-property-value-allowed-list': null, - 'declaration-property-value-disallowed-list': null, + 'declaration-property-value-disallowed-list': {'word-break': ['break-word']}, 'declaration-property-value-no-unknown': true, 'font-family-name-quotes': 'always-where-recommended', 'font-family-no-duplicate-names': true, diff --git a/web_src/css/features/console.css b/web_src/css/features/console.css index 99fb25dae5..e2d3327cfa 100644 --- a/web_src/css/features/console.css +++ b/web_src/css/features/console.css @@ -5,8 +5,7 @@ color: var(--color-console-fg); font-family: var(--fonts-monospace); border-radius: var(--border-radius); - word-break: break-word; - overflow-wrap: break-word; + overflow-wrap: anywhere; } .console img { max-width: 100%; } diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index cf2e73572c..4d12dfaea2 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -5,7 +5,6 @@ Gitea's private styles use `g-` prefix. .gt-word-break { word-wrap: break-word !important; - word-break: break-word; /* compat: Safari */ overflow-wrap: anywhere; } diff --git a/web_src/css/repo.css b/web_src/css/repo.css index a29e9a0986..ec1f964909 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -418,7 +418,7 @@ td .commit-summary { } .repository.file.list .non-diff-file-content .plain-text pre { - word-break: break-word; + overflow-wrap: anywhere; white-space: pre-wrap; } diff --git a/web_src/css/shared/flex-list.css b/web_src/css/shared/flex-list.css index 6217b45300..0f54779252 100644 --- a/web_src/css/shared/flex-list.css +++ b/web_src/css/shared/flex-list.css @@ -59,7 +59,7 @@ color: var(--color-text); font-size: 16px; font-weight: var(--font-weight-semibold); - word-break: break-word; + overflow-wrap: anywhere; min-width: 0; } @@ -74,7 +74,7 @@ flex-wrap: wrap; gap: .25rem; color: var(--color-text-light-2); - word-break: break-word; + overflow-wrap: anywhere; } .flex-item .flex-item-body a { From b8f65234bc23fb31de2b2eb8e5d1352dcb1241f8 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 10 May 2024 20:58:05 +0800 Subject: [PATCH 67/99] Fix some UI regressions for commit list (#30920) Close #30919 --------- Co-authored-by: silverwind (cherry picked from commit 080486e47dba7ed767707fb0a2939677dfbcb0e3) --- templates/repo/commits_list_small.tmpl | 14 +++++++++----- web_src/css/base.css | 1 + web_src/css/repo.css | 6 +----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/templates/repo/commits_list_small.tmpl b/templates/repo/commits_list_small.tmpl index 6ca6dd5cdc..4c67319b8c 100644 --- a/templates/repo/commits_list_small.tmpl +++ b/templates/repo/commits_list_small.tmpl @@ -13,13 +13,12 @@ {{$commitLink:= printf "%s/commit/%s" $.comment.Issue.PullRequest.BaseRepo.Link (PathEscape .ID.String)}} - {{RenderCommitMessageLinkSubject $.root.Context .Message $commitLink ($.comment.Issue.PullRequest.BaseRepo.ComposeMetas ctx)}} + + {{- RenderCommitMessageLinkSubject $.root.Context .Message $commitLink ($.comment.Issue.PullRequest.BaseRepo.ComposeMetas ctx) -}} + {{if IsMultilineCommitMessage .Message}} - - {{end}} - {{if IsMultilineCommitMessage .Message}} -
{{RenderCommitBody $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.ComposeMetas ctx)}}
+ {{end}} @@ -47,5 +46,10 @@
+ {{if IsMultilineCommitMessage .Message}} +
+		{{- RenderCommitBody $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.ComposeMetas ctx) -}}
+	
+ {{end}} {{end}}
diff --git a/web_src/css/base.css b/web_src/css/base.css index 3d91586934..94be1ef610 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -898,6 +898,7 @@ input:-webkit-autofill:active, font-weight: var(--font-weight-normal); margin: 0 6px; padding: 5px 10px; + flex-shrink: 0; } .ui .sha.label .shortsha { diff --git a/web_src/css/repo.css b/web_src/css/repo.css index ec1f964909..e58525af0f 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -2487,14 +2487,10 @@ tbody.commit-list { .commit-body { margin: 0.25em 0; white-space: pre-wrap; + overflow-wrap: anywhere; line-height: initial; } -/* PR-comment */ -.repository .timeline-item .commit-body { - margin-left: 45px; -} - .git-notes.top { text-align: left; } From 32c97efab455f70e4ff2424d971ffb660870cbc8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 May 2024 22:16:09 +0800 Subject: [PATCH 68/99] Remove If Exist check on migration for mssql because that syntax required SQL server 2016 (#30894) Fix #30872 We will assume the database is consistent before executing the migration. So the indexes should exist. Removing `IF EXIST` then is safe enough. --------- Co-authored-by: silverwind (cherry picked from commit 40de54ece82356b161cdb9cc224ed9004af8ae5d) Conflicts: models/migrations/v1_22/v286.go MSSQL is not supported in Forgejo --- .../Test_RepositoryFormat/review_state.yml | 2 ++ models/migrations/v1_22/v286_test.go | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/models/migrations/fixtures/Test_RepositoryFormat/review_state.yml b/models/migrations/fixtures/Test_RepositoryFormat/review_state.yml index 1197b086e3..dd64980916 100644 --- a/models/migrations/fixtures/Test_RepositoryFormat/review_state.yml +++ b/models/migrations/fixtures/Test_RepositoryFormat/review_state.yml @@ -1,3 +1,5 @@ - id: 1 + user_id: 1 + pull_id: 1 commit_sha: 19fe5caf872476db265596eaac1dc35ad1c6422d diff --git a/models/migrations/v1_22/v286_test.go b/models/migrations/v1_22/v286_test.go index 7c353747e3..a19c9396e2 100644 --- a/models/migrations/v1_22/v286_test.go +++ b/models/migrations/v1_22/v286_test.go @@ -19,21 +19,21 @@ func PrepareOldRepository(t *testing.T) (*xorm.Engine, func()) { type CommitStatus struct { ID int64 - ContextHash string + ContextHash string `xorm:"char(40) index"` } type RepoArchiver struct { ID int64 - RepoID int64 - Type int - CommitID string + RepoID int64 `xorm:"index unique(s)"` + Type int `xorm:"unique(s)"` + CommitID string `xorm:"VARCHAR(40) unique(s)"` } type ReviewState struct { ID int64 - CommitSHA string - UserID int64 - PullID int64 + UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"` + PullID int64 `xorm:"NOT NULL INDEX UNIQUE(pull_commit_user) DEFAULT 0"` + CommitSHA string `xorm:"NOT NULL VARCHAR(40) UNIQUE(pull_commit_user)"` } type Comment struct { From 1f56a49f28ad358dbe31a112938caedb9082db53 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 May 2024 22:55:49 +0800 Subject: [PATCH 69/99] Move reverproxyauth before session so the header will not be ignored even if user has login (#27821) When a user logout and then login another user, the reverseproxy auth should be checked before session otherwise the old user is still login. (cherry picked from commit 26ae5922348d2dbaf2161bbd6ac79b2aa455e5f0) --- routers/web/web.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/routers/web/web.go b/routers/web/web.go index 78c88fb938..48f9102749 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -98,14 +98,14 @@ func optionsCorsHandler() func(next http.Handler) http.Handler { // The Session plugin is expected to be executed second, in order to skip authentication // for users that have already signed in. func buildAuthGroup() *auth_service.Group { - group := auth_service.NewGroup( - &auth_service.OAuth2{}, // FIXME: this should be removed and only applied in download and oauth related routers - &auth_service.Basic{}, // FIXME: this should be removed and only applied in download and git/lfs routers - &auth_service.Session{}, - ) + group := auth_service.NewGroup() + group.Add(&auth_service.OAuth2{}) // FIXME: this should be removed and only applied in download and oauth related routers + group.Add(&auth_service.Basic{}) // FIXME: this should be removed and only applied in download and git/lfs routers + if setting.Service.EnableReverseProxyAuth { - group.Add(&auth_service.ReverseProxy{}) + group.Add(&auth_service.ReverseProxy{}) // reverseproxy should before Session, otherwise the header will be ignored if user has login } + group.Add(&auth_service.Session{}) if setting.IsWindows && auth_model.IsSSPIEnabled(db.DefaultContext) { group.Add(&auth_service.SSPI{}) // it MUST be the last, see the comment of SSPI From eb792d9f8a4c6972f5a4cfea6e9cb643b1d6a7ce Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 7 May 2024 15:36:48 +0800 Subject: [PATCH 70/99] Move database operations of merging a pull request to post receive hook and add a transaction (#30805) Merging PR may fail because of various problems. The pull request may have a dirty state because there is no transaction when merging a pull request. ref https://github.com/go-gitea/gitea/pull/25741#issuecomment-2074126393 This PR moves all database update operations to post-receive handler for merging a pull request and having a database transaction. That means if database operations fail, then the git merging will fail, the git client will get a fail result. There are already many tests for pull request merging, so we don't need to add a new one. --------- Co-authored-by: wxiaoguang (cherry picked from commit ebf0c969403d91ed80745ff5bd7dfbdb08174fc7) Conflicts: modules/private/hook.go routers/private/hook_post_receive.go trivial conflicts because 263a716cb5 * Performance optimization for git push (#30104) was not cherry-picked and because of 998a431747a15cc95f7056a2029b736551eb037b Do not update PRs based on events that happened before they existed --- cmd/hook.go | 3 ++ modules/private/hook.go | 2 + modules/repository/env.go | 8 +++ routers/private/hook_post_receive.go | 63 +++++++++++++++++++++++ routers/private/hook_post_receive_test.go | 49 ++++++++++++++++++ services/contexttest/context_tests.go | 13 +++++ services/pull/merge.go | 27 ++++------ services/pull/update.go | 3 +- 8 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 routers/private/hook_post_receive_test.go diff --git a/cmd/hook.go b/cmd/hook.go index ff3059f9df..4f73f8e2bc 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -366,6 +366,7 @@ Forgejo or set your environment appropriately.`, "") isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki)) repoName := os.Getenv(repo_module.EnvRepoName) pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64) + prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64) pusherName := os.Getenv(repo_module.EnvPusherName) hookOptions := private.HookOptions{ @@ -375,6 +376,8 @@ Forgejo or set your environment appropriately.`, "") GitObjectDirectory: os.Getenv(private.GitObjectDirectory), GitQuarantinePath: os.Getenv(private.GitQuarantinePath), GitPushOptions: pushOptions(), + PullRequestID: prID, + PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)), } oldCommitIDs := make([]string, hookBatchSize) newCommitIDs := make([]string, hookBatchSize) diff --git a/modules/private/hook.go b/modules/private/hook.go index cab8c81224..1d0ef4e3a9 100644 --- a/modules/private/hook.go +++ b/modules/private/hook.go @@ -11,6 +11,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" ) @@ -53,6 +54,7 @@ type HookOptions struct { GitQuarantinePath string GitPushOptions GitPushOptions PullRequestID int64 + PushTrigger repository.PushTrigger DeployKeyID int64 // if the pusher is a DeployKey, then UserID is the repo's org user. IsWiki bool ActionPerm int diff --git a/modules/repository/env.go b/modules/repository/env.go index 30edd1c9e3..e4f32092fc 100644 --- a/modules/repository/env.go +++ b/modules/repository/env.go @@ -25,11 +25,19 @@ const ( EnvKeyID = "GITEA_KEY_ID" // public key ID EnvDeployKeyID = "GITEA_DEPLOY_KEY_ID" EnvPRID = "GITEA_PR_ID" + EnvPushTrigger = "GITEA_PUSH_TRIGGER" EnvIsInternal = "GITEA_INTERNAL_PUSH" EnvAppURL = "GITEA_ROOT_URL" EnvActionPerm = "GITEA_ACTION_PERM" ) +type PushTrigger string + +const ( + PushTriggerPRMergeToBase PushTrigger = "pr-merge-to-base" + PushTriggerPRUpdateWithBase PushTrigger = "pr-update-with-base" +) + // InternalPushingEnvironment returns an os environment to switch off hooks on push // It is recommended to avoid using this unless you are pushing within a transaction // or if you absolutely are sure that post-receive and pre-receive will do nothing diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 381e3c6c77..10b300f3df 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -4,20 +4,26 @@ package private import ( + "context" "fmt" "net/http" "strconv" "time" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" + pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" + timeutil "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" gitea_context "code.gitea.io/gitea/services/context" @@ -155,6 +161,14 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { } } + // handle pull request merging, a pull request action should push at least 1 commit + if opts.PushTrigger == repo_module.PushTriggerPRMergeToBase { + handlePullRequestMerging(ctx, opts, ownerName, repoName, updates) + if ctx.Written() { + return + } + } + // Handle Push Options if len(opts.GitPushOptions) > 0 { // load the repository @@ -302,3 +316,52 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { RepoWasEmpty: wasEmpty, }) } + +func loadContextCacheUser(ctx context.Context, id int64) (*user_model.User, error) { + return cache.GetWithContextCache(ctx, "hook_post_receive_user", id, func() (*user_model.User, error) { + return user_model.GetUserByID(ctx, id) + }) +} + +// handlePullRequestMerging handle pull request merging, a pull request action should push at least 1 commit +func handlePullRequestMerging(ctx *gitea_context.PrivateContext, opts *private.HookOptions, ownerName, repoName string, updates []*repo_module.PushUpdateOptions) { + if len(updates) == 0 { + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ + Err: fmt.Sprintf("Pushing a merged PR (pr:%d) no commits pushed ", opts.PullRequestID), + }) + return + } + + pr, err := issues_model.GetPullRequestByID(ctx, opts.PullRequestID) + if err != nil { + log.Error("GetPullRequestByID[%d]: %v", opts.PullRequestID, err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{Err: "GetPullRequestByID failed"}) + return + } + + pusher, err := loadContextCacheUser(ctx, opts.UserID) + if err != nil { + log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{Err: "Load pusher user failed"}) + return + } + + pr.MergedCommitID = updates[len(updates)-1].NewCommitID + pr.MergedUnix = timeutil.TimeStampNow() + pr.Merger = pusher + pr.MergerID = pusher.ID + err = db.WithTx(ctx, func(ctx context.Context) error { + // Removing an auto merge pull and ignore if not exist + if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) { + return fmt.Errorf("DeleteScheduledAutoMerge[%d]: %v", opts.PullRequestID, err) + } + if _, err := pr.SetMerged(ctx); err != nil { + return fmt.Errorf("SetMerged failed: %s/%s Error: %v", ownerName, repoName, err) + } + return nil + }) + if err != nil { + log.Error("Failed to update PR to merged: %v", err) + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{Err: "Failed to update PR to merged"}) + } +} diff --git a/routers/private/hook_post_receive_test.go b/routers/private/hook_post_receive_test.go new file mode 100644 index 0000000000..658557d3cf --- /dev/null +++ b/routers/private/hook_post_receive_test.go @@ -0,0 +1,49 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package private + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" + pull_model "code.gitea.io/gitea/models/pull" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/private" + repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/services/contexttest" + + "github.com/stretchr/testify/assert" +) + +func TestHandlePullRequestMerging(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) + assert.NoError(t, err) + assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + + user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + + err = pull_model.ScheduleAutoMerge(db.DefaultContext, user1, pr.ID, repo_model.MergeStyleSquash, "squash merge a pr") + assert.NoError(t, err) + + autoMerge := unittest.AssertExistsAndLoadBean(t, &pull_model.AutoMerge{PullID: pr.ID}) + + ctx, resp := contexttest.MockPrivateContext(t, "/") + handlePullRequestMerging(ctx, &private.HookOptions{ + PullRequestID: pr.ID, + UserID: 2, + }, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, []*repo_module.PushUpdateOptions{ + {NewCommitID: "01234567"}, + }) + assert.Equal(t, 0, len(resp.Body.String())) + pr, err = issues_model.GetPullRequestByID(db.DefaultContext, pr.ID) + assert.NoError(t, err) + assert.True(t, pr.HasMerged) + assert.EqualValues(t, "01234567", pr.MergedCommitID) + + unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{ID: autoMerge.ID}) +} diff --git a/services/contexttest/context_tests.go b/services/contexttest/context_tests.go index 7bfab2ed16..073af213a2 100644 --- a/services/contexttest/context_tests.go +++ b/services/contexttest/context_tests.go @@ -86,6 +86,19 @@ func MockAPIContext(t *testing.T, reqPath string) (*context.APIContext, *httptes return ctx, resp } +func MockPrivateContext(t *testing.T, reqPath string) (*context.PrivateContext, *httptest.ResponseRecorder) { + resp := httptest.NewRecorder() + req := mockRequest(t, reqPath) + base, baseCleanUp := context.NewBaseContext(resp, req) + base.Data = middleware.GetContextData(req.Context()) + base.Locale = &translation.MockLocale{} + ctx := &context.PrivateContext{Base: base} + _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later + chiCtx := chi.NewRouteContext() + ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx) + return ctx, resp +} + // LoadRepo load a repo into a test context. func LoadRepo(t *testing.T, ctx gocontext.Context, repoID int64) { var doer *user_model.User diff --git a/services/pull/merge.go b/services/pull/merge.go index 1d6431ab66..525146833e 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -18,7 +18,6 @@ import ( git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" access_model "code.gitea.io/gitea/models/perm/access" - pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -168,12 +167,6 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U pullWorkingPool.CheckIn(fmt.Sprint(pr.ID)) defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID)) - // Removing an auto merge pull and ignore if not exist - // FIXME: is this the correct point to do this? Shouldn't this be after IsMergeStyleAllowed? - if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) { - return err - } - prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests) if err != nil { log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err) @@ -190,17 +183,15 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U AddTestPullRequestTask(ctx, doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "", 0) }() - pr.MergedCommitID, err = doMergeAndPush(ctx, pr, doer, mergeStyle, expectedHeadCommitID, message) + _, err = doMergeAndPush(ctx, pr, doer, mergeStyle, expectedHeadCommitID, message, repo_module.PushTriggerPRMergeToBase) if err != nil { return err } - pr.MergedUnix = timeutil.TimeStampNow() - pr.Merger = doer - pr.MergerID = doer.ID - - if _, err := pr.SetMerged(ctx); err != nil { - log.Error("SetMerged %-v: %v", pr, err) + // reload pull request because it has been updated by post receive hook + pr, err = issues_model.GetPullRequestByID(ctx, pr.ID) + if err != nil { + return err } if err := pr.LoadIssue(ctx); err != nil { @@ -251,7 +242,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U } // doMergeAndPush performs the merge operation without changing any pull information in database and pushes it up to the base repository -func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) (string, error) { +func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, pushTrigger repo_module.PushTrigger) (string, error) { // Clone base repo. mergeCtx, cancel, err := createTemporaryRepoForMerge(ctx, pr, doer, expectedHeadCommitID) if err != nil { @@ -324,11 +315,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use pr.BaseRepo.Name, pr.ID, ) + + mergeCtx.env = append(mergeCtx.env, repo_module.EnvPushTrigger+"="+string(pushTrigger)) pushCmd := git.NewCommand(ctx, "push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch) // Push back to upstream. - // TODO: this cause an api call to "/api/internal/hook/post-receive/...", - // that prevents us from doint the whole merge in one db transaction + // This cause an api call to "/api/internal/hook/post-receive/...", + // If it's merge, all db transaction and operations should be there but not here to prevent deadlock. if err := pushCmd.Run(mergeCtx.RunOpts()); err != nil { if strings.Contains(mergeCtx.errbuf.String(), "non-fast-forward") { return "", &git.ErrPushOutOfDate{ diff --git a/services/pull/update.go b/services/pull/update.go index 1bba396880..dbc1b711e2 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -15,6 +15,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/repository" ) // Update updates pull request with base branch. @@ -72,7 +73,7 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model. BaseBranch: pr.HeadBranch, } - _, err = doMergeAndPush(ctx, reversePR, doer, repo_model.MergeStyleMerge, "", message) + _, err = doMergeAndPush(ctx, reversePR, doer, repo_model.MergeStyleMerge, "", message, repository.PushTriggerPRUpdateWithBase) defer func() { AddTestPullRequestTask(ctx, doer, reversePR.HeadRepo.ID, reversePR.HeadBranch, false, "", "", 0) From 4157f8f2ec988bd3944a92ef6ee10f7625ff88e4 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sun, 12 May 2024 12:05:22 +0200 Subject: [PATCH 71/99] chore(deadcode): update --- .deadcode-out | 3 --- 1 file changed, 3 deletions(-) diff --git a/.deadcode-out b/.deadcode-out index f22a9df101..0f1b12c257 100644 --- a/.deadcode-out +++ b/.deadcode-out @@ -186,7 +186,6 @@ package "code.gitea.io/gitea/modules/git" func (ErrExecTimeout).Error func (ErrUnsupportedVersion).Error func SetUpdateHook - func GetObjectFormatOfRepo func openRepositoryWithDefaultContext func IsTagExist func ToEntryMode @@ -325,8 +324,6 @@ package "code.gitea.io/gitea/routers/web" package "code.gitea.io/gitea/routers/web/org" func MustEnableProjects - func getActionIssues - func UpdateIssueProject package "code.gitea.io/gitea/services/context" func GetPrivateContext From 81e3156f8b27d47a7b2895bc4751b4a478d2086c Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sun, 12 May 2024 20:20:18 +0200 Subject: [PATCH 72/99] chore(release-notes): [gitea] week 2024-20 cherry pick --- release-notes/8.0.0/feat/3729.md | 1 + release-notes/8.0.0/fix/3729.md | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 release-notes/8.0.0/feat/3729.md create mode 100644 release-notes/8.0.0/fix/3729.md diff --git a/release-notes/8.0.0/feat/3729.md b/release-notes/8.0.0/feat/3729.md new file mode 100644 index 0000000000..bc76e24bd5 --- /dev/null +++ b/release-notes/8.0.0/feat/3729.md @@ -0,0 +1 @@ +- [PR](https://github.com/go-gitea/gitea/pull/30874): add actions-artifacts to the [storage migrate CLI](https://forgejo.org/docs/v8.0/admin/command-line/#migrate). diff --git a/release-notes/8.0.0/fix/3729.md b/release-notes/8.0.0/fix/3729.md new file mode 100644 index 0000000000..27d83e0e55 --- /dev/null +++ b/release-notes/8.0.0/fix/3729.md @@ -0,0 +1,2 @@ +- [PR](https://github.com/go-gitea/gitea/pull/30912): when adopting a repository, the default branch is not taken into account +- [PR](https://github.com/go-gitea/gitea/pull/30715): pull request search shows closed pull requests in the open tab From 418cd41f14fd3df12109eb08dffbfe5061026536 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 May 2024 00:06:54 +0000 Subject: [PATCH 73/99] Update module github.com/golangci/golangci-lint/cmd/golangci-lint to v1.58.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4e4bb78207..ce670c877b 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ XGO_VERSION := go-1.21.x AIR_PACKAGE ?= github.com/cosmtrek/air@v1 # renovate: datasource=go EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v2/cmd/editorconfig-checker@2.8.0 # renovate: datasource=go GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 # renovate: datasource=go -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2 # renovate: datasource=go +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.58.1 # renovate: datasource=go GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 # renovate: datasource=go SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.6-0.20240201115257-bcc7c78b7786 # renovate: datasource=go From 4fadf7c75b81f9b1b4189f0b2f7fbd0ec4359f60 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 May 2024 02:04:30 +0000 Subject: [PATCH 74/99] Update module github.com/golangci/misspell/cmd/misspell to v0.5.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4e4bb78207..7dc6e95ec9 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-che GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 # renovate: datasource=go GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2 # renovate: datasource=go GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go -MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 # renovate: datasource=go +MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1 # renovate: datasource=go SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.6-0.20240201115257-bcc7c78b7786 # renovate: datasource=go XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go From 010cccd33ee4bcbe8f13ec8bc35773d38dbce5d6 Mon Sep 17 00:00:00 2001 From: Codeberg Translate Date: Mon, 13 May 2024 11:48:36 +0000 Subject: [PATCH 75/99] [I18N] Translations update from Weblate (#3637) Translations update from [Weblate](https://translate.codeberg.org) for [Forgejo/forgejo](https://translate.codeberg.org/projects/forgejo/forgejo/). Co-authored-by: Kaede Fujisaki Co-authored-by: emansije Co-authored-by: Kita Ikuyo Co-authored-by: kdh8219 Co-authored-by: enricpineda Co-authored-by: 0ko <0ko@users.noreply.translate.codeberg.org> Co-authored-by: Fjuro Co-authored-by: nmmr Co-authored-by: VioletLul Co-authored-by: leana8959 Co-authored-by: Dirk Co-authored-by: Nifou Co-authored-by: hankskyjames777 Co-authored-by: yeziruo Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3637 Reviewed-by: 0ko <0ko@noreply.codeberg.org> Co-authored-by: Codeberg Translate Co-committed-by: Codeberg Translate --- options/locale/locale_ca.ini | 31 +++++++++++++++++++++++++++++++ options/locale/locale_cs-CZ.ini | 18 ++++++++++-------- options/locale/locale_de-DE.ini | 14 ++++++++------ options/locale/locale_fil.ini | 33 +++++++++++++++++++++++++++++---- options/locale/locale_fr-FR.ini | 2 +- options/locale/locale_ja-JP.ini | 11 +++++++++-- options/locale/locale_ko-KR.ini | 23 +++++++++++++++++++++-- options/locale/locale_pt-PT.ini | 3 +++ options/locale/locale_ru-RU.ini | 16 +++++++++------- options/locale/locale_zh-CN.ini | 1 + options/locale/locale_zh-TW.ini | 17 +++++++++++++---- 11 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 options/locale/locale_ca.ini diff --git a/options/locale/locale_ca.ini b/options/locale/locale_ca.ini new file mode 100644 index 0000000000..a4201400be --- /dev/null +++ b/options/locale/locale_ca.ini @@ -0,0 +1,31 @@ + + + +[common] +home = inici +dashboard = Panell de control +explore = Explorar +help = Ajuda +logo = Logo +sign_in = Entrar +sign_in_with_provider = Entra amb %s +sign_in_or = o +sign_out = Sortir +register = Registrar-se +version = Versió +powered_by = Creat amb %s +page = Pàgina +template = Plantilla +language = Idioma +notifications = Notificacions +active_stopwatch = Registre de Temps Actiu +create_new = Crear… +user_profile_and_more = Perfil i configuració… +signed_in_as = Entrat com +enable_javascript = Aquest lloc web requereix Javascript. +toc = Taula de Continguts +licenses = Llicències +sign_up = Registrar-se +link_account = Vincular un compte +tracked_time_summary = Resum del temps registrat basat en filtres del llistat de temes +return_to_gitea = Tornar a Forgejo \ No newline at end of file diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index ca7b3e513f..9e278f3fd0 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -146,15 +146,15 @@ sign_in_with_provider = Přihlásit se přes %s confirm_delete_artifact = Opravdu chcete odstranit artefakt „%s“? toggle_menu = Přepnout nabídku filter = Filtr -filter.is_fork = Forknuto -filter.not_fork = Není forknuto -filter.is_mirror = Zrcadleno -filter.is_template = Šablona -filter.not_template = Není šablona +filter.is_fork = Forky +filter.not_fork = Nejsou forky +filter.is_mirror = Zrcadla +filter.is_template = Šablony +filter.not_template = Nejsou šablony filter.public = Veřejné filter.private = Soukromé filter.is_archived = Archivováno -filter.not_mirror = Není zrcadleno +filter.not_mirror = Nejsou zrcadla filter.not_archived = Není archivováno filter.clear = Vymazat filtry more_items = Další položky @@ -996,7 +996,7 @@ access_token_desc = Oprávnění vybraného tokenu omezují autorizaci pouze na blocked_users_none = Nemáte žádné zablokované uživatele. blocked_since = Zablokován od %s hints = Nápovědy -additional_repo_units_hint = Podíbnout k povolení dalších jednotek úložiště +additional_repo_units_hint = Navrhnout povolení dalších jednotek úložiště update_hints = Aktualizovat nápovědy update_hints_success = Nápovědy byly aktualizovány. additional_repo_units_hint_description = Zobrazit tlačítko „Přidat další jednotky...“ u repozitářů, které nemají povolené všechny dostupné jednotky. @@ -2721,7 +2721,7 @@ pulls.title_desc_one = žádá o sloučení %[1]d commitu z %[2]s d pulls.merged_title_desc_one = sloučil %[1]d commit z %[2]s do %[3]s %[4]s open_with_editor = Otevřít pomocí %s commits.search_branch = Tato větev -editor.commit_id_not_matching = ID commitu se neshoduje s ID commitu, který jste upravovali. Proveďte commit do nové větve a poté je slučte. +editor.commit_id_not_matching = Tento soubor se během úpravy změnil. Proveďte commit do nové větve a poté je slučte. pulls.ready_for_review = Připraveni na posouzení? settings.rename_branch_failed_protected = Nepodařilo se přejmenovat větev %s, jelikož se jedná o chráněnou větev. editor.push_out_of_date = Push je nejspíše zastaralý. @@ -2888,6 +2888,7 @@ teams.invite.title=Byli jste pozváni do týmu %s v organizaci teams.invite.by=Pozvání od %s teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže. follow_blocked_user = Tuto organizaci nemůžete sledovat, protože jste v ní zablokovaní. +open_dashboard = Otevřít nástěnku [admin] dashboard=Přehled @@ -3683,6 +3684,7 @@ owner.settings.chef.keypair.description=Pro autentizaci do registru Chef je zapo rpm.repository.multiple_groups = Tento balíček je dostupný v několika skupinách. owner.settings.cargo.rebuild.description = Opětovné sestavení může být užitečné, pokud není index synchronizován s uloženými balíčky Cargo. owner.settings.cargo.rebuild.no_index = Opětovné vytvoření selhalo, nebyl inicializován žádný index. +npm.dependencies.bundle = Přidružené závislosti [secrets] secrets=Tajné klíče diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 67f088a33e..a1a55c4dfa 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -149,10 +149,10 @@ filter.is_archived = Archiviert filter.not_archived = Nicht archiviert filter.is_fork = Geforkt filter.not_fork = Nicht geforkt -filter.is_mirror = Gemirrort -filter.not_mirror = Nicht gemirrort -filter.is_template = Vorlage -filter.not_template = Keine Vorlage +filter.is_mirror = Gespiegelt +filter.not_mirror = Nicht gespiegelt +filter.is_template = Vorlagen +filter.not_template = Keine Vorlagen filter.public = Öffentlich filter.private = Privat more_items = Mehr Einträge @@ -993,7 +993,7 @@ blocked_users = Blockierte Benutzer blocked_since = Blockiert seit %s change_password = Passwort ändern hints = Hinweise -additional_repo_units_hint = Zur Aktivierung zusätzlicher Repository-Einheiten ermutigen +additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen update_hints = Hinweise aktualisieren update_hints_success = Hinweise wurden aktualisiert. additional_repo_units_hint_description = Einen „Mehr Einheiten hinzufügen …“-Button für Repositorys, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen. @@ -2707,7 +2707,7 @@ open_with_editor = Öffnen mit %s commits.search_branch = Dieser Branch pulls.ready_for_review = Bereit zum Review? settings.rename_branch_failed_protected = Branch %s kann nicht umbenannt werden, weil er ein geschützter Branch ist. -editor.commit_id_not_matching = Die Commit-ID passt nicht zur ID die du bearbeitet hast hast. Committe in einen neuen Branch, dann führe einen Merge durch. +editor.commit_id_not_matching = Die Datei wurde geändert, während du sie bearbeitet hast. Committe in einen neuen Branch, dann führe einen Merge durch. editor.push_out_of_date = Der Push scheint veraltet zu sein. n_commit_few = %s Commits n_branch_one = %s Branch @@ -2865,6 +2865,7 @@ teams.invite.title=Du wurdest eingeladen, dem Team %s in der Or teams.invite.by=Von %s eingeladen teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten. follow_blocked_user = Du kannst dieser Organisation nicht folgen, weil diese Organisation dich blockiert hat. +open_dashboard = Übersicht öffnen [admin] dashboard=Übersicht @@ -3652,6 +3653,7 @@ rpm.repository = Repository-Info rpm.repository.multiple_groups = Dieses Paket ist in mehreren Gruppen verfügbar. rpm.repository.architectures = Architekturen owner.settings.cargo.rebuild.no_index = Kann nicht erneut erzeugen, es wurde kein Index initialisiert. +npm.dependencies.bundle = Gebündelte Abhängigkeiten [secrets] secrets=Secrets diff --git a/options/locale/locale_fil.ini b/options/locale/locale_fil.ini index c3136d50d7..1ebd88666c 100644 --- a/options/locale/locale_fil.ini +++ b/options/locale/locale_fil.ini @@ -7,7 +7,7 @@ language = Wika mirrors = Mga Mirror forks = Mga Fork activities = Mga Aktibidad -pull_requests = Mga hiling sa paghatak +pull_requests = Mga hiling sa paghila issues = Mga Isyu milestones = Mga Milestone ok = OK @@ -604,7 +604,7 @@ Location = Lokasyon joined_on = Sumali noong %s repositories = Mga Repositoryo activity = Pampublikong aktibidad -followers_few = %d Mga tagasunod +followers_few = %d mga tagasunod block_user = I-block ang user change_avatar = Palitan ang iyong avatar… block_user.detail = Pakiunawa na kung i-block mo ang user na ito, isasagawa ang iba pang mga aksyon. Gaya ng: @@ -617,7 +617,7 @@ watched = Mga sinusubaybayan na repositoryo code = Code projects = Mga Proyekto overview = Pangkalahatang Ideya -following_few = %d Sinusundan +following_few = %d sinusundan follow = Sundan unfollow = I-unfollow block = Harangan @@ -1076,7 +1076,7 @@ migrate_items_pullrequests = Mga hiling sa pagtulak archive.pull.nocomment = Naka-archive ang repo na ito. Hindi ka makakakomento sa mga pull request. archive.title = Naka-archive ang repo na ito. Maari mong itignan ang mga file at i-clone ito, pero hindi makaka-push o magbukas ng mga isyu o mga pull request. archive.title_date = Naka-archive ang repositoryo na ito noong %s. Maari mong itignan ang mga file at i-clone ito, pero hindi makaka-push o magbukas ng mga isyu o mga pull request. -pulls = Mga hiling sa paghatak +pulls = Mga hiling sa paghila activity.merged_prs_count_n = Mga naisamang hiling sa paghatak wiki.last_updated = Huling binago %s file.title = %s sa %s @@ -1448,6 +1448,31 @@ issues.review.pending = Nakabinbin pulls.status_checking = Nakabinbin ang ilang mga [pagsusuri] editor.file_changed_while_editing = Ang nilalaman ng file ay nagbago mula noong nagsimula kang mag-edit. Mag-click dito upang makita ang mga pagbabago o Mag-commit ng mga pagbabago muli para i-overwrite sila. editor.file_already_exists = Umiiral na ang file na may pangalang "%s" sa repositoryong ito. +issues.review.review = Suriin +activity.git_stats_push_to_branch = sa %s at +activity.git_stats_and_deletions = at +issues.new.no_projects = Walang mga proyekto +pulls.auto_merge_button_when_succeed = (Kung nagtagumpay ang mga [check]) +activity.git_stats_on_default_branch = Sa %s, +activity.period.quarterly = 3 buwan +issues.review.left_comment = iniwan ang [comment] +pulls.compare_base = isama sa +activity.git_stats_additions = at mayroong +issues.reopen_comment_issue = [Comment] at buksang muli +issues.close_comment_issue = [Comment] at isara +pulls.compare_compare = hilain mula sa +pulls.waiting_count_n = %d mga hinihintay na pagsusuri +pulls.waiting_count_1 = %d hinihintay na pagsusuri +contributors.contribution_type.deletions = Mga pagbura +pulls.ready_for_review = Handa ba para sa pagsuri? +activity.period.daily = 1 araw +activity.period.halfweekly = 3 araw +activity.period.weekly = 1 linggo +activity.period.monthly = 1 buwan +activity.period.semiyearly = 6 na buwan +activity.period.yearly = 1 taon +issues.new.title_empty = Hindi maaaring walang laman ang pamagat +issues.new.projects = Mga proyeko [search] commit_kind = Maghanap ng mga commit... diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index e1ccaa3cc3..1c99f86cb1 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -146,7 +146,7 @@ confirm_delete_artifact = Êtes-vous certain de vouloir supprimer l'artefect "%s filter.clear = Effacer le filtre filter.is_archived = Archivé filter.not_archived = Non archivé -filter.is_fork = Dupliqué +filter.is_fork = Bifurcations filter.not_fork = Non dupliqué filter.not_mirror = Non répliqué filter.is_template = Modèle diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 3219749d30..8d06177d2f 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -171,7 +171,8 @@ contributions_zero=貢献なし less=少 more=多 contributions_one = 貢献 -contributions_few = 貢献 +contributions_few = 貢献たち +contributions_format = {month} {day}, {year} に {contributions} 件の貢献 [editor] buttons.heading.tooltip=見出し追加 @@ -2723,6 +2724,12 @@ settings.sourcehut_builds.manifest_path = Build manifestのパス settings.sourcehut_builds.secrets_helper = ジョブにビルドシークレットへのアクセス権を付与します (SECRETS:RO 権限が必要です) release.hide_archive_links_helper = このリリース用に自動的に生成されたソース コード アーカイブを非表示にします。たとえば、独自のソース コードをアップロードする場合などです。 error.broken_git_hook = このリポジトリの Git フックが壊れているようです。ドキュメントに従って修正し、コミットをいくつかプッシュしてステータスを更新してください。 +editor.commit_id_not_matching = このコミットIDはあなたが編集していたものと一致しません。新しいブランチへコミットし、そしてマージしてください。 +issues.num_participants_one = %d 人の参加者 +commits.search_branch = このブランチ +size_format = %[1]s: %[2]s, %[3]s: %[4]s +editor.push_out_of_date = このpushはもう古いようです。 +issues.archived_label_description = (アーカイブ済) %s [graphs] component_loading = %s の読み込み中... @@ -2730,7 +2737,7 @@ component_loading_failed = %s を読み込めませんでした component_loading_info = 少し時間がかかるかもしれません… component_failed_to_load = 予期しないエラーが発生しました。 code_frequency.what = コード頻度 -contributors.what = 貢献者 +contributors.what = 貢献たち recent_commits.what = 最近のコミット [org] diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index b70bc49cc9..07a82eff17 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -155,8 +155,17 @@ confirm_delete_artifact = 정말 artifact "%s"를 삭제하실건가요? artifacts = Artifacts [aria] +navbar = 네비게이션 바 +footer.links = 링크 [heatmap] +number_of_contributions_in_the_last_12_months = 지난 12달간 %s 명의 기여자 +contributions_zero = 기여자 없음 +contributions_format = {year}년 {month}월 {day}일에 {contributions}개의 기여 +contributions_one = 기여 +contributions_few = 기여 +less = 적은 +more = 많은 [editor] @@ -817,7 +826,7 @@ issues.action_milestone=마일스톤 issues.action_milestone_no_select=마일스톤 없음 issues.action_assignee=담당자 issues.action_assignee_no_select=담당자 없음 -issues.opened_by= %[3]s가 %[1]s에 오픈 +issues.opened_by= %[3]s님이 %[1]s에 오픈 issues.previous=이전 issues.next=다음 issues.open_title=오픈 @@ -1252,6 +1261,12 @@ projects = 프로젝트 projects.desc = 이슈와 풀 리퀘스트를 프로젝트에서 관리합니다. projects.create = 프로젝트 만들기 project_board = 프로젝트 +projects.create_success = "%s" 프로젝트가 생성되었습니다. +projects.deletion = 프로젝트 삭제 +projects.deletion_desc = 프로젝트를 삭제하면 관련된 모든 이슈에서 해당 프로젝트가 제거됩니다. 계속하시겠습니까? +projects.deletion_success = 프로젝트가 삭제되었습니다. +projects.edit = 프로젝트 수정 +projects.new_subheader = 한 곳에서 당신의 작업을 조정, 추적, 업데이트해 프로젝트를 일정대로 투명하게 유지하세요. @@ -1704,4 +1719,8 @@ runs.commit=커밋 [search] -code_search_by_git_grep = 현재 코드 검색 결과는 "git grep"에 의해 제공됩니다.관리자가 코드 인덱서를 활성화하면 더 나은 결과가 제공될 수 있습니다. \ No newline at end of file +code_search_by_git_grep = 현재 코드 검색 결과는 "git grep"에 의해 제공됩니다.관리자가 코드 인덱서를 활성화하면 더 나은 결과가 제공될 수 있습니다. +branch_kind = 브랜치 검색... +keyword_search_unavailable = 지금은 키워드로 검색이 지원되지 않습니다. 사이트 관리자에게 문의하십시오. +commit_kind = 커밋 검색... +no_results = 일치하는 결과를 찾을 수 없습니다. \ No newline at end of file diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index c7fc74b234..de68e23c86 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -2869,6 +2869,7 @@ teams.invite.title=Foi-lhe feito um convite para se juntar à equipa %s< teams.invite.by=Convidado(a) por %s teams.invite.description=Clique no botão abaixo para se juntar à equipa. follow_blocked_user = Não pode seguir esta organização porque esta organização bloqueou-o/a. +open_dashboard = Abrir painel de controlo [admin] dashboard=Painel de controlo @@ -3411,6 +3412,7 @@ config_settings = Configurações auths.tip.gitlab_new = Registe uma nova aplicação em https://gitlab.com/-/profile/applications config.open_with_editor_app_help = Os editores da opção "Abrir com" do menu da clonagem. Se for deixado em branco, será usado o valor predefinido. Expanda para ver o que está predefinido. config.allow_dots_in_usernames = Permitir que os utilizadores usem pontos no seu nome de utilizador. Não altera as contas existentes. +auths.default_domain_name = Nome de domínio predefinido usado para o endereço de email [action] create_repo=criou o repositório %s @@ -3653,6 +3655,7 @@ owner.settings.chef.title=Registo do Chef owner.settings.chef.keypair=Gerar par de chaves owner.settings.chef.keypair.description=É necessário um par de chaves para autenticar no registro Chef. Se você gerou um par de chaves antes, gerar um novo par de chaves irá descartar o par de chaves antigo. owner.settings.cargo.rebuild.no_index = Não foi possível reconstruir, não há um índice inicializado. +npm.dependencies.bundle = Dependências agrupadas [secrets] secrets=Segredos diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 8151291aa2..f4ee7a1da0 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -2865,6 +2865,7 @@ teams.invite.by=Приглашен(а) %s teams.invite.description=Нажмите на кнопку ниже, чтобы присоединиться к команде. follow_blocked_user = Вы не можете подписаться на эту организацию, т.к. вы в ней заблокированы. teams.general_access = Настраиваемый доступ +open_dashboard = Открыть панель [admin] dashboard=Панель управления @@ -2875,7 +2876,7 @@ repositories=Репозитории hooks=Веб-хуки integrations=Интеграции authentication=Аутентификация -emails=Адреса эл. почты пользователей +emails=Адреса эл. почты config=Конфигурация notices=Системные оповещения monitor=Мониторинг @@ -3044,7 +3045,7 @@ repos.unadopted=Непринятые репозитории repos.unadopted.no_more=Больше непринятых репозиториев не найдено repos.owner=Владелец repos.name=Название -repos.private=Личный +repos.private=Частный repos.watches=Следят repos.stars=Звезды repos.forks=Ответвления @@ -3082,19 +3083,19 @@ auths.enabled=Включено auths.syncenabled=Включить синхронизацию пользователей auths.updated=Обновлено auths.auth_type=Тип аутентификации -auths.auth_name=Имя аутентификации +auths.auth_name=Название аутентификации auths.security_protocol=Протокол безопасности auths.domain=Домен auths.host=Сервер auths.port=Порт auths.bind_dn=Bind DN auths.bind_password=Привязать пароль -auths.user_base=База для поиска пользователя +auths.user_base=База поиска пользователей auths.user_dn=DN пользователя -auths.attribute_username=Атрибут Username +auths.attribute_username=Атрибут username auths.attribute_username_placeholder=Оставьте пустым, чтобы использовать имя пользователя для регистрации. -auths.attribute_name=Атрибут First Name -auths.attribute_surname=Атрибут Surname +auths.attribute_name=Атрибут first name +auths.attribute_surname=Атрибут surname auths.attribute_mail=Атрибут эл. почты auths.attribute_ssh_public_key=Атрибут открытого ключа SSH auths.attribute_avatar=Атрибут аватара @@ -3661,6 +3662,7 @@ rpm.repository.architectures = Архитектуры rpm.repository.multiple_groups = Этот пакет доступен в нескольких группах. owner.settings.chef.keypair.description = Для аутентификации реестра Chef необходима пара ключей. Если до этого вы уже сгенерировали пару ключей, генерация новой приведёт к прекращению действия предыдущей. owner.settings.cargo.rebuild.no_index = Невозможно выполнить пересборку. Нет инициализированного индекса. +npm.dependencies.bundle = Комплектные зависимости [secrets] secrets=Секреты diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 0b495b6c67..8bdc11b7b2 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2883,6 +2883,7 @@ teams.invite.title=您已被邀请加入组织 %s 中的团队 teams.invite.by=邀请人 %s teams.invite.description=请点击下面的按钮加入团队。 follow_blocked_user = 你无法关注此组织,因为此组织已屏蔽你。 +open_dashboard = 打开仪表盘 [admin] dashboard=管理面板 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index b0f9071f22..44855f480f 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -139,11 +139,11 @@ filter = 篩選 filter.clear = 清除篩選條件 filter.is_archived = 已歸檔 filter.not_archived = 未封存 -filter.is_fork = 已派生 -filter.not_fork = 不是分岔 -filter.is_mirror = 已鏡像 +filter.is_fork = 已分叉 +filter.not_fork = 不是分叉 +filter.is_mirror = 鏡像 filter.not_mirror = 不是鏡像 -filter.is_template = 模板 +filter.is_template = 範本 filter.not_template = 不是範本 filter.public = 公開 filter.private = 私有 @@ -379,6 +379,7 @@ stars_few = %d 個星星 stars_one = %d 個星星 forks_one = %d 個 fork forks_few = %d 個 fork +go_to = 前往 [auth] create_new_account=註冊帳戶 @@ -671,6 +672,7 @@ block_user.detail_3 = 該使用者無法將您加為協作者,您也無法將 follow_blocked_user = 因為這個使用者封鎖您或被您封鎖,您不能追蹤此使用者。 block = 封鎖 unblock = 解除封鎖 +block_user.detail = 請注意,封鎖此使用者將會導致以下結果。例如: [settings] profile=個人資料 @@ -974,6 +976,13 @@ keep_email_private_popup = 這將在您的個人資料頁面、合併請求或 ssh_signonly = 因為目前 SSH 已被停用,這個金鑰只被用來校驗提交簽署。 email_desc = 您的主要電子信箱將被用於通知、密碼復原、網頁 Git 操作(如果您的信箱不是隱藏的)。 pronouns_custom = 自訂 +oauth2_client_secret_hint = 這把密鑰在您離開或重新整理此頁面後將不再被顯示。請確保您已儲存它。 +additional_repo_units_hint_description = 在沒有啟用所有模組的儲存庫中顯示「新增更多模組…」按鈕。 +hidden_comment_types.issue_ref_tooltip = 使用者更改與問題相關分支/標籤的留言 +pronouns = 代名詞 +update_oauth2_application_success = 您已成功更新該 OAuth2 應用程式。 +oauth2_redirect_uris = 轉址 URI。每個 URI 應各佔一行。 +pronouns_unspecified = 未指定 [repo] owner=擁有者 From 182d5eeef9a88104269f275f0eaa4e8a15ffeb87 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Mon, 13 May 2024 12:05:49 +0000 Subject: [PATCH 76/99] [I18N] Improve base locale related to settings and accounts (#3733) - general English improvements - separated the header of Language part in user settings into a new string for better translatability - made that header contain "Default", just like the theme one, because this is how this actually works: the bottom selector saves the language temporarily, the selector in the settings saves it permanently. Not many users know about this difference. This clarification will help some - removed some of "Manage" from the headers where they aren't really needed. This improves the consistency with some other headers Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3733 Reviewed-by: Earl Warren --- options/locale/locale_en-US.ini | 27 +++++++++++++------------ templates/user/settings/appearance.tmpl | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 55af096e48..b95c72d289 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -439,8 +439,8 @@ tab_openid = OpenID oauth_signup_tab = Register New Account oauth_signup_title = Complete New Account oauth_signup_submit = Complete Account -oauth_signin_tab = Link to Existing Account -oauth_signin_title = Sign In to Authorize Linked Account +oauth_signin_tab = Link to an existing account +oauth_signin_title = Sign in to authorize linked account oauth_signin_submit = Link Account oauth.signin.error = There was an error processing the authorization request. If this error persists, please contact the site administrator. oauth.signin.error.access_denied = The authorization request was denied. @@ -691,13 +691,13 @@ password = Password security = Security avatar = Avatar ssh_gpg_keys = SSH / GPG keys -social = Social Accounts +social = Social accounts applications = Applications -orgs = Manage organizations +orgs = Organizations repos = Repositories delete = Delete Account twofa = Two-factor authentication (TOTP) -account_link = Linked Accounts +account_link = Linked accounts organization = Organizations uid = UID webauthn = Two-factor authentication (Security keys) @@ -726,6 +726,7 @@ change_username_redirect_prompt = The old username will redirect until someone c continue = Continue cancel = Cancel language = Language +language.title = Default language ui = Theme hints = Hints additional_repo_units_hint = Suggest to enable additional repository units @@ -776,8 +777,8 @@ change_password_success = Your password has been updated. Sign in using your new password_change_disabled = Non-local users cannot update their password through the Forgejo web interface. manage_emails = Manage email addresses -manage_themes = Select default theme -manage_openid = Manage OpenID addresses +manage_themes = Default theme +manage_openid = OpenID addresses email_desc = Your primary email address will be used for notifications, password recovery and, provided that it is not hidden, web-based Git operations. theme_desc = This will be your default theme across the site. primary = Primary @@ -797,7 +798,7 @@ openid_deletion = Remove OpenID Address openid_deletion_desc = Removing this OpenID address from your account will prevent you from signing in with it. Continue? openid_deletion_success = The OpenID address has been removed. add_new_email = Add email address -add_new_openid = Add New OpenID URI +add_new_openid = Add new OpenID URI add_email = Add email address add_openid = Add OpenID URI add_email_confirmation_sent = A confirmation email has been sent to "%s". Please check your inbox within the next %s to confirm your email address. @@ -888,7 +889,7 @@ social_desc = These social accounts can be used to sign in to your account. Make unbind = Unlink unbind_success = The social account has been removed successfully. -manage_access_token = Manage access tokens +manage_access_token = Access tokens generate_new_token = Generate new token tokens_desc = These tokens grant access to your account using the Forgejo API. token_name = Token name @@ -970,11 +971,11 @@ webauthn_delete_key_desc = If you remove a security key you can no longer sign i webauthn_key_loss_warning = If you lose your security keys, you will lose access to your account. webauthn_alternative_tip = You may want to configure an additional authentication method. -manage_account_links = Manage Linked Accounts +manage_account_links = Linked accounts manage_account_links_desc = These external accounts are linked to your Forgejo account. account_links_not_available = There are currently no external accounts linked to your Forgejo account. -link_account = Link Account -remove_account_link = Remove Linked Account +link_account = Link account +remove_account_link = Remove linked account remove_account_link_desc = Removing a linked account will revoke its access to your Forgejo account. Continue? remove_account_link_success = The linked account has been removed. @@ -3618,7 +3619,7 @@ owner.settings.cargo.rebuild.description = Rebuilding can be useful if the index owner.settings.cargo.rebuild.error = Failed to rebuild Cargo index: %v owner.settings.cargo.rebuild.success = The Cargo index was successfully rebuild. owner.settings.cargo.rebuild.no_index = Cannot rebuild, no index is initialized. -owner.settings.cleanuprules.title = Manage cleanup rules +owner.settings.cleanuprules.title = Cleanup rules owner.settings.cleanuprules.add = Add cleanup rule owner.settings.cleanuprules.edit = Edit cleanup rule owner.settings.cleanuprules.none = There are no cleanup rules yet. diff --git a/templates/user/settings/appearance.tmpl b/templates/user/settings/appearance.tmpl index 075c19f0c3..c1d7ac2ccc 100644 --- a/templates/user/settings/appearance.tmpl +++ b/templates/user/settings/appearance.tmpl @@ -43,7 +43,7 @@

- {{ctx.Locale.Tr "settings.language"}} + {{ctx.Locale.Tr "settings.language.title"}}

From 66cb6732edbcb39508bff8455fc22db16e94e2cd Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Mon, 13 May 2024 12:04:20 +0200 Subject: [PATCH 77/99] chore(dependency): automerge golangci-lint upgrades --- renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/renovate.json b/renovate.json index d785e3b5a1..a6b36af601 100644 --- a/renovate.json +++ b/renovate.json @@ -98,6 +98,7 @@ "description": "Automerge some packages when CI succeeds", "extends": ["packages:linters", "packages:test"], "matchDepNames": [ + "github.com/golangci/golangci-lint/cmd/golangci-lint", "github.com/PuerkitoBio/goquery", "happy-dom", "markdownlint-cli", From 584f36f0a179e9bc7b519fd83db5770db6a5044c Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 11 May 2024 16:28:56 +0200 Subject: [PATCH 78/99] Use CSS `inset` shorthand (#30939) Use [inset](https://developer.mozilla.org/en-US/docs/Web/CSS/inset) shorthand instead of longhands. There may be more cases but these ones I was able to definitely identify. Signed-off-by: proton --- web_src/css/helpers.css | 5 +---- web_src/css/markup/content.css | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/web_src/css/helpers.css b/web_src/css/helpers.css index cf2e73572c..64621ac906 100644 --- a/web_src/css/helpers.css +++ b/web_src/css/helpers.css @@ -21,10 +21,7 @@ Gitea's private styles use `g-` prefix. .g-table-auto-ellipsis td.auto-ellipsis span { position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; + inset: 0; padding: inherit; white-space: nowrap; overflow: hidden; diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index 419868a461..cb7823c05f 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -204,10 +204,7 @@ .markup input[type="checkbox"]::after { position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; + inset: 0; pointer-events: none; background: var(--color-text); mask-size: cover; From 337f4f9d87739990bcc60a9f0ecd03c74c49bc17 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Mon, 13 May 2024 15:11:29 +0200 Subject: [PATCH 79/99] Rename Str2html to SanitizeHTML and clarify its behavior (followup) (take 2) In 801792e4dc Rename Str2html to SanitizeHTML and clarify its behavior (followup) the replacement was incorrect because c9d0e63c20 Remove unnecessary "Str2html" modifier from templates was not applied and Str2html should have not been present in the first place. Fixes: https://codeberg.org/forgejo/forgejo/issues/3554 --- release-notes/8.0.0/fix/3744.md | 1 + templates/mail/issue/default.tmpl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 release-notes/8.0.0/fix/3744.md diff --git a/release-notes/8.0.0/fix/3744.md b/release-notes/8.0.0/fix/3744.md new file mode 100644 index 0000000000..5d5d3ef9fe --- /dev/null +++ b/release-notes/8.0.0/fix/3744.md @@ -0,0 +1 @@ +- mail notifications of pull requests push are empty diff --git a/templates/mail/issue/default.tmpl b/templates/mail/issue/default.tmpl index 4e83dbcfdb..395b118d3e 100644 --- a/templates/mail/issue/default.tmpl +++ b/templates/mail/issue/default.tmpl @@ -30,7 +30,7 @@ {{.locale.Tr "mail.issue.action.force_push" .Doer.Name .Comment.Issue.PullRequest.HeadBranch $oldCommitLink $newCommitLink}} {{else}} - {{.locale.TrN (len .Comment.Commits) "mail.issue.action.push_1" "mail.issue.action.push_n" .Doer.Name .Comment.Issue.PullRequest.HeadBranch (len .Comment.Commits) | SanitizeHTML}} + {{.locale.TrN (len .Comment.Commits) "mail.issue.action.push_1" "mail.issue.action.push_n" .Doer.Name .Comment.Issue.PullRequest.HeadBranch (len .Comment.Commits)}} {{end}}

{{end}} From 48c18e17d5d040a122907cd28e91666724282672 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Mon, 13 May 2024 17:32:28 +0200 Subject: [PATCH 80/99] chore(release-notes): go-enry v2.8.8 Refs: https://codeberg.org/forgejo/forgejo/pulls/3723 --- release-notes/8.0.0/feat/3723.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 release-notes/8.0.0/feat/3723.md diff --git a/release-notes/8.0.0/feat/3723.md b/release-notes/8.0.0/feat/3723.md new file mode 100644 index 0000000000..986e10bdc0 --- /dev/null +++ b/release-notes/8.0.0/feat/3723.md @@ -0,0 +1,18 @@ +- With the go-enry upgrade to [v2.8.8](https://github.com/go-enry/go-enry/releases/tag/v2.8.8), language detection in the repository [now includes](https://github.com/github-linguist/linguist/releases/tag/v7.29.0): + - New languages + - [Roc](https://github.com/github-linguist/linguist/pull/6633) + - [BitBake](https://github.com/github-linguist/linguist/pull/6665) with `.bbappend`, `.bbclass` and `.inc` extensions + - [Glimmer TS](https://github.com/github-linguist/linguist/pull/6680) + - [Edge](https://github.com/github-linguist/linguist/pull/6695) + - [Pip Requirements](https://github.com/github-linguist/linguist/pull/6739) + - [Mojo](https://github.com/github-linguist/linguist/pull/6400) + - [Slint](https://github.com/github-linguist/linguist/pull/6750) + - [Oberon](https://github.com/github-linguist/linguist/pull/4645) + - New data formats + - [TextGrid](https://github.com/github-linguist/linguist/pull/6719) + - File names and extensions: + - The [rebornix.Ruby extension is deprecated in favor of Shopify.ruby-lsp](https://github.com/github-linguist/linguist/pull/6738) + - [Add .bicepparam to list of Bicep file extensions](https://github.com/github-linguist/linguist/pull/6664) + - [Add cs.pp extension to C#](https://github.com/github-linguist/linguist/pull/6679) + - [Add tmux.conf and .tmux.conf as shell filenames](https://github.com/github-linguist/linguist/pull/6726) + - [Add .env.sample as Dotenv filename](https://github.com/github-linguist/linguist/pull/6732) From 61643a698cd5f00f1132bbee5798144a48ab4255 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Mon, 13 May 2024 18:16:35 +0000 Subject: [PATCH 81/99] Translation updates from Weblate (#3748) This is not the usual Weblate PR. I did not reset Weblate after squash-merging https://codeberg.org/forgejo/forgejo/pulls/3637, so Weblate failed to rebase and locked. These are manually cherry-picked commits that Weblate produced after that PR was merged. We need to squash-merge them too before resetting Weblate, so the new translations don't get lost. Co-authored-by: earl-warren Co-authored-by: Cwpute Co-authored-by: Mylloon Co-authored-by: leana8959 Co-authored-by: owofied Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3748 Reviewed-by: Earl Warren --- options/locale/locale_fr-FR.ini | 73 +++++++++++++++++---------------- options/locale/locale_pl-PL.ini | 58 ++++++++++++++++++++------ 2 files changed, 83 insertions(+), 48 deletions(-) diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 1c99f86cb1..8079656d5b 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -148,13 +148,13 @@ filter.is_archived = Archivé filter.not_archived = Non archivé filter.is_fork = Bifurcations filter.not_fork = Non dupliqué -filter.not_mirror = Non répliqué -filter.is_template = Modèle -filter.not_template = Pas un modèle +filter.not_mirror = Non miroirs +filter.is_template = Modèles +filter.not_template = Non modèles filter.public = Publique filter.private = Privé filter = Filtre -filter.is_mirror = Répliqué +filter.is_mirror = Miroirs toggle_menu = Menu va-et-vient more_items = Plus d'éléments invalid_data = Données invalides : %v @@ -637,7 +637,7 @@ required_prefix = Le texte entré doit commencer par "%s" AccessToken = Jeton d'accès FullName = Nom complet Description = Description -Pronouns = Qualités +Pronouns = Pronoms Biography = Biographie Website = Site web Location = Emplacement @@ -997,11 +997,11 @@ user_block_success = Cet utilisateur a été bloqué avec succès. change_password = Modifier le mot de passe hints = Suggestions additional_repo_units_hint_description = Afficher un bouton "Ajouter plus d'unités..." pour les dépôts qui n'ont pas toutes les unités disponibles activées. -additional_repo_units_hint = Encourager l'ajout de nouvelles unités pour le dépôt +additional_repo_units_hint = Suggérer l'ajout de nouvelles unités pour le dépôt update_hints = Mettre à jour les suggestions update_hints_success = Les suggestions ont été mises à jour. -pronouns_custom = Sur mesure -pronouns = Qualités +pronouns_custom = Personnalisés +pronouns = Pronoms pronouns_unspecified = Non spécifié [repo] @@ -1971,7 +1971,7 @@ wiki.default_commit_message=Écrire une note concernant cette mise à jour (opti wiki.save_page=Enregistrer la page wiki.last_commit_info=%s a édité cette page %s wiki.edit_page_button=Modifier -wiki.new_page_button=Nouvelle Page +wiki.new_page_button=Nouvelle page wiki.file_revision=Révisions de la page wiki.wiki_page_revisions=Révisions de la page wiki wiki.back_to_wiki=Retour à la page wiki @@ -2144,12 +2144,12 @@ settings.pulls.default_allow_edits_from_maintainers=Autoriser les modifications settings.releases_desc=Activer les publications du dépôt settings.packages_desc=Activer le registre des paquets du dépôt settings.projects_desc=Activer les projets de dépôt -settings.actions_desc=Activer les actions du dépôt +settings.actions_desc=Activer l'intégration continue avec Forgejo Actions settings.admin_settings=Paramètres administrateur settings.admin_enable_health_check=Activer les vérifications de santé du dépôt (git fsck) settings.admin_code_indexer=Indexeur de code settings.admin_stats_indexer=Indexeur des statistiques de code -settings.admin_indexer_commit_sha=Dernier SHA indexé +settings.admin_indexer_commit_sha=Dernier commit indexé settings.admin_indexer_unindexed=Non indexé settings.reindex_button=Ajouter à queue de réindexation settings.reindex_requested=Réindexation demandée @@ -2525,7 +2525,7 @@ diff.file_after=Après diff.file_image_width=Largeur diff.file_image_height=Hauteur diff.file_byte_size=Taille -diff.file_suppressed=Fichier diff supprimé car celui-ci est trop grand +diff.file_suppressed=Diff de fichier supprimé car celui-ci est trop grand diff.file_suppressed_line_too_long=Diff de fichier supprimé car une ou plusieurs lignes sont trop longues diff.too_many_files=Certains fichiers ne sont pas affichés car ce diff contient trop de modifications diff.show_more=Voir plus @@ -2539,7 +2539,7 @@ diff.comment.add_single_comment=Commenter (simple) diff.comment.add_review_comment=Commenter diff.comment.start_review=Débuter une évaluation diff.comment.reply=Répondre -diff.review=Évaluation +diff.review=Terminer l'évaluation diff.review.header=Évaluer diff.review.placeholder=Commenter cette évaluation diff.review.comment=Commenter @@ -2584,7 +2584,7 @@ release.prerelease_desc=Marquer comme pré-publication release.prerelease_helper=Marquer cette publication comme impropre à la production. release.cancel=Annuler release.publish=Publier -release.save_draft=Sauvegarder le Brouillon +release.save_draft=Sauvegarder le brouillon release.edit_release=Actualiser la publication release.delete_release=Supprimer cette publication release.delete_tag=Supprimer l'étiquette @@ -2600,7 +2600,7 @@ release.tag_already_exist=Ce nom d'étiquette existe déjà. release.downloads=Téléchargements release.download_count=Télécharger: %s release.add_tag_msg=Utiliser le titre et le contenu de la publication comme message d’étiquette. -release.add_tag=Créer uniquement l'étiquette +release.add_tag=Créer l'étiquette release.releases_for=Publications pour %s release.tags_for=Étiquettes pour %s @@ -2720,7 +2720,7 @@ pulls.merged_title_desc_one = fusionné %[1]d commit depuis %[2]s v pulls.title_desc_one = veut fusionner %[1]d commit depuis %[2]s vers %[3]s stars = Étoiles n_tag_few = %s étiquettes -editor.commit_id_not_matching = L'ID de la révision ne correspond pas à celui que vous éditiez. Appliquez les modifications à une nouvelle branche puis procédez à la fusion. +editor.commit_id_not_matching = Le fichier a été modifié pendant que vous l'éditiez. Appliquez les modifications à une nouvelle branche puis procédez à la fusion. commits.search_branch = Cette branche open_with_editor = Ouvrir avec %s pulls.ready_for_review = Prêt à être évalué ? @@ -2752,7 +2752,7 @@ settings.matrix.room_id_helper = L'identifiant du salon peut être obtenu dans l settings.sourcehut_builds.access_token_helper = Un jeton d'accès ayant des permissions JOBS:RW. Génère un jeton builds.sr.ht ou un jeton builds.sr.ht token ayant accès aux secrets sur meta.sr.ht. settings.matrix.access_token_helper = Il est recommandé de créer un compte Matrix dédié pour cela. Le jeton d'accès peut être obtenu depuis le client web Element (dans un onglet privé/incognito). Il faut ensuite fermer l'onglet privé/icognito (se déconnecter invaliderait le jeton). release.hide_archive_links = Masquer les archives générées automatiquement -release.hide_archive_links_helper = Masquer les archives de code source générées automatiquement pour cette version. Par exemple, si vous téléchargez vos propres archives. +release.hide_archive_links_helper = Masquer les archives de code source générées automatiquement pour cette publication. Par exemple, si vous téléchargez vos propres archives. [graphs] component_loading=Chargement de %s… @@ -2820,9 +2820,9 @@ settings.labels_desc=Ajoute des labels qui peuvent être utilisés sur les ticke members.membership_visibility=Visibilité des membres: members.public=Visible -members.public_helper=rendre caché +members.public_helper=Rendre caché members.private=Caché -members.private_helper=rendre visible +members.private_helper=Rendre visible members.member_role=Rôle du membre : members.owner=Propriétaire members.member=Membre @@ -2885,6 +2885,7 @@ teams.invite.title=Vous avez été invité à rejoindre l'équipe %s%s @@ -3680,6 +3682,7 @@ rpm.repository = Information sur le dépôt rpm.repository.architectures = Architectures rpm.repository.multiple_groups = Ce paquet est disponible dans plusieurs groupes. owner.settings.cargo.rebuild.no_index = Incapable de reconstruire, index non initialisé. +npm.dependencies.bundle = Bundles de dépendances [secrets] secrets=Secrets @@ -3694,12 +3697,12 @@ deletion=Supprimer le secret deletion.description=La suppression d'un secret est permanente et irréversible. Continuer ? deletion.success=Le secret a été supprimé. deletion.failed=Impossible de supprimer le secret. -management=Gestion des Secrets +management=Gestion des secrets [actions] actions=Actions -unit.desc=Gérer les actions +unit.desc=Gérer l'intégration continue avec Forgejo Actions status.unknown=Inconnu status.waiting=En attente @@ -3747,7 +3750,7 @@ runners.version=Version runners.reset_registration_token=Réinitialiser le jeton d'enregistrement runners.reset_registration_token_success=Le jeton d’inscription de l’exécuteur a été réinitialisé avec succès -runs.all_workflows=Tous les flux de travail +runs.all_workflows=Tous les workflows runs.commit=Révision runs.scheduled=Planifié runs.pushed_by=soumis par @@ -3764,9 +3767,9 @@ runs.no_workflows.documentation=Pour plus d’informations sur les actions Gitea runs.no_runs=Le flux de travail n'a pas encore d'exécution. runs.empty_commit_message=(message de révision vide) -workflow.disable=Désactiver le flux de travail +workflow.disable=Désactiver le workflow workflow.disable_success=Le flux de travail « %s » a bien été désactivé. -workflow.enable=Activer le flux de travail +workflow.enable=Activer le workflow workflow.enable_success=Le workflow « %s » a bien été activé. workflow.disabled=Le flux de travail est désactivé. @@ -3795,8 +3798,8 @@ runs.no_job_without_needs = Le workflow doit contenir au moins une tâche sans d [projects] type-1.display_name=Projet personnel -type-2.display_name=Projet de dépôt -type-3.display_name=Projet d’organisation +type-2.display_name=Projet du dépôt +type-3.display_name=Projet de l'organisation [git.filemode] changed_filemode=%[1]s → %[2]s @@ -3845,12 +3848,12 @@ commit_kind = Chercher les commits... [munits.data] b = o -mib = MiB -kib = KiB -gib = GiB -tib = TiB -pib = PiB -eib = EiB +mib = Mo +kib = ko +gib = Go +tib = To +pib = Po +eib = Eo [markup] filepreview.line = Ligne %[1]d dans %[2]s diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index 38109eb2c3..3d5adc8561 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -143,7 +143,7 @@ show_log_seconds = Pokaż sekundy show_full_screen = Pokaż pełny ekran download_logs = Pobierz logi confirm_delete_selected = Potwierdzić usunięcie wszystkich wybranych elementów? -filter.is_template = Szablon +filter.is_template = Szablony filter.public = Publiczne filter.private = Prywatne copy_generic = Skopiuj do schowka @@ -152,10 +152,11 @@ tracked_time_summary = Podsumowanie śledzonego czasu na podstawie filtrów list show_timestamps = Pokaż znaczniki czasu filter.not_archived = Nie zarchiwizowane filter.not_mirror = Nie lustrzane odbicie -filter.not_template = Nie szablon +filter.not_template = Nie szablony filter.is_archived = Zarchiwizowane -filter.is_mirror = Lustrzane odbicie +filter.is_mirror = Kopie lustrzane more_items = Więcej elementów +filter.is_fork = Forki [aria] navbar = Pasek nawigacji @@ -167,6 +168,10 @@ footer.links = Linki contributions_format = {contributions} w dniu {month} {day}, {year} less = Mniej more = Więcej +number_of_contributions_in_the_last_12_months = %s wkładów w ciągu ostatnich 12 miesięcy +contributions_zero = Brak wkładów +contributions_one = Wkład +contributions_few = Wkłady [editor] buttons.heading.tooltip = Dodaj nagłówek @@ -206,7 +211,7 @@ lightweight=Niskie wymagania lightweight_desc=Forgejo ma niskie minimalne wymagania i może działać na niedrogim Raspberry Pi. Oszczędzaj energię swojego komputera! license=Otwarte źródło license_desc=Pobierz na Forgejo! Dołącz do nas dzięki swojemu wkładowi, aby uczynić ten projekt jeszcze lepszym. Nie wstydź się zostać współtwórcą! -install_desc = Po prostu uruchom plik binarny dla swojej platformy, dostarcz ją za pomocą Dockera, lub weż wersjęzapakowaną. +install_desc = Po prostu uruchom plik binarny dla swojej platformy, dostarcz ją za pomocą Dockera, lub użyj wersji zapakowanej. [install] install=Instalacja @@ -367,6 +372,9 @@ go_to = Przejdź do relevant_repositories = Wyświetlane są tylko istotne repozytoria, pokaż niefiltrowane wyniki. stars_one = %d gwiazdka stars_few = %d gwiazdek +forks_one = %d fork +forks_few = %d forki +relevant_repositories_tooltip = Repozytoria, które nie są forkami lub nie mają tematu, ikony i opisu są ukryte. [auth] create_new_account=Zarejestruj konto @@ -431,10 +439,23 @@ prohibit_login_desc = Twoje konto jest zablokowane, skontaktuj się z administra change_unconfirmed_email_summary = Zmień adres e-mail, na który zostanie wysłana wiadomość aktywacyjna. manual_activation_only = Skontaktuj się z administratorem witryny, aby dokończyć aktywację. change_unconfirmed_email = Jeśli podczas rejestracji podałeś nieprawidłowy adres e-mail, możesz go zmienić poniżej, a potwierdzenie zostanie wysłane na nowy adres. +openid_signin_desc = Wprowadź swój identyfikator URI OpenID. Na przykład: alice.openid.example.org lub https://openid.example.org/alice. +authorization_failed_desc = Autoryzacja nie powiodła się, ponieważ wykryliśmy nieprawidłowe żądanie. Skontaktuj się z autorem aplikacji, którą próbowałeś autoryzować. +password_pwned = Wybrane hasło znajduje się na liście skradzionych haseł, które zostały wcześniej ujawnione w wyniku publicznego naruszenia danych. Spróbuj ponownie z innym hasłem i rozważ zmianę tego hasła również w innych miejscach. +last_admin = Nie można usunąć ostatniego administratora. Musi istnieć co najmniej jeden administrator. +tab_signin = Zaloguj +oauth.signin.error = Wystąpił błąd podczas przetwarzania żądania autoryzacji. Jeśli ten błąd nadal występuje, skontaktuj się z administratorem witryny. +change_unconfirmed_email_error = Nie udało się zmienić adresu email: %v +invalid_code_forgot_password = Twój kod potwierdzający jest niepoprawny lub wygasł. Naciśnij tutaj⁣, aby rozpocząć nową sesję. +invalid_password = Twoje hasło nie zgadza się z hasłem, które zostało użyte do stworzenia konta. +reset_password_wrong_user = Jesteś zalogowany jako %s, ale link odzyskujący jest dla %s +tab_signup = Zarejestruj +oauth.signin.error.access_denied = Wniosek o autoryzację został odrzucony. +oauth.signin.error.temporarily_unavailable = Autoryzacja nie powiodła się, ponieważ serwer uwierzytelniania jest tymczasowo niedostępny. Spróbuj ponownie później. [mail] view_it_on=Zobacz na %s -link_not_working_do_paste=Nie działa? Spróbuj skopiować i wkleić go do przeglądarki. +link_not_working_do_paste=Czy link nie działa? Spróbuj skopiować i wkleić go do paska adresu URL przeglądarki. hi_user_x=Cześć %s, activate_account=Aktywuj swoje konto @@ -448,12 +469,12 @@ activate_email.text=Aby zweryfikować swój adres e-mail, w ciągu następnych < register_notify=Witamy w Forgejo register_notify.title=%[1]s, witaj w %[2]s register_notify.text_1=to jest Twój e-mail z potwierdzeniem rejestracji dla %s! -register_notify.text_2=Możesz teraz zalogować się za pomocą nazwy użytkownika: %s. -register_notify.text_3=Jeśli to konto zostało utworzone dla Ciebie, ustaw swoje hasło. +register_notify.text_2=Możesz teraz zalogować się za pomocą nazwy użytkownika: %s +register_notify.text_3=Jeśli ktoś inny utworzył dla ciebie to konto, musisz najpierw ustawić swoje hasło. reset_password=Odzyskaj swoje konto -reset_password.title=%s, prosiłeś o odzyskanie konta -reset_password.text=Kliknij poniższy link, aby odzyskać swoje konto w ciągu %s: +reset_password.title=%s, otrzymaliśmy prośbę o odzyskanie konta +reset_password.text=Jeśli to byłeś ty, kliknij poniższy link, aby odzyskać swoje konto w ciągu %s: register_success=Rejestracja powiodła się @@ -477,13 +498,24 @@ release.downloads=Pobierz: release.download.zip=Kod źródłowy (ZIP) release.download.targz=Kod źródłowy (TAR.GZ) -repo.transfer.subject_to=%s chciałby przenieść "%s" do %s -repo.transfer.subject_to_you=%s chciałby przenieść "%s" do ciebie +repo.transfer.subject_to=%s chce przenieść repozytorium "%s" do %s +repo.transfer.subject_to_you=%s chce przenieść repozytorium "%s" do ciebie repo.transfer.to_you=ciebie repo.transfer.body=Aby zaakceptować lub odrzucić go, odwiedź %s lub po prostu go zignoruj. -repo.collaborator.added.subject=%s dodał Cię do %s -repo.collaborator.added.text=Zostałeś dodany jako współtwórca repozytorium: +repo.collaborator.added.subject=%s dodał cię do %s jako współtwórce +repo.collaborator.added.text=Zostałeś dodany jako współtwórca do repozytorium: +issue.action.push_1 = @%[1]s pchnął %[3]d commit do %[2]s +activate_email.title = %s, zweryfikuj swój adres e-mail +admin.new_user.text = Kliknij tutaj, aby zarządzać tym użytkownikiem z panelu administracyjnego. +issue.action.push_n = @%[1]s pchnął %[3]d commity do %[2]s +reply = lub odpowiedz bezpośrednio na ten e-mail +admin.new_user.subject = Właśnie zarejestrował się nowy użytkownik %s +admin.new_user.user_info = Informacje użytkownika +issue.action.approve = @%[1]s zatwierdził ten pull request. +issue.action.reject = @%[1]s poprosił o zmiany w tym pull requescie. +issue.action.review_dismissed = @%[1]s odrzucił ostatnią analizę od %[2]s dla tego pull requesta. +team_invite.subject = %[1]s zaprosił cię do dołączenia do organizacji %[2]s [modal] From e4e84a7ecf4b14873e68a56b8ab2288e7db79bc7 Mon Sep 17 00:00:00 2001 From: 0ko <0ko@noreply.codeberg.org> Date: Mon, 13 May 2024 18:22:16 +0000 Subject: [PATCH 82/99] Improve translatability of "Transfer ownership" (#3739) This text can have different forms in other languages depending on context. The commit also contains a change to .editorconfig to prevent EoF changes when mass-replacing strings, as that causes unintentional merge conflicts with Weblate. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3739 Reviewed-by: Earl Warren --- .editorconfig | 3 +++ options/locale/locale_ar.ini | 2 +- options/locale/locale_bg.ini | 2 +- options/locale/locale_cs-CZ.ini | 2 +- options/locale/locale_de-DE.ini | 2 +- options/locale/locale_el-GR.ini | 2 +- options/locale/locale_en-US.ini | 4 +++- options/locale/locale_es-ES.ini | 2 +- options/locale/locale_fa-IR.ini | 2 +- options/locale/locale_fi-FI.ini | 2 +- options/locale/locale_fr-FR.ini | 2 +- options/locale/locale_id-ID.ini | 2 +- options/locale/locale_is-IS.ini | 2 +- options/locale/locale_it-IT.ini | 2 +- options/locale/locale_ja-JP.ini | 2 +- options/locale/locale_ko-KR.ini | 2 +- options/locale/locale_lv-LV.ini | 2 +- options/locale/locale_nl-NL.ini | 2 +- options/locale/locale_pl-PL.ini | 2 +- options/locale/locale_pt-BR.ini | 2 +- options/locale/locale_pt-PT.ini | 2 +- options/locale/locale_ru-RU.ini | 2 +- options/locale/locale_si-LK.ini | 2 +- options/locale/locale_sk-SK.ini | 2 +- options/locale/locale_sv-SE.ini | 2 +- options/locale/locale_tr-TR.ini | 2 +- options/locale/locale_uk-UA.ini | 2 +- options/locale/locale_zh-CN.ini | 2 +- options/locale/locale_zh-HK.ini | 2 +- options/locale/locale_zh-TW.ini | 2 +- templates/repo/settings/options.tmpl | 6 +++--- 31 files changed, 37 insertions(+), 32 deletions(-) diff --git a/.editorconfig b/.editorconfig index c0946ac997..722416dfeb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -26,3 +26,6 @@ indent_style = tab [*.svg] insert_final_newline = false + +[options/locale/locale_*.ini] +insert_final_newline = false diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini index bcd4b6af9f..4879bb1cc6 100644 --- a/options/locale/locale_ar.ini +++ b/options/locale/locale_ar.ini @@ -1214,7 +1214,7 @@ settings.pulls_desc = فعّل طلب الدمج في المستودع settings.pulls.ignore_whitespace = تجاهل المسافات في النزاعات settings.danger_zone = منطقة الخطر settings.new_owner_has_same_repo = المالك الجديد لديه مستودع بالاسم نفسه؛ برجاء اختيار اسم آخر. -settings.transfer = نقل الملكية +settings.transfer.title = نقل الملكية settings.transfer_abort = ألغِ نقل الملكية settings.transfer_abort_invalid = لا يمكنك إلغاء عملية غير موجودة لنقل ملكية مستودع. settings.transfer.success = نجح نقل ملكية المستودع. diff --git a/options/locale/locale_bg.ini b/options/locale/locale_bg.ini index d7093b85d5..260249682e 100644 --- a/options/locale/locale_bg.ini +++ b/options/locale/locale_bg.ini @@ -570,7 +570,7 @@ issues.role.owner_helper = Този потребител е притежател settings.delete_notices_2 = - Тази операция ще изтрие перманентно хранилището %s, включително кода, задачите, коментарите, данните на уикито и настройките за сътрудници. settings.admin_settings = Администраторски настройки issues.role.owner = Притежател -settings.transfer = Прехвърляне на притежанието +settings.transfer.title = Прехвърляне на притежанието issues.author = Автор issues.closed_at = `затвори тази задача %[2]s` settings.collaborator_deletion_desc = Премахването на сътрудник ще отнеме достъпа му до това хранилище. Продължаване? diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 9e278f3fd0..accd305630 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -2153,7 +2153,7 @@ settings.convert_fork_desc=Tento fork můžete převést na běžný repozitář settings.convert_fork_notices_1=Tato operace převede fork na běžný repozitář a nelze ji vrátit zpět. settings.convert_fork_confirm=Převést repozitář settings.convert_fork_succeed=Fork bylo převeden na běžný repozitář. -settings.transfer=Předat vlastnictví +settings.transfer.title=Předat vlastnictví settings.transfer.rejected=Převod repozitáře byl zamítnut. settings.transfer.success=Převod repozitáře byl úspěšný. settings.transfer_abort=Zrušit převod diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index a1a55c4dfa..0828cc4dec 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -2146,7 +2146,7 @@ settings.convert_fork_desc=Du kannst diesen Fork in ein normales Repository umwa settings.convert_fork_notices_1=Dieser Vorgang konvertiert den Fork in ein normales Repository und kann nicht rückgängig gemacht werden. settings.convert_fork_confirm=Repository umwandeln settings.convert_fork_succeed=Der Fork wurde in ein normales Repository konvertiert. -settings.transfer=Besitz übertragen +settings.transfer.title=Besitz übertragen settings.transfer.rejected=Repository-Übertragung wurde abgelehnt. settings.transfer.success=Repository-Übertragung war erfolgreich. settings.transfer_abort=Übertragung abbrechen diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index e1264aea00..fbf5cfe235 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -2145,7 +2145,7 @@ settings.convert_fork_desc=Μπορείτε να μετατρέψετε αυτό settings.convert_fork_notices_1=Αυτή η λειτουργία θα μετατρέψει το fork σε ένα κανονικό αποθετήριο και δεν μπορεί να αναιρεθεί. settings.convert_fork_confirm=Μετατροπή αποθετηρίου settings.convert_fork_succeed=Το fork έχει μετατραπεί σε κανονικό αποθετήριο. -settings.transfer=Μεταβίβαση ιδιοκτησίας +settings.transfer.title=Μεταβίβαση ιδιοκτησίας settings.transfer.rejected=Η μεταβίβαση του αποθετηρίου απορρίφθηκε. settings.transfer.success=Η μεταβίβαση του αποθετηρίου ήταν επιτυχής. settings.transfer_abort=Ακύρωση μεταβίβασης diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index b95c72d289..12c4197c67 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2202,7 +2202,9 @@ settings.convert_fork_desc = You can convert this fork into a regular repository settings.convert_fork_notices_1 = This operation will convert the fork into a regular repository and cannot be undone. settings.convert_fork_confirm = Convert repository settings.convert_fork_succeed = The fork has been converted into a regular repository. -settings.transfer = Transfer ownership +settings.transfer.title = Transfer ownership +settings.transfer.button = Transfer ownership +settings.transfer.modal.title = Transfer ownership settings.transfer.rejected = Repository transfer was rejected. settings.transfer.success = Repository transfer was successful. settings.transfer_abort = Cancel transfer diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 7727e930a6..9575ca355b 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -2109,7 +2109,7 @@ settings.convert_fork_desc=Puede convertir este fork en un repositorio normal. E settings.convert_fork_notices_1=Esta operación convertirá el fork en un repositorio regular y no se puede deshacer. settings.convert_fork_confirm=Convertir repositorio settings.convert_fork_succeed=El fork se ha convertido en un repositorio normal. -settings.transfer=Transferir la propiedad +settings.transfer.title=Transferir la propiedad settings.transfer.rejected=La transferencia de repositorio fue rechazada. settings.transfer.success=La transferencia del repositorio fue exitosa. settings.transfer_abort=Cancelar transferencia diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index fbacfd72c8..c07e906146 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -1595,7 +1595,7 @@ settings.convert_fork_desc=شما می توانید این انشعاب را ب settings.convert_fork_notices_1=این عملیات، انشعاب را تبدیل به مخزن عادی خواهد کرد و بازگشت ناپذیر است. settings.convert_fork_confirm=تبدیل مخزن settings.convert_fork_succeed=انشعاب به یک مخزن عادی تبدیل شده است. -settings.transfer=انتقال مالکیت +settings.transfer.title=انتقال مالکیت settings.transfer.rejected=انتقال انبار رد شده است. settings.transfer.success=انتقال انبار موفق بود. settings.transfer_abort=لغو انتقال diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index 1560075d6b..cee797a170 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -1133,7 +1133,7 @@ settings.tracker_issue_style.alphanumeric=Aakkosnumeerinen settings.enable_timetracker=Ota käyttöön ajan seuranta settings.danger_zone=Vaaravyöhyke settings.new_owner_has_same_repo=Uudella omistajalla on jo samanniminen repo. Ole hyvä ja valitse toinen nimi. -settings.transfer=Siirrä omistajuus +settings.transfer.title=Siirrä omistajuus settings.transfer_form_title=Syötä repon nimi vahvistuksena: settings.transfer_notices_3=- Jos arkisto on yksityinen ja se siirretään yksittäiselle käyttäjälle, tämä toiminto varmistaa, että käyttäjällä on ainakin lukuoikeudet (ja muuttaa käyttöoikeuksia tarvittaessa). settings.transfer_owner=Uusi omistaja diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 8079656d5b..19fb8fc85f 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -2166,7 +2166,7 @@ settings.convert_fork_desc=Vous pouvez convertir cette bifurcation en dépôt st settings.convert_fork_notices_1=Cette opération convertira la bifurcation en dépôt standard. Cette action est irréversible. settings.convert_fork_confirm=Convertir le dépôt settings.convert_fork_succeed=La bifurcation a été convertie en dépôt standard. -settings.transfer=Changer de propriétaire +settings.transfer.title=Changer de propriétaire settings.transfer.rejected=Le transfert du dépôt a été rejeté. settings.transfer.success=Le transfert du dépôt a réussi. settings.transfer_abort=Annuler le transfert diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 26e3a9b22d..5370a404f0 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -869,7 +869,7 @@ settings.tracker_issue_style.numeric=Numerik settings.tracker_issue_style.alphanumeric=Alfhanumerik settings.danger_zone=Zona Bahaya settings.new_owner_has_same_repo=Pemilik baru sudah memiliki repositori dengan nama yang sama. Silakan pilih nama lain. -settings.transfer=Transfer Kepemilikan +settings.transfer.title=Transfer Kepemilikan settings.transfer_owner=Pemilik Baru settings.delete=Menghapus Repositori Ini settings.delete_notices_1=- Operasi ini TIDAK BISA dibatalkan. diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini index e448ee4568..9d890773b2 100644 --- a/options/locale/locale_is-IS.ini +++ b/options/locale/locale_is-IS.ini @@ -1024,7 +1024,7 @@ settings.use_external_wiki=Nota Utanaðkomandi Handbók settings.tracker_issue_style.numeric=Tölugildi settings.danger_zone=Hættusvæði settings.convert_notices_1=Þessi aðgerð mun breyta speglinum í venjulegt hugbúnaðarsafn og ekki er hægt að afturkalla hana. -settings.transfer=Flytja Eignarhald +settings.transfer.title=Flytja Eignarhald settings.trust_model.collaboratorcommitter.desc=Gildar undirskriftir frá samstarfsaðilum hugbúnaðarsafnsins verða merktar „traust“ ef þær passa við framlagandan. Að öðrum kosti verða gildar undirskriftir merktar „ótraust“ ef undirskriftin passar við framlagandan og „ósamþykkt“ að öðru leyti. Þetta mun neyða Forgejo til að vera merkt sem framlagandi á undirrituðum framlögum með raunverulega framlagandan merktan sem Co-Authored-By: og Co-Committed-By: í framlaginu. Sjálfgefinn Forgejo lykill verður að passa við notanda í gagnagrunninum. settings.wiki_delete_desc=Að eyða handbókargögn er varanlegt og ekki er hægt að afturkalla það. settings.delete=Eyða Þetta Hugbúnaðarsafn diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index 2af6019eae..367b373252 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -1946,7 +1946,7 @@ settings.convert_fork_desc=Puoi convertire questo fork in un normale repository. settings.convert_fork_notices_1=Questa operazione convertirà il fork in un normale repository e non può essere annullata. settings.convert_fork_confirm=Converti progetto settings.convert_fork_succeed=Il fork è stato convertito in un repository regolare. -settings.transfer=Trasferisci proprietà +settings.transfer.title=Trasferisci proprietà settings.transfer.rejected=Il trasferimento del repository è stato rifiutato. settings.transfer.success=Il trasferimento del repository è andato a buon fine. settings.transfer_abort=Annulla trasferimento diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 8d06177d2f..4b1ffce9f6 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -2159,7 +2159,7 @@ settings.convert_fork_desc=フォークを通常のリポジトリに変換で settings.convert_fork_notices_1=この操作によりフォークから通常のリポジトリに変換されます。 元に戻すことはできません。 settings.convert_fork_confirm=リポジトリを変換 settings.convert_fork_succeed=フォークを通常のリポジトリに変換しました。 -settings.transfer=オーナー移転 +settings.transfer.title=オーナー移転 settings.transfer.rejected=リポジトリの移転は拒否されました。 settings.transfer.success=リポジトリの移転が成功しました。 settings.transfer_abort=転送をキャンセル diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index 07a82eff17..4e3a24a04b 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -1081,7 +1081,7 @@ settings.convert=일반 저장소로 변환 settings.convert_confirm=저장소 변환 settings.convert_fork=일반 저장소로 변환 settings.convert_fork_confirm=저장소 변환 -settings.transfer=소유권 이전 +settings.transfer.title=소유권 이전 settings.transfer_owner=새 소유자 settings.transfer_succeed=저장소가 이전 되었습니다. settings.trust_model.collaborator=협업자 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index e2ab79e3f8..ba1883acdb 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -2080,7 +2080,7 @@ settings.convert_fork_desc=Jūs varat nomainīt šo atdalīto repozitoriju kā n settings.convert_fork_notices_1=Šī darbība mainīs atdalīto repozitoriju uz neatkarīgu repozitoriju un ir neatgriezeniska. settings.convert_fork_confirm=Konvertēt repozitoriju settings.convert_fork_succeed=Atdalītais repozitorijs tika izmainīts par neatkarīgu repozitoriju. -settings.transfer=Mainīt īpašnieku +settings.transfer.title=Mainīt īpašnieku settings.transfer.rejected=Repozitorija īpašnieka maiņas pieprasījums tika noraidīts. settings.transfer.success=Repozitorija īpašnieka maiņa veiksmīga. settings.transfer_abort=Atcelt īpašnieka maiņu diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index 7c78a30237..a710e5d58a 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -2480,7 +2480,7 @@ settings.reindex_button = Toevoegen aan herindexeringswachtrij settings.reindex_requested = Herindexering aangevraagd settings.danger_zone = Gevaren zone settings.new_owner_has_same_repo = De nieuwe eigenaar heeft al een repository met dezelfde naam. Kies een andere naam. -settings.transfer = Eigendom overdragen +settings.transfer.title = Eigendom overdragen settings.transfer.success = Repository overdracht was succesvol. settings.transfer_abort = Overdracht annuleren settings.transfer_abort_success = De repository overdracht naar %s is succesvol geannuleerd. diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index 3d5adc8561..99ab350b66 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -1665,7 +1665,7 @@ settings.convert_fork_desc=Możesz przekonwertować ten fork w zwykłe repozytor settings.convert_fork_notices_1=Ta operacja przekonwertuje fork w zwykłe repozytorium i nie może być cofnięta. settings.convert_fork_confirm=Konwertuj repozytorium settings.convert_fork_succeed=Fork został przekonwertowany w zwykłe repozytorium. -settings.transfer=Przeniesienie własności +settings.transfer.title=Przeniesienie własności settings.transfer.rejected=Przeniesienie repozytorium zostało odrzucone. settings.transfer.success=Przeniesienie repozytorium powiodło się. settings.transfer_abort=Anuluj transfer diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 27f8f0066a..705c163853 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -2082,7 +2082,7 @@ settings.convert_fork_desc=Você pode converter este fork em um repositório nor settings.convert_fork_notices_1=Esta operação irá converter o fork em um repositório normal e não pode ser desfeita. settings.convert_fork_confirm=Converter repositório settings.convert_fork_succeed=O fork foi convertido em um repositório normal. -settings.transfer=Transferir propriedade +settings.transfer.title=Transferir propriedade settings.transfer.rejected=A transferência do repositório foi rejeitada. settings.transfer.success=A transferência do repositório foi bem sucedida. settings.transfer_abort=Cancelar transferência diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index de68e23c86..4a915122f7 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -2168,7 +2168,7 @@ settings.convert_fork_desc=Pode converter esta derivação num repositório norm settings.convert_fork_notices_1=Esta operação irá converter a derivação num repositório normal e não poderá ser revertida. settings.convert_fork_confirm=Converter repositório settings.convert_fork_succeed=A derivação foi convertida num repositório normal. -settings.transfer=Transferir a propriedade +settings.transfer.title=Transferir a propriedade settings.transfer.rejected=A transferência do repositório foi rejeitada. settings.transfer.success=A transferência do repositório foi bem sucedida. settings.transfer_abort=Cancelar a transferência diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index f4ee7a1da0..65a927c635 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -2124,7 +2124,7 @@ settings.convert_fork_desc=Вы можете преобразовать это settings.convert_fork_notices_1=Эта операция преобразует этот ответвление в обычный репозиторий, и не может быть отменена. settings.convert_fork_confirm=Преобразовать репозиторий settings.convert_fork_succeed=Ответвление преобразовано в обычный репозиторий. -settings.transfer=Передать права собственности +settings.transfer.title=Передать права собственности settings.transfer.rejected=Передача репозитория отменена. settings.transfer.success=Передача репозитория выполнена успешно. settings.transfer_abort=Отменить передачу diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini index a0b5f9f4e2..1d133d7570 100644 --- a/options/locale/locale_si-LK.ini +++ b/options/locale/locale_si-LK.ini @@ -1537,7 +1537,7 @@ settings.convert_fork_desc=ඔබට මෙම දෙබලක සාමාන settings.convert_fork_notices_1=මෙම මෙහෙයුම දෙබලක සාමාන්ය ගබඩාවක් බවට පරිවර්තනය කරන අතර එය අහෝසි කළ නොහැක. settings.convert_fork_confirm=පරිවර්තනය කරන්න ගබඩාව settings.convert_fork_succeed=මෙම දෙබලක සාමාන්ය ගබඩාවක් බවට පරිවර්තනය කර ඇත. -settings.transfer=අයිතිය පැවරීම +settings.transfer.title=අයිතිය පැවරීම settings.transfer.rejected=ගබඩාව මාරු කිරීම ප්රතික්ෂේප කරන ලදී. settings.transfer.success=ගබඩාව මාරු කිරීම සාර්ථක විය. settings.transfer_abort=මාරු කිරීම අවලංගු කරන්න diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini index 43f071a1f2..034d32454f 100644 --- a/options/locale/locale_sk-SK.ini +++ b/options/locale/locale_sk-SK.ini @@ -1168,7 +1168,7 @@ settings.convert_fork_desc=Tento fork môžete previesť na bežný repozitár. settings.convert_fork_notices_1=Táto operácia skonvertuje fork na bežný repozitár a nedá sa vrátiť späť. settings.convert_fork_confirm=Konvertovať repozitár settings.convert_fork_succeed=Fork bol prevedený na bežný repozitár. -settings.transfer=Previesť vlastníctvo +settings.transfer.title=Previesť vlastníctvo settings.transfer_notices_1=- Ak prenesiete repozitár na užívateľa, stratíte k nemu prístup. settings.transfer_notices_2=- Prístup k repozitáru si ponecháte, ak ho prevediete na organizáciu, ktorú (spolu)vlastníte. settings.transfer_owner=Nový vlastník diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 61190fae34..0e7529774c 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -1288,7 +1288,7 @@ settings.convert_confirm=Konvertera utvecklingskatalog settings.convert_succeed=Speglingen har blivit konverterad till en vanlig utvecklingskatalog. settings.convert_fork=Konvertera till vanlig utvecklingskatalog settings.convert_fork_confirm=Konvertera utvecklingskatalog -settings.transfer=Överför Ägarskap +settings.transfer.title=Överför Ägarskap settings.transfer_desc=Överför denna utvecklingskatalog till en användare eller organisation för vilken du har administratörsrättigheter till. settings.transfer_form_title=Ange utvecklingskatalogens namn för att bekräfta: settings.transfer_notices_1=- Du kommer förlora åtkomst till denna utvecklingskatalog om du för över den till en individuell användare. diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index c2c5385421..02a3a2dc08 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -2094,7 +2094,7 @@ settings.convert_fork_desc=Bu çatalı normal bir depoya dönüştürebilirsiniz settings.convert_fork_notices_1=Bu işlem çatalı normal bir depoya dönüştürür ve geri alınamaz. settings.convert_fork_confirm=Depoyu Dönüştür settings.convert_fork_succeed=Çatal normal bir depoya dönüştürüldü. -settings.transfer=Sahipliği Aktar +settings.transfer.title=Sahipliği Aktar settings.transfer.rejected=Depo aktarımı reddedildi. settings.transfer.success=Depo aktarımı başarıyla tamamlandı. settings.transfer_abort=Aktarımı iptal et diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 137ee205fa..482d27b504 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -1654,7 +1654,7 @@ settings.convert_fork_desc=Ви можете перетворити цей фо settings.convert_fork_notices_1=Ця операція перетворить форк на звичайний репозиторій та не може бути скасованою. settings.convert_fork_confirm=Перетворити репозиторій settings.convert_fork_succeed=Цей форк успішно перетворено на звичайний репозиторій. -settings.transfer=Передати новому власнику +settings.transfer.title=Передати новому власнику settings.transfer.rejected=Перенесення репозиторію відхилено. settings.transfer.success=Перенесення репозиторію виконано. settings.transfer_abort=Скасувати перенесення diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 8bdc11b7b2..af58a3da72 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2167,7 +2167,7 @@ settings.convert_fork_desc=您可以将该镜像仓库转换为普通仓库, settings.convert_fork_notices_1=该操作会将派生仓库转换为普通仓库,但该操作不可逆。 settings.convert_fork_confirm=转换仓库 settings.convert_fork_succeed=此派生仓库已经转换为普通仓库。 -settings.transfer=转让仓库所有权 +settings.transfer.title=转让仓库所有权 settings.transfer.rejected=代码库转移被拒绝。 settings.transfer.success=代码库转移成功。 settings.transfer_abort=取消转移 diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini index adc6f2aeef..4e5be41392 100644 --- a/options/locale/locale_zh-HK.ini +++ b/options/locale/locale_zh-HK.ini @@ -592,7 +592,7 @@ settings.tracker_issue_style.numeric=數字 settings.tracker_issue_style.alphanumeric=字母及數字 settings.danger_zone=危險操作區 settings.new_owner_has_same_repo=新的儲存庫擁有者已經存在同名儲存庫! -settings.transfer=轉移儲存庫所有權 +settings.transfer.title=轉移儲存庫所有權 settings.transfer_owner=新擁有者 settings.delete=刪除本儲存庫 settings.delete_notices_1=- 此操作 不可以 被回滾。 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 44855f480f..0a17b021b1 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -2010,7 +2010,7 @@ settings.convert_fork_desc=您可以將此 fork 轉換成普通儲存庫。此 settings.convert_fork_notices_1=此操作會將此 fork 轉換成普通儲存庫且不可還原。 settings.convert_fork_confirm=轉換儲存庫 settings.convert_fork_succeed=此 fork 已轉換成普通儲存庫。 -settings.transfer=轉移儲存庫所有權 +settings.transfer.title=轉移儲存庫所有權 settings.transfer.rejected=儲存庫轉移被拒絕。 settings.transfer.success=儲存庫已成功轉移。 settings.transfer_abort=取消轉移 diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 979df1f5cf..0c68a7a970 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -439,7 +439,7 @@ {{end}}
-
{{ctx.Locale.Tr "repo.settings.transfer"}}
+
{{ctx.Locale.Tr "repo.settings.transfer.title"}}
{{if .RepoTransfer}} {{ctx.Locale.Tr "repo.settings.transfer_started" .RepoTransfer.Recipient.DisplayName}} @@ -456,7 +456,7 @@ {{else}} - + {{end}}
@@ -584,7 +584,7 @@ {{end}}