From 49625aac60ef78dd799172c75298c0809ecf941d Mon Sep 17 00:00:00 2001 From: Gusted Date: Wed, 2 Apr 2025 16:03:28 +0000 Subject: [PATCH 1/6] [v11.0/forgejo]: fix(i18n): fix several usages of i18n (#7430) **Backport of forgejo/forgejo#7422** - Add new translations, if an existing one couldn't be used. - Use existing translations, if one existed and fit the purpose. - Spotted by the lint-locale-usage tooling by @fogti. (cherry picked from commit bd9366e7fc834d42fd60dbe5391c268f65452db7) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7430 Reviewed-by: 0ko <0ko@noreply.codeberg.org> Co-authored-by: Gusted Co-committed-by: Gusted --- options/locale/locale_en-US.ini | 2 +- options/locale_next/locale_en-US.json | 5 ++++- routers/web/repo/editor.go | 2 +- templates/admin/auth/list.tmpl | 2 +- templates/admin/emails/list.tmpl | 2 +- templates/admin/notice.tmpl | 2 +- templates/admin/org/list.tmpl | 2 +- templates/admin/packages/list.tmpl | 2 +- templates/admin/repo/list.tmpl | 2 +- templates/admin/user/list.tmpl | 2 +- templates/repo/settings/lfs_file.tmpl | 2 +- templates/user/auth/finalize_openid.tmpl | 2 +- 12 files changed, 15 insertions(+), 12 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 2a8c789385..bfdcdb9112 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1436,7 +1436,7 @@ editor.file_is_a_symlink = `"%s" is a symbolic link. Symbolic links cannot be ed editor.filename_is_a_directory = Filename "%s" is already used as a directory name in this repository. editor.file_editing_no_longer_exists = The file being edited, "%s", no longer exists in this repository. 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_changed_while_editing = The file contents have changed since you opened the file. 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 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. diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json index 4f5d102392..4f3c65a68f 100644 --- a/options/locale_next/locale_en-US.json +++ b/options/locale_next/locale_en-US.json @@ -16,5 +16,8 @@ "incorrect_root_url": "This Forgejo instance is configured to be served on \"%s\". You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.", "themes.names.forgejo-auto": "Forgejo (follow system theme)", "themes.names.forgejo-light": "Forgejo light", - "themes.names.forgejo-dark": "Forgejo dark" + "themes.names.forgejo-dark": "Forgejo dark", + "settings.adopt": "Adopt", + "install.invalid_lfs_path": "Unable to create the LFS root at the specified path: %[1]s", + "install.lfs_jwt_secret_failed": "Unable to generate a LFS JWT secret: %[1]s" } diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 77f71fd2b1..5114cc9c05 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -585,7 +585,7 @@ func DeleteFilePost(ctx *context.Context) { ctx.Error(http.StatusInternalServerError, err.Error()) } } else if models.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) { - ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplDeleteFile, &form) + ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplDeleteFile, &form) } else if git.IsErrPushRejected(err) { errPushRej := err.(*git.ErrPushRejected) if len(errPushRej.Message) == 0 { diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl index 9c283fe3d8..0c7138bd68 100644 --- a/templates/admin/auth/list.tmpl +++ b/templates/admin/auth/list.tmpl @@ -31,7 +31,7 @@ {{svg "octicon-pencil"}} {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/admin/emails/list.tmpl b/templates/admin/emails/list.tmpl index 8796794aee..5c30df87af 100644 --- a/templates/admin/emails/list.tmpl +++ b/templates/admin/emails/list.tmpl @@ -67,7 +67,7 @@ {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl index 4f8783dd42..08f0a4f204 100644 --- a/templates/admin/notice.tmpl +++ b/templates/admin/notice.tmpl @@ -25,7 +25,7 @@ {{svg "octicon-note" 16}} {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} {{if .Notices}} diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl index b719d259e0..8c9c198897 100644 --- a/templates/admin/org/list.tmpl +++ b/templates/admin/org/list.tmpl @@ -67,7 +67,7 @@ {{svg "octicon-pencil"}} {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl index f22600a449..5f9965e34c 100644 --- a/templates/admin/packages/list.tmpl +++ b/templates/admin/packages/list.tmpl @@ -75,7 +75,7 @@ {{svg "octicon-trash"}} {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 0422705ea9..7a75ceded7 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -87,7 +87,7 @@ {{svg "octicon-trash"}} {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index f4609edbbf..368e113d24 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -110,7 +110,7 @@ {{else}} - {{ctx.Locale.Tr "no_results_found"}} + {{ctx.Locale.Tr "repo.pulls.no_results"}} {{end}} diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl index 941d09f3e6..3b6b763536 100644 --- a/templates/repo/settings/lfs_file.tmpl +++ b/templates/repo/settings/lfs_file.tmpl @@ -31,7 +31,7 @@ {{ctx.Locale.Tr "repo.audio_not_supported_in_browser"}} {{else if .IsPDFFile}} -
+
{{else}} {{ctx.Locale.Tr "repo.file_view_raw"}} {{end}} diff --git a/templates/user/auth/finalize_openid.tmpl b/templates/user/auth/finalize_openid.tmpl index f84f860b02..372471368f 100644 --- a/templates/user/auth/finalize_openid.tmpl +++ b/templates/user/auth/finalize_openid.tmpl @@ -30,7 +30,7 @@ {{if .ShowRegistrationButton}}
From 52da8aab7ea3e93703991f46f19aa5d88eea1dcc Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Thu, 3 Apr 2025 07:35:20 +0000 Subject: [PATCH 2/6] [v11.0/forgejo] fix(migrations): transfer PR flow information (#7437) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7421 - When migrating a pull requests from a Gitea or Forgejo instance, check if the pull request was created via the AGit flow and transfer that bit of information to the migrated pull request. - Expose this bit of information as the `flow` field for the pull request. - We have to do a horrible Go hack with Gitea's [go-sdk](gitea.com/gitea/go-sdk) to list all pull requests while being able to decode it to a struct that contains the new `Flow` field. The library does not allow you to do this out of the box, so we have to use `go:linkname` to access the private method that allows us to do this. This in turn means we have to do some boilerplate code that the library otherwise would do for us. The better option would be forking, but that would be a hassle of keeping the library in sync. - Resolves forgejo/forgejo#5848 - Unit test added. Co-authored-by: Gusted Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7437 Reviewed-by: Gusted Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- modules/migration/pullrequest.go | 1 + modules/structs/pull.go | 3 +- services/convert/pull.go | 1 + services/migrations/gitea_downloader.go | 41 +++++++++++++++++- services/migrations/gitea_downloader_test.go | 43 +++++++++++++++++++ services/migrations/gitea_sdk_hack.go | 16 +++++++ services/migrations/gitea_uploader.go | 1 + services/migrations/main_test.go | 1 + ...t-test%2Fpulls%3Flimit=50&page=1&state=all | 8 ++++ .../GET_%2Fapi%2Fv1%2Fsettings%2Fapi | 7 +++ .../full_download/GET_%2Fapi%2Fv1%2Fversion | 7 +++ templates/swagger/v1_json.tmpl | 5 +++ 12 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 services/migrations/gitea_sdk_hack.go create mode 100644 services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Frepos%2FGusted%2Fagit-test%2Fpulls%3Flimit=50&page=1&state=all create mode 100644 services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fsettings%2Fapi create mode 100644 services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fversion diff --git a/modules/migration/pullrequest.go b/modules/migration/pullrequest.go index 933348d671..0861ab24f1 100644 --- a/modules/migration/pullrequest.go +++ b/modules/migration/pullrequest.go @@ -34,6 +34,7 @@ type PullRequest struct { Assignees []string IsLocked bool `yaml:"is_locked"` Reactions []*Reaction + Flow int64 ForeignIndex int64 Context DownloaderContext `yaml:"-"` EnsuredSafe bool `yaml:"ensured_safe"` diff --git a/modules/structs/pull.go b/modules/structs/pull.go index ab627666c9..1ce7550e19 100644 --- a/modules/structs/pull.go +++ b/modules/structs/pull.go @@ -57,7 +57,8 @@ type PullRequest struct { // swagger:strfmt date-time Closed *time.Time `json:"closed_at"` - PinOrder int `json:"pin_order"` + PinOrder int `json:"pin_order"` + Flow int64 `json:"flow"` } // PRBranchInfo information about a branch diff --git a/services/convert/pull.go b/services/convert/pull.go index 0cb4070595..ca965a0d18 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -95,6 +95,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u RequestedReviewersTeams: []*api.Team{}, AllowMaintainerEdit: pr.AllowMaintainerEdit, + Flow: int64(pr.Flow), Base: &api.PRBranchInfo{ Name: pr.BaseBranch, diff --git a/services/migrations/gitea_downloader.go b/services/migrations/gitea_downloader.go index 272a7d379a..133cc5c928 100644 --- a/services/migrations/gitea_downloader.go +++ b/services/migrations/gitea_downloader.go @@ -504,6 +504,28 @@ func (g *GiteaDownloader) GetComments(commentable base.Commentable) ([]*base.Com return allComments, true, nil } +type ForgejoPullRequest struct { + gitea_sdk.PullRequest + Flow int64 `json:"flow"` +} + +// Extracted from https://gitea.com/gitea/go-sdk/src/commit/164e3358bc02213954fb4380b821bed80a14824d/gitea/pull.go#L347-L364 +func (g *GiteaDownloader) fixPullHeadSha(pr *ForgejoPullRequest) error { + if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil && pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" { + owner := pr.Base.Repository.Owner.UserName + repo := pr.Base.Repository.Name + refs, _, err := g.client.GetRepoRefs(owner, repo, pr.Head.Ref) + if err != nil { + return err + } + if len(refs) == 0 { + return fmt.Errorf("unable to resolve PR ref %q", pr.Head.Ref) + } + pr.Head.Sha = refs[0].Object.SHA + } + return nil +} + // GetPullRequests returns pull requests according page and perPage func (g *GiteaDownloader) GetPullRequests(page, perPage int) ([]*base.PullRequest, bool, error) { if perPage > g.maxPerPage { @@ -511,16 +533,30 @@ func (g *GiteaDownloader) GetPullRequests(page, perPage int) ([]*base.PullReques } allPRs := make([]*base.PullRequest, 0, perPage) - prs, _, err := g.client.ListRepoPullRequests(g.repoOwner, g.repoName, gitea_sdk.ListPullRequestsOptions{ + prs := make([]*ForgejoPullRequest, 0, perPage) + opt := gitea_sdk.ListPullRequestsOptions{ ListOptions: gitea_sdk.ListOptions{ Page: page, PageSize: perPage, }, State: gitea_sdk.StateAll, - }) + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", url.PathEscape(g.repoOwner), url.PathEscape(g.repoName))) + link.RawQuery = opt.QueryEncode() + _, err := getParsedResponse(g.client, "GET", link.String(), http.Header{"content-type": []string{"application/json"}}, nil, &prs) if err != nil { return nil, false, fmt.Errorf("error while listing pull requests (page: %d, pagesize: %d). Error: %w", page, perPage, err) } + + if g.client.CheckServerVersionConstraint(">= 1.14.0") != nil { + for i := range prs { + if err := g.fixPullHeadSha(prs[i]); err != nil { + return nil, false, fmt.Errorf("error while listing pull requests (page: %d, pagesize: %d). Error: %w", page, perPage, err) + } + } + } + for _, pr := range prs { var milestone string if pr.Milestone != nil { @@ -598,6 +634,7 @@ func (g *GiteaDownloader) GetPullRequests(page, perPage int) ([]*base.PullReques MergeCommitSHA: mergeCommitSHA, IsLocked: pr.IsLocked, PatchURL: pr.PatchURL, + Flow: pr.Flow, Head: base.PullRequestBranch{ Ref: headRef, SHA: headSHA, diff --git a/services/migrations/gitea_downloader_test.go b/services/migrations/gitea_downloader_test.go index b3d49752f3..24c53af023 100644 --- a/services/migrations/gitea_downloader_test.go +++ b/services/migrations/gitea_downloader_test.go @@ -307,3 +307,46 @@ func TestGiteaDownloadRepo(t *testing.T) { }, }, reviews) } + +func TestForgejoDownloadRepo(t *testing.T) { + token := os.Getenv("CODE_FORGEJO_TOKEN") + + fixturePath := "./testdata/code-forgejo-org/full_download" + server := unittest.NewMockWebServer(t, "https://code.forgejo.org", fixturePath, token != "") + defer server.Close() + + downloader, err := NewGiteaDownloader(t.Context(), server.URL, "Gusted/agit-test", "", "", token) + require.NoError(t, err) + require.NotNil(t, downloader) + + prs, _, err := downloader.GetPullRequests(1, 50) + require.NoError(t, err) + assert.Len(t, prs, 1) + + assertPullRequestEqual(t, &base.PullRequest{ + Number: 1, + PosterID: 63, + PosterName: "Gusted", + PosterEmail: "postmaster@gusted.xyz", + Title: "Add extra information", + State: "open", + Created: time.Date(2025, time.April, 1, 20, 28, 45, 0, time.UTC), + Updated: time.Date(2025, time.April, 1, 20, 28, 45, 0, time.UTC), + Base: base.PullRequestBranch{ + CloneURL: "", + Ref: "main", + SHA: "79ebb873a6497c8847141ba9706b3f757196a1e6", + RepoName: "agit-test", + OwnerName: "Gusted", + }, + Head: base.PullRequestBranch{ + CloneURL: server.URL + "/Gusted/agit-test.git", + Ref: "refs/pull/1/head", + SHA: "667e9317ec37b977e6d3d7d43e3440636970563c", + RepoName: "agit-test", + OwnerName: "Gusted", + }, + PatchURL: server.URL + "/Gusted/agit-test/pulls/1.patch", + Flow: 1, + }, prs[0]) +} diff --git a/services/migrations/gitea_sdk_hack.go b/services/migrations/gitea_sdk_hack.go new file mode 100644 index 0000000000..f3959717a8 --- /dev/null +++ b/services/migrations/gitea_sdk_hack.go @@ -0,0 +1,16 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package migrations + +import ( + "io" + "net/http" + + _ "unsafe" // Needed for go:linkname support + + gitea_sdk "code.gitea.io/sdk/gitea" +) + +//go:linkname getParsedResponse code.gitea.io/sdk/gitea.(*Client).getParsedResponse +func getParsedResponse(client *gitea_sdk.Client, method, path string, header http.Header, body io.Reader, obj any) (*gitea_sdk.Response, error) diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 7edaef5557..55adad9685 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -802,6 +802,7 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*issues_model MergeBase: pr.Base.SHA, Index: pr.Number, HasMerged: pr.Merged, + Flow: issues_model.PullRequestFlow(pr.Flow), Issue: &issue, } diff --git a/services/migrations/main_test.go b/services/migrations/main_test.go index 17e6505df2..d543bd6d9c 100644 --- a/services/migrations/main_test.go +++ b/services/migrations/main_test.go @@ -136,6 +136,7 @@ func assertPullRequestEqual(t *testing.T, expected, actual *base.PullRequest) { assert.ElementsMatch(t, expected.Assignees, actual.Assignees) assert.Equal(t, expected.IsLocked, actual.IsLocked) assertReactionsEqual(t, expected.Reactions, actual.Reactions) + assert.Equal(t, expected.Flow, actual.Flow) } func assertPullRequestsEqual(t *testing.T, expected, actual []*base.PullRequest) { diff --git a/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Frepos%2FGusted%2Fagit-test%2Fpulls%3Flimit=50&page=1&state=all b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Frepos%2FGusted%2Fagit-test%2Fpulls%3Flimit=50&page=1&state=all new file mode 100644 index 0000000000..87095d9e24 --- /dev/null +++ b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Frepos%2FGusted%2Fagit-test%2Fpulls%3Flimit=50&page=1&state=all @@ -0,0 +1,8 @@ +Access-Control-Expose-Headers: X-Total-Count +Cache-Control: max-age=0, private, must-revalidate, no-transform +Content-Type: application/json;charset=utf-8 +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Total-Count: 1 + +[{"id":4980,"url":"https://code.forgejo.org/Gusted/agit-test/pulls/1","number":1,"user":{"id":63,"login":"Gusted","login_name":"26734","source_id":1,"full_name":"","email":"postmaster@gusted.xyz","avatar_url":"https://code.forgejo.org/avatars/4ca5ad8bc488630869fdbd2051da61cbed7241c9c066d4e5e1dd36300f887340","html_url":"https://code.forgejo.org/Gusted","language":"en-US","is_admin":false,"last_login":"2025-04-01T16:35:18Z","created":"2023-07-08T13:33:38Z","restricted":false,"active":true,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":2,"following_count":0,"starred_repos_count":0,"username":"Gusted"},"title":"Add extra information","body":"","labels":[],"milestone":null,"assignee":null,"assignees":null,"requested_reviewers":[],"requested_reviewers_teams":[],"state":"open","draft":false,"is_locked":false,"comments":0,"review_comments":0,"additions":0,"deletions":0,"changed_files":0,"html_url":"https://code.forgejo.org/Gusted/agit-test/pulls/1","diff_url":"https://code.forgejo.org/Gusted/agit-test/pulls/1.diff","patch_url":"https://code.forgejo.org/Gusted/agit-test/pulls/1.patch","mergeable":true,"merged":false,"merged_at":null,"merge_commit_sha":null,"merged_by":null,"allow_maintainer_edit":false,"base":{"label":"main","ref":"main","sha":"79ebb873a6497c8847141ba9706b3f757196a1e6","repo_id":1414,"repo":{"id":1414,"owner":{"id":63,"login":"Gusted","login_name":"","source_id":0,"full_name":"","email":"gusted@noreply.code.forgejo.org","avatar_url":"https://code.forgejo.org/avatars/4ca5ad8bc488630869fdbd2051da61cbed7241c9c066d4e5e1dd36300f887340","html_url":"https://code.forgejo.org/Gusted","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2023-07-08T13:33:38Z","restricted":false,"active":false,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":2,"following_count":0,"starred_repos_count":0,"username":"Gusted"},"name":"agit-test","full_name":"Gusted/agit-test","description":"USED FOR FORGEJO UNIT TESTING","empty":false,"private":false,"fork":false,"template":false,"parent":null,"mirror":false,"size":36,"language":"","languages_url":"https://code.forgejo.org/api/v1/repos/Gusted/agit-test/languages","html_url":"https://code.forgejo.org/Gusted/agit-test","url":"https://code.forgejo.org/api/v1/repos/Gusted/agit-test","link":"","ssh_url":"ssh://git@code.forgejo.org/Gusted/agit-test.git","clone_url":"https://code.forgejo.org/Gusted/agit-test.git","original_url":"","website":"","stars_count":0,"forks_count":0,"watchers_count":1,"open_issues_count":0,"open_pr_counter":1,"release_counter":0,"default_branch":"main","archived":false,"created_at":"2025-04-01T20:25:03Z","updated_at":"2025-04-01T20:25:03Z","archived_at":"1970-01-01T00:00:00Z","permissions":{"admin":true,"push":true,"pull":true},"has_issues":true,"internal_tracker":{"enable_time_tracker":true,"allow_only_contributors_to_track_time":true,"enable_issue_dependencies":true},"has_wiki":true,"wiki_branch":"main","globally_editable_wiki":false,"has_pull_requests":true,"has_projects":true,"has_releases":true,"has_packages":true,"has_actions":true,"ignore_whitespace_conflicts":false,"allow_merge_commits":true,"allow_rebase":true,"allow_rebase_explicit":true,"allow_squash_merge":true,"allow_fast_forward_only_merge":true,"allow_rebase_update":true,"default_delete_branch_after_merge":false,"default_merge_style":"merge","default_allow_maintainer_edit":false,"default_update_style":"merge","avatar_url":"","internal":false,"mirror_interval":"","object_format_name":"sha1","mirror_updated":"0001-01-01T00:00:00Z","repo_transfer":null,"topics":null}},"head":{"label":"","ref":"refs/pull/1/head","sha":"667e9317ec37b977e6d3d7d43e3440636970563c","repo_id":1414,"repo":{"id":1414,"owner":{"id":63,"login":"Gusted","login_name":"","source_id":0,"full_name":"","email":"gusted@noreply.code.forgejo.org","avatar_url":"https://code.forgejo.org/avatars/4ca5ad8bc488630869fdbd2051da61cbed7241c9c066d4e5e1dd36300f887340","html_url":"https://code.forgejo.org/Gusted","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2023-07-08T13:33:38Z","restricted":false,"active":false,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":2,"following_count":0,"starred_repos_count":0,"username":"Gusted"},"name":"agit-test","full_name":"Gusted/agit-test","description":"USED FOR FORGEJO UNIT TESTING","empty":false,"private":false,"fork":false,"template":false,"parent":null,"mirror":false,"size":36,"language":"","languages_url":"https://code.forgejo.org/api/v1/repos/Gusted/agit-test/languages","html_url":"https://code.forgejo.org/Gusted/agit-test","url":"https://code.forgejo.org/api/v1/repos/Gusted/agit-test","link":"","ssh_url":"ssh://git@code.forgejo.org/Gusted/agit-test.git","clone_url":"https://code.forgejo.org/Gusted/agit-test.git","original_url":"","website":"","stars_count":0,"forks_count":0,"watchers_count":1,"open_issues_count":0,"open_pr_counter":1,"release_counter":0,"default_branch":"main","archived":false,"created_at":"2025-04-01T20:25:03Z","updated_at":"2025-04-01T20:25:03Z","archived_at":"1970-01-01T00:00:00Z","permissions":{"admin":true,"push":true,"pull":true},"has_issues":true,"internal_tracker":{"enable_time_tracker":true,"allow_only_contributors_to_track_time":true,"enable_issue_dependencies":true},"has_wiki":true,"wiki_branch":"main","globally_editable_wiki":false,"has_pull_requests":true,"has_projects":true,"has_releases":true,"has_packages":true,"has_actions":true,"ignore_whitespace_conflicts":false,"allow_merge_commits":true,"allow_rebase":true,"allow_rebase_explicit":true,"allow_squash_merge":true,"allow_fast_forward_only_merge":true,"allow_rebase_update":true,"default_delete_branch_after_merge":false,"default_merge_style":"merge","default_allow_maintainer_edit":false,"default_update_style":"merge","avatar_url":"","internal":false,"mirror_interval":"","object_format_name":"sha1","mirror_updated":"0001-01-01T00:00:00Z","repo_transfer":null,"topics":null}},"merge_base":"79ebb873a6497c8847141ba9706b3f757196a1e6","due_date":null,"created_at":"2025-04-01T20:28:45Z","updated_at":"2025-04-01T20:28:45Z","closed_at":null,"pin_order":0,"flow":1}] diff --git a/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fsettings%2Fapi b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fsettings%2Fapi new file mode 100644 index 0000000000..11c4e7b8ba --- /dev/null +++ b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fsettings%2Fapi @@ -0,0 +1,7 @@ +Content-Length: 117 +Cache-Control: max-age=0, private, must-revalidate, no-transform +Content-Type: application/json;charset=utf-8 +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN + +{"max_response_items":50,"default_paging_num":30,"default_git_trees_per_page":1000,"default_max_blob_size":10485760} diff --git a/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fversion b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fversion new file mode 100644 index 0000000000..411ed84e24 --- /dev/null +++ b/services/migrations/testdata/code-forgejo-org/full_download/GET_%2Fapi%2Fv1%2Fversion @@ -0,0 +1,7 @@ +Cache-Control: max-age=0, private, must-revalidate, no-transform +Content-Type: application/json;charset=utf-8 +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +Content-Length: 53 + +{"version":"11.0.0-dev-617-1d1e0ced3e+gitea-1.22.0"} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 400c71af1a..a16deb61a8 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -26133,6 +26133,11 @@ "format": "date-time", "x-go-name": "Deadline" }, + "flow": { + "type": "integer", + "format": "int64", + "x-go-name": "Flow" + }, "head": { "$ref": "#/definitions/PRBranchInfo" }, From 7bc4f4976e3d56e1562bcf6864fc8a04e2891d1d Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Thu, 3 Apr 2025 16:58:13 +0000 Subject: [PATCH 3/6] [v11.0/forgejo] fix: handle viewing a submodule entry (#7450) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7261 - When trying to view a submodule directory via the normal `/src/branch/` path, generate a redirect link to the submodule location. - Resolves forgejo/forgejo#5267 Co-authored-by: Gnarwhal Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7450 Reviewed-by: Gusted Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- routers/web/repo/view.go | 10 +++++++++- tests/integration/repo_test.go | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index b7a7a3f042..bea002f690 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -1044,7 +1044,15 @@ func renderHomeCode(ctx *context.Context) { return } - if entry.IsDir() { + if entry.IsSubModule() { + subModuleURL, err := ctx.Repo.Commit.GetSubModule(entry.Name()) + if err != nil { + HandleGitError(ctx, "Repo.Commit.GetSubModule", err) + return + } + subModuleFile := git.NewSubModuleFile(ctx.Repo.Commit, subModuleURL, entry.ID.String()) + ctx.Redirect(subModuleFile.RefURL(setting.AppURL, ctx.Repo.Repository.FullName(), setting.SSH.Domain)) + } else if entry.IsDir() { renderDirectory(ctx) } else { renderFile(ctx, entry) diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go index f8961443c5..308942e4fe 100644 --- a/tests/integration/repo_test.go +++ b/tests/integration/repo_test.go @@ -1423,6 +1423,12 @@ func TestRepoSubmoduleView(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) htmlDoc.AssertElement(t, fmt.Sprintf(`tr[data-entryname="repo1"] a[href="%s"]`, u.JoinPath("/user2/repo1").String()), true) + + // Check that a link to the submodule returns a redirect and that the redirect link is correct. + req = NewRequest(t, "GET", "/"+repo.FullName()+"/src/branch/"+repo.DefaultBranch+"/repo1") + resp = MakeRequest(t, req, http.StatusSeeOther) + + assert.Equal(t, u.JoinPath("/user2/repo1").String(), resp.Header().Get("Location")) }) } From 6bcdfd6efbb9aa24129086d9fb19f51797338cce Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Fri, 11 Apr 2025 13:08:56 +0000 Subject: [PATCH 4/6] [v11.0/forgejo] fix: package_blob.has_blake2b may be null (#7521) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7520 - When looking for an existing blob, has_blake2b will be null when it was created prior to v26 migration in v11, when the field was introduced. - Add unit test and minimal refactoring to load fixtures. The AddFixture function should not be where it currently is because it cannot be used by some packages (circular import). But that's a refactor that needs to be elsewhere for backporting purposes. Fixes https://codeberg.org/forgejo/forgejo/issues/7519 When the fix is missing, the test fails like so: ``` --- FAIL: TestPackagesGetOrInsertBlob (0.03s) --- FAIL: TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database (0.00s) package_blob_test.go:55: Error Trace: /home/earl-warren/software/forgejo/models/packages/package_blob_test.go:55 Error: Not equal: expected: true actual : false Test: TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database package_blob_test.go:56: Error Trace: /home/earl-warren/software/forgejo/models/packages/package_blob_test.go:56 Error: Expected value not to be nil. Test: TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database ``` ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [x] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/.md` to be be used for the release notes instead of the title. Co-authored-by: Earl Warren Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7521 Reviewed-by: Earl Warren Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- .../package_blob.yml | 17 +++++ models/packages/main_test.go | 31 +++++++++ models/packages/package_blob.go | 21 +++--- models/packages/package_blob_test.go | 64 +++++++++++++++++++ models/packages/package_test.go | 9 --- 5 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 models/fixtures/TestPackagesGetOrInsertBlob/package_blob.yml create mode 100644 models/packages/main_test.go create mode 100644 models/packages/package_blob_test.go diff --git a/models/fixtures/TestPackagesGetOrInsertBlob/package_blob.yml b/models/fixtures/TestPackagesGetOrInsertBlob/package_blob.yml new file mode 100644 index 0000000000..ec90787c43 --- /dev/null +++ b/models/fixtures/TestPackagesGetOrInsertBlob/package_blob.yml @@ -0,0 +1,17 @@ +- + id: 1 + size: 10 + hash_md5: HASHMD5_1 + hash_sha1: HASHSHA1_1 + hash_sha256: HASHSHA256_1 + hash_sha512: HASHSHA512_1 + hash_blake2b: HASHBLAKE2B_1 + created_unix: 946687980 +- + id: 2 + size: 20 + hash_md5: HASHMD5_2 + hash_sha1: HASHSHA1_2 + hash_sha256: HASHSHA256_2 + hash_sha512: HASHSHA512_2 + created_unix: 946687980 diff --git a/models/packages/main_test.go b/models/packages/main_test.go new file mode 100644 index 0000000000..8114461502 --- /dev/null +++ b/models/packages/main_test.go @@ -0,0 +1,31 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package packages + +import ( + "path/filepath" + "testing" + + "forgejo.org/models/unittest" + "forgejo.org/modules/setting" + + _ "forgejo.org/models" + _ "forgejo.org/models/actions" + _ "forgejo.org/models/activities" + _ "forgejo.org/models/forgefed" +) + +func AddFixtures(dirs ...string) func() { + return unittest.OverrideFixtures( + unittest.FixturesOptions{ + Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"), + Base: setting.AppWorkPath, + Dirs: dirs, + }, + ) +} + +func TestMain(m *testing.M) { + unittest.MainTest(m) +} diff --git a/models/packages/package_blob.go b/models/packages/package_blob.go index e86f652540..0de4434ef8 100644 --- a/models/packages/package_blob.go +++ b/models/packages/package_blob.go @@ -44,14 +44,19 @@ func GetOrInsertBlob(ctx context.Context, pb *PackageBlob) (*PackageBlob, bool, existing := &PackageBlob{} - has, err := e.Where(builder.Eq{ - "size": pb.Size, - "hash_md5": pb.HashMD5, - "hash_sha1": pb.HashSHA1, - "hash_sha256": pb.HashSHA256, - "hash_sha512": pb.HashSHA512, - "hash_blake2b": pb.HashBlake2b, - }).Get(existing) + has, err := e.Where(builder.And( + builder.Eq{ + "size": pb.Size, + "hash_md5": pb.HashMD5, + "hash_sha1": pb.HashSHA1, + "hash_sha256": pb.HashSHA256, + "hash_sha512": pb.HashSHA512, + }, + builder.Or( + builder.Eq{"hash_blake2b": pb.HashBlake2b}, + builder.IsNull{"hash_blake2b"}, + ), + )).Get(existing) if err != nil { return nil, false, err } diff --git a/models/packages/package_blob_test.go b/models/packages/package_blob_test.go new file mode 100644 index 0000000000..7de6aab15a --- /dev/null +++ b/models/packages/package_blob_test.go @@ -0,0 +1,64 @@ +// Copyright 2025 The Forgejo Authors. +// SPDX-License-Identifier: GPL-3.0-or-later + +package packages + +import ( + "testing" + + "forgejo.org/models/unittest" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPackagesGetOrInsertBlob(t *testing.T) { + defer AddFixtures("models/fixtures/TestPackagesGetOrInsertBlob/")() + require.NoError(t, unittest.PrepareTestDatabase()) + + blake2bIsSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 1}) + blake2bNotSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 2}) + + blake2bSetToRandom := *blake2bNotSet + blake2bSetToRandom.HashBlake2b = "SOMETHING RANDOM" + + for _, testCase := range []struct { + name string + exists bool + packageBlob *PackageBlob + }{ + { + name: "exists and blake2b is not null in the database", + exists: true, + packageBlob: blake2bIsSet, + }, + { + name: "exists and blake2b is null in the database", + exists: true, + packageBlob: &blake2bSetToRandom, + }, + { + name: "does not exists", + exists: false, + packageBlob: &PackageBlob{ + Size: 30, + HashMD5: "HASHMD5_3", + HashSHA1: "HASHSHA1_3", + HashSHA256: "HASHSHA256_3", + HashSHA512: "HASHSHA512_3", + HashBlake2b: "HASHBLAKE2B_3", + }, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + found, has, _ := GetOrInsertBlob(t.Context(), testCase.packageBlob) + assert.Equal(t, testCase.exists, has) + require.NotNil(t, found) + if testCase.exists { + assert.Equal(t, found.ID, testCase.packageBlob.ID) + } else { + unittest.BeanExists(t, &PackageBlob{ID: found.ID}) + } + }) + } +} diff --git a/models/packages/package_test.go b/models/packages/package_test.go index ab2d49c94c..3c1ec413fd 100644 --- a/models/packages/package_test.go +++ b/models/packages/package_test.go @@ -13,18 +13,9 @@ import ( "forgejo.org/models/unittest" user_model "forgejo.org/models/user" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - "github.com/stretchr/testify/require" ) -func TestMain(m *testing.M) { - unittest.MainTest(m) -} - func prepareExamplePackage(t *testing.T) *packages_model.Package { require.NoError(t, unittest.PrepareTestDatabase()) From a4e8594643ade4fb728a363e81ec0d276c7e39ea Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Tue, 15 Apr 2025 06:24:49 +0000 Subject: [PATCH 5/6] [v11.0/forgejo] fix(UI): i18n: improve naming (#7542) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7539 ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). - [x] I will test the UI with a screenshot. And attach it in a comment when test has passed. ### Documentation - [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. https://codeberg.org/forgejo/docs/pulls/1145 - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [x] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/.md` to be be used for the release notes instead of the title. ### Reason for the PR? The reason is to correct the naming of the lang in the UI. It was discussed in the matrix chat and requested by @0ko. https://matrix.to/#/!UJgSZwuZLRYXEOyjPb:matrix.org/$TbMlNm9L1P9gHFwJYZ3vTIPBKtUHyaoQVEDdzfTQIxI?via=matrix.org&via=envs.net&via=mozilla.org Co-authored-by: tacaly Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7542 Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- custom/conf/app.example.ini | 2 +- modules/setting/i18n.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 79793ad47f..f8fa95bbab 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -2408,7 +2408,7 @@ LEVEL = Info ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The first locale will be used as the default if user browser's language doesn't match any locale in the list. ;LANGS = en-US,zh-CN,zh-HK,zh-TW,da,de-DE,nds,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg,it-IT,fi-FI,fil,eo,tr-TR,cs-CZ,sl,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID -;NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Danish,Deutsch,Plattdüütsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Filipino,Esperanto,Türkçe,Čeština,Slovenščina,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia +;NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Dansk,Deutsch,Plattdüütsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Filipino,Esperanto,Türkçe,Čeština,Slovenščina,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/modules/setting/i18n.go b/modules/setting/i18n.go index c2e5822cf0..a400cf844c 100644 --- a/modules/setting/i18n.go +++ b/modules/setting/i18n.go @@ -9,7 +9,7 @@ var defaultI18nLangNames = []string{ "zh-CN", "简体中文", "zh-HK", "繁體中文(香港)", "zh-TW", "繁體中文(台灣)", - "da", "Danish", + "da", "Dansk", "de-DE", "Deutsch", "nds", "Plattdüütsch", "fr-FR", "Français", From 64d885422217b9499476d713e963c61f932c4815 Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Tue, 15 Apr 2025 07:40:53 +0000 Subject: [PATCH 6/6] [v11.0/forgejo] fix: match PackageBlob.HashBlake2b definition and migration (#7544) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/7543 If not a migration will show a warning: `[W] Table public.package_blob column hash_blake2b db type is VARCHAR(255), struct type is CHAR(128)` Co-authored-by: Earl Warren Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7544 Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- models/forgejo_migrations/v26.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/forgejo_migrations/v26.go b/models/forgejo_migrations/v26.go index 5efe48a302..3292d93ffd 100644 --- a/models/forgejo_migrations/v26.go +++ b/models/forgejo_migrations/v26.go @@ -7,8 +7,8 @@ import "xorm.io/xorm" func AddHashBlake2bToPackageBlob(x *xorm.Engine) error { type PackageBlob struct { - ID int64 `xorm:"pk autoincr"` - HashBlake2b string + ID int64 `xorm:"pk autoincr"` + HashBlake2b string `xorm:"hash_blake2b char(128) UNIQUE(blake2b) INDEX"` } return x.Sync(&PackageBlob{}) }