From dcd3a631288686a95cedbd4aa9cce245e896825d Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Wed, 26 Jul 2023 14:04:01 +0800 Subject: [PATCH 01/21] Move web JSON functions to web context and simplify code (#26132) The JSONRedirect/JSONOK/JSONError functions were put into "Base" context incorrectly, it would cause abuse. Actually, they are for "web context" only, so, move them to the correct place. And by the way, use them to simplify old code: +75 -196 --- modules/context/base.go | 12 ------- modules/context/context.go | 12 +++++++ routers/web/admin/auths.go | 8 ++--- routers/web/admin/config.go | 4 +-- routers/web/admin/hooks.go | 4 +-- routers/web/admin/packages.go | 4 +-- routers/web/admin/repos.go | 4 +-- routers/web/admin/stacktrace.go | 4 +-- routers/web/auth/webauthn.go | 2 +- routers/web/org/members.go | 12 ++----- routers/web/org/org_labels.go | 4 +-- routers/web/org/projects.go | 32 +++++-------------- routers/web/org/setting.go | 4 +-- routers/web/org/teams.go | 8 ++--- routers/web/repo/branch.go | 4 +-- routers/web/repo/issue.go | 12 ++----- routers/web/repo/issue_label.go | 8 ++--- routers/web/repo/milestone.go | 4 +-- routers/web/repo/projects.go | 32 +++++-------------- routers/web/repo/pull.go | 4 +-- routers/web/repo/pull_review.go | 4 +-- routers/web/repo/release.go | 8 ++--- routers/web/repo/setting/collaboration.go | 8 ++--- routers/web/repo/setting/deploy_key.go | 4 +-- routers/web/repo/setting/protected_branch.go | 20 +++--------- routers/web/repo/setting/webhook.go | 4 +-- routers/web/repo/wiki.go | 4 +-- routers/web/shared/actions/runners.go | 9 ++---- routers/web/user/setting/account.go | 4 +-- routers/web/user/setting/applications.go | 4 +-- routers/web/user/setting/keys.go | 4 +-- routers/web/user/setting/oauth2_common.go | 4 +-- routers/web/user/setting/security/openid.go | 4 +-- routers/web/user/setting/security/security.go | 4 +-- routers/web/user/setting/security/webauthn.go | 4 +-- routers/web/user/setting/webhooks.go | 4 +-- 36 files changed, 75 insertions(+), 196 deletions(-) diff --git a/modules/context/base.go b/modules/context/base.go index 8566ef7861bae..83e5a214f8b3c 100644 --- a/modules/context/base.go +++ b/modules/context/base.go @@ -136,18 +136,6 @@ func (b *Base) JSON(status int, content any) { } } -func (b *Base) JSONRedirect(redirect string) { - b.JSON(http.StatusOK, map[string]any{"redirect": redirect}) -} - -func (b *Base) JSONOK() { - b.JSON(http.StatusOK, map[string]any{"ok": true}) // this is only a dummy response, frontend seldom uses it -} - -func (b *Base) JSONError(msg string) { - b.JSON(http.StatusBadRequest, map[string]any{"errorMessage": msg}) -} - // RemoteAddr returns the client machine ip address func (b *Base) RemoteAddr() string { return b.Req.RemoteAddr diff --git a/modules/context/context.go b/modules/context/context.go index 47a04c989c81f..de0518a1d27c4 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -226,3 +226,15 @@ func (ctx *Context) GetErrMsg() string { } return msg } + +func (ctx *Context) JSONRedirect(redirect string) { + ctx.JSON(http.StatusOK, map[string]any{"redirect": redirect}) +} + +func (ctx *Context) JSONOK() { + ctx.JSON(http.StatusOK, map[string]any{"ok": true}) // this is only a dummy response, frontend seldom uses it +} + +func (ctx *Context) JSONError(msg string) { + ctx.JSON(http.StatusBadRequest, map[string]any{"errorMessage": msg}) +} diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index adde26f0b56e1..b743d1b0a55b4 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -454,15 +454,11 @@ func DeleteAuthSource(ctx *context.Context) { } else { ctx.Flash.Error(fmt.Sprintf("auth_service.DeleteSource: %v", err)) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/auths/" + url.PathEscape(ctx.Params(":authid")), - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/auths/" + url.PathEscape(ctx.Params(":authid"))) return } log.Trace("Authentication deleted by admin(%s): %d", ctx.Doer.Name, source.ID) ctx.Flash.Success(ctx.Tr("admin.auths.deletion_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/auths", - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/auths") } diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index ba0d862645198..c70a2d1c95125 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -179,9 +179,7 @@ func Config(ctx *context.Context) { func ChangeConfig(ctx *context.Context) { key := strings.TrimSpace(ctx.FormString("key")) if key == "" { - ctx.JSON(http.StatusOK, map[string]string{ - "redirect": ctx.Req.URL.String(), - }) + ctx.JSONRedirect(ctx.Req.URL.String()) return } value := ctx.FormString("value") diff --git a/routers/web/admin/hooks.go b/routers/web/admin/hooks.go index 2e4122c9048bf..cd8cc29cdfbc0 100644 --- a/routers/web/admin/hooks.go +++ b/routers/web/admin/hooks.go @@ -67,7 +67,5 @@ func DeleteDefaultOrSystemWebhook(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/hooks", - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/hooks") } diff --git a/routers/web/admin/packages.go b/routers/web/admin/packages.go index 731a1d6ac2f27..8e4b8a373ef52 100644 --- a/routers/web/admin/packages.go +++ b/routers/web/admin/packages.go @@ -97,7 +97,5 @@ func DeletePackageVersion(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")), - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type"))) } diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go index 2ea8a2ad35819..d1d0abca02545 100644 --- a/routers/web/admin/repos.go +++ b/routers/web/admin/repos.go @@ -58,9 +58,7 @@ func DeleteRepo(ctx *context.Context) { log.Trace("Repository deleted: %s", repo.FullName()) ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/repos?page=" + url.QueryEscape(ctx.FormString("page")) + "&sort=" + url.QueryEscape(ctx.FormString("sort")), - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/repos?page=" + url.QueryEscape(ctx.FormString("page")) + "&sort=" + url.QueryEscape(ctx.FormString("sort"))) } // UnadoptedRepos lists the unadopted repositories diff --git a/routers/web/admin/stacktrace.go b/routers/web/admin/stacktrace.go index f2d2be481a6a3..b603fb59a26d7 100644 --- a/routers/web/admin/stacktrace.go +++ b/routers/web/admin/stacktrace.go @@ -42,7 +42,5 @@ func Stacktrace(ctx *context.Context) { func StacktraceCancel(ctx *context.Context) { pid := ctx.Params("pid") process.GetManager().Cancel(process.IDType(pid)) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/admin/monitor/stacktrace", - }) + ctx.JSONRedirect(setting.AppSubURL + "/admin/monitor/stacktrace") } diff --git a/routers/web/auth/webauthn.go b/routers/web/auth/webauthn.go index e369f860811fa..013e11eacce0a 100644 --- a/routers/web/auth/webauthn.go +++ b/routers/web/auth/webauthn.go @@ -154,5 +154,5 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) { } _ = ctx.Session.Delete("twofaUid") - ctx.JSON(http.StatusOK, map[string]string{"redirect": redirect}) + ctx.JSONRedirect(redirect) } diff --git a/routers/web/org/members.go b/routers/web/org/members.go index 8da0f0b9fd012..fae8b48128be8 100644 --- a/routers/web/org/members.go +++ b/routers/web/org/members.go @@ -101,9 +101,7 @@ func MembersAction(ctx *context.Context) { err = models.RemoveOrgUser(org.ID, uid) if organization.IsErrLastOrgOwner(err) { ctx.Flash.Error(ctx.Tr("form.last_org_owner")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/members", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/members") return } case "leave": @@ -115,9 +113,7 @@ func MembersAction(ctx *context.Context) { }) } else if organization.IsErrLastOrgOwner(err) { ctx.Flash.Error(ctx.Tr("form.last_org_owner")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/members", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/members") } else { log.Error("RemoveOrgUser(%d,%d): %v", org.ID, ctx.Doer.ID, err) } @@ -138,7 +134,5 @@ func MembersAction(ctx *context.Context) { redirect = setting.AppSubURL + "/" } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": redirect, - }) + ctx.JSONRedirect(redirect) } diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index 08566637a8780..a9f9e963d4970 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -90,9 +90,7 @@ func DeleteLabel(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.issues.label_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/settings/labels", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/labels") } // InitializeLabels init labels for an organization diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 50bb5591e57aa..ea6e7dff48ffd 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -219,9 +219,7 @@ func DeleteProject(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.ContextUser.HomeLink() + "/-/projects", - }) + ctx.JSONRedirect(ctx.ContextUser.HomeLink() + "/-/projects") } // RenderEditProject allows a project to be edited @@ -449,9 +447,7 @@ func UpdateIssueProject(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // DeleteProjectBoard allows for the deletion of a project board @@ -497,9 +493,7 @@ func DeleteProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // AddBoardToProjectPost allows a new board to be added to a project. @@ -526,9 +520,7 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // CheckProjectBoardChangePermissions check permission @@ -594,9 +586,7 @@ func EditProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // SetDefaultProjectBoard set default board for uncategorized issues/pulls @@ -611,9 +601,7 @@ func SetDefaultProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // UnsetDefaultProjectBoard unset default board for uncategorized issues/pulls @@ -628,9 +616,7 @@ func UnsetDefaultProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // MoveIssues moves or keeps issues in a column and sorts them inside that column @@ -730,7 +716,5 @@ func MoveIssues(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index f63b2e9f064e0..5ae61c79befe2 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -219,9 +219,7 @@ func DeleteWebhook(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/settings/hooks", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/settings/hooks") } // Labels render organization labels page diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index aefadaf809e82..196d3e9bf0403 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -256,9 +256,7 @@ func TeamsRepoAction(ctx *context.Context) { } if action == "addall" || action == "removeall" { - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories") return } ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(ctx.Org.Team.LowerName) + "/repositories") @@ -530,9 +528,7 @@ func DeleteTeam(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("org.teams.delete_team_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Org.OrgLink + "/teams", - }) + ctx.JSONRedirect(ctx.Org.OrgLink + "/teams") } // TeamInvite renders the team invite page diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index 999104d7872dd..d71d555bc2b54 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -162,9 +162,7 @@ func RestoreBranchPost(ctx *context.Context) { } func redirect(ctx *context.Context) { - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/branches?page=" + url.QueryEscape(ctx.FormString("page")), - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/branches?page=" + url.QueryEscape(ctx.FormString("page"))) } // CreateBranch creates new branch in repository diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index b7d159d158081..f5cec5a323bbc 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2221,9 +2221,7 @@ func UpdateIssueMilestone(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // UpdateIssueAssignee change issue's or pull's assignee @@ -2267,9 +2265,7 @@ func UpdateIssueAssignee(ctx *context.Context) { } } } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // UpdatePullReviewRequest add or remove review request @@ -2392,9 +2388,7 @@ func UpdatePullReviewRequest(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // SearchIssues searches for issues across the repositories that the user has access to diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index af5db83bd5d24..5d326bab58084 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -157,9 +157,7 @@ func DeleteLabel(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.issues.label_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/labels", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/labels") } // UpdateIssueLabel change issue's labels @@ -226,7 +224,5 @@ func UpdateIssueLabel(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index 7b20cd98482bc..ad355ce5d7d92 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -255,9 +255,7 @@ func DeleteMilestone(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.milestones.deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/milestones", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/milestones") } // MilestoneIssuesAndPulls lists all the issues and pull requests of the milestone diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 1574c90c02ed0..b8662e0605562 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -203,9 +203,7 @@ func DeleteProject(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/projects", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/projects") } // RenderEditProject allows a project to be edited @@ -397,9 +395,7 @@ func UpdateIssueProject(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // DeleteProjectBoard allows for the deletion of a project board @@ -452,9 +448,7 @@ func DeleteProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // AddBoardToProjectPost allows a new board to be added to a project. @@ -487,9 +481,7 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } func checkProjectBoardChangePermissions(ctx *context.Context) (*project_model.Project, *project_model.Board) { @@ -561,9 +553,7 @@ func EditProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // SetDefaultProjectBoard set default board for uncategorized issues/pulls @@ -578,9 +568,7 @@ func SetDefaultProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // UnSetDefaultProjectBoard unset default board for uncategorized issues/pulls @@ -595,9 +583,7 @@ func UnSetDefaultProjectBoard(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } // MoveIssues moves or keeps issues in a column and sorts them inside that column @@ -699,7 +685,5 @@ func MoveIssues(ctx *context.Context) { return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 5290e25d463f3..237e53413f767 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1423,9 +1423,7 @@ func CleanUpPullRequest(ctx *context.Context) { } defer func() { - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": issue.Link(), - }) + ctx.JSONRedirect(issue.Link()) }() // Check if branch has no new commits diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index f7c962d1ae8f2..c2271750c4d1d 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -156,9 +156,7 @@ func UpdateResolveConversation(ctx *context.Context) { renderConversation(ctx, comment) return } - ctx.JSON(http.StatusOK, map[string]any{ - "ok": true, - }) + ctx.JSONOK() } func renderConversation(ctx *context.Context, comment *issues_model.Comment) { diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 3d991384e56a7..957cf56972ce3 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -628,13 +628,9 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) { } if isDelTag { - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/tags", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/tags") return } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/releases", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/releases") } diff --git a/routers/web/repo/setting/collaboration.go b/routers/web/repo/setting/collaboration.go index 8f2d30686207c..b708422cbd26c 100644 --- a/routers/web/repo/setting/collaboration.go +++ b/routers/web/repo/setting/collaboration.go @@ -133,9 +133,7 @@ func DeleteCollaboration(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/settings/collaboration", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/collaboration") } // AddTeamPost response for adding a team to a repository @@ -204,7 +202,5 @@ func DeleteTeam(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("repo.settings.remove_team_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/settings/collaboration", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/collaboration") } diff --git a/routers/web/repo/setting/deploy_key.go b/routers/web/repo/setting/deploy_key.go index d08c51f5e5c3b..577706d45441b 100644 --- a/routers/web/repo/setting/deploy_key.go +++ b/routers/web/repo/setting/deploy_key.go @@ -105,7 +105,5 @@ func DeleteDeployKey(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/settings/keys", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/keys") } diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index cf59e747d84f1..5bfdb8f515ba6 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -318,41 +318,31 @@ func DeleteProtectedBranchRulePost(ctx *context.Context) { ruleID := ctx.ParamsInt64("id") if ruleID <= 0 { ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID))) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink), - }) + ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) return } rule, err := git_model.GetProtectedBranchRuleByID(ctx, ctx.Repo.Repository.ID, ruleID) if err != nil { ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID))) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink), - }) + ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) return } if rule == nil { ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID))) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink), - }) + ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) return } if err := git_model.DeleteProtectedBranch(ctx, ctx.Repo.Repository.ID, ruleID); err != nil { ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", rule.RuleName)) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink), - }) + ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) return } ctx.Flash.Success(ctx.Tr("repo.settings.remove_protected_branch_success", rule.RuleName)) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink), - }) + ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) } // RenameBranchPost responses for rename a branch diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go index d85d5c8b07ff6..5c4e1d47d09ad 100644 --- a/routers/web/repo/setting/webhook.go +++ b/routers/web/repo/setting/webhook.go @@ -729,7 +729,5 @@ func DeleteWebhook(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/settings/hooks", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings/hooks") } diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 4773e25c70664..e3c187c33bfdb 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -790,7 +790,5 @@ func DeleteWikiPagePost(ctx *context.Context) { notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(wikiName)) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": ctx.Repo.RepoLink + "/wiki/", - }) + ctx.JSONRedirect(ctx.Repo.RepoLink + "/wiki/") } diff --git a/routers/web/shared/actions/runners.go b/routers/web/shared/actions/runners.go index 21e5a90d8f206..eb84cc4a2ef48 100644 --- a/routers/web/shared/actions/runners.go +++ b/routers/web/shared/actions/runners.go @@ -5,7 +5,6 @@ package actions import ( "errors" - "net/http" actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" @@ -160,9 +159,7 @@ func RunnerDeletePost(ctx *context.Context, runnerID int64, log.Warn("DeleteRunnerPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL) ctx.Flash.Warning(ctx.Tr("actions.runners.delete_runner_failed")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": failedRedirectTo, - }) + ctx.JSONRedirect(failedRedirectTo) return } @@ -170,7 +167,5 @@ func RunnerDeletePost(ctx *context.Context, runnerID int64, ctx.Flash.Success(ctx.Tr("actions.runners.delete_runner_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": successRedirectTo, - }) + ctx.JSONRedirect(successRedirectTo) } diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go index 532f0d8e39126..ecb846e91bb38 100644 --- a/routers/web/user/setting/account.go +++ b/routers/web/user/setting/account.go @@ -227,9 +227,7 @@ func DeleteEmail(ctx *context.Context) { log.Trace("Email address deleted: %s", ctx.Doer.Name) ctx.Flash.Success(ctx.Tr("settings.email_deletion_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/account", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/account") } // DeleteAccount render user suicide page and response for delete user himself diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go index 81209376960d5..088aba38b6925 100644 --- a/routers/web/user/setting/applications.go +++ b/routers/web/user/setting/applications.go @@ -83,9 +83,7 @@ func DeleteApplication(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("settings.delete_token_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/applications", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/applications") } func loadApplicationsData(ctx *context.Context) { diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go index d9412cae7cae8..2336c04bbed22 100644 --- a/routers/web/user/setting/keys.go +++ b/routers/web/user/setting/keys.go @@ -256,9 +256,7 @@ func DeleteKey(ctx *context.Context) { ctx.Flash.Warning("Function not implemented") ctx.Redirect(setting.AppSubURL + "/user/settings/keys") } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/keys", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/keys") } func loadKeysData(ctx *context.Context) { diff --git a/routers/web/user/setting/oauth2_common.go b/routers/web/user/setting/oauth2_common.go index 923ce4b4367b9..641cc1fd9ffae 100644 --- a/routers/web/user/setting/oauth2_common.go +++ b/routers/web/user/setting/oauth2_common.go @@ -138,7 +138,7 @@ func (oa *OAuth2CommonHandlers) DeleteApp(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("settings.remove_oauth2_application_success")) - ctx.JSON(http.StatusOK, map[string]any{"redirect": oa.BasePathList}) + ctx.JSONRedirect(oa.BasePathList) } // RevokeGrant revokes the grant @@ -149,5 +149,5 @@ func (oa *OAuth2CommonHandlers) RevokeGrant(ctx *context.Context) { } ctx.Flash.Success(ctx.Tr("settings.revoke_oauth2_grant_success")) - ctx.JSON(http.StatusOK, map[string]any{"redirect": oa.BasePathList}) + ctx.JSONRedirect(oa.BasePathList) } diff --git a/routers/web/user/setting/security/openid.go b/routers/web/user/setting/security/openid.go index f4133f3916026..b5509f570fd6a 100644 --- a/routers/web/user/setting/security/openid.go +++ b/routers/web/user/setting/security/openid.go @@ -112,9 +112,7 @@ func DeleteOpenID(ctx *context.Context) { log.Trace("OpenID address deleted: %s", ctx.Doer.Name) ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success")) - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/security", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/security") } // ToggleOpenIDVisibility response for toggle visibility of user's openid diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go index cc5f817a9d428..dae9bf950dce7 100644 --- a/routers/web/user/setting/security/security.go +++ b/routers/web/user/setting/security/security.go @@ -48,9 +48,7 @@ func DeleteAccountLink(ctx *context.Context) { } } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/security", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/security") } func loadSecurityData(ctx *context.Context) { diff --git a/routers/web/user/setting/security/webauthn.go b/routers/web/user/setting/security/webauthn.go index 89ac184a47e7c..990e506d6fdf7 100644 --- a/routers/web/user/setting/security/webauthn.go +++ b/routers/web/user/setting/security/webauthn.go @@ -116,7 +116,5 @@ func WebauthnDelete(ctx *context.Context) { ctx.ServerError("GetWebAuthnCredentialByID", err) return } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/security", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/security") } diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go index db03d7b1ed20d..04092461fde39 100644 --- a/routers/web/user/setting/webhooks.go +++ b/routers/web/user/setting/webhooks.go @@ -42,7 +42,5 @@ func DeleteWebhook(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) } - ctx.JSON(http.StatusOK, map[string]any{ - "redirect": setting.AppSubURL + "/user/settings/hooks", - }) + ctx.JSONRedirect(setting.AppSubURL + "/user/settings/hooks") } From f3ed0ef692a2c73fdf491d86f27fad33da742174 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 26 Jul 2023 15:02:53 +0800 Subject: [PATCH 02/21] Fix bugs in LFS meta garbage collection (#26122) This PR - Fix #26093. Replace `time.Time` with `timeutil.TimeStamp` - Fix #26135. Add missing `xorm:"extends"` to `CountLFSMetaObject` for LFS meta object query - Add a unit test for LFS meta object garbage collection --- models/git/lfs.go | 9 +++-- services/repository/lfs.go | 5 +-- services/repository/lfs_test.go | 64 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 services/repository/lfs_test.go diff --git a/models/git/lfs.go b/models/git/lfs.go index 7d3da72a9410c..e8192f92c5c68 100644 --- a/models/git/lfs.go +++ b/models/git/lfs.go @@ -6,7 +6,6 @@ package git import ( "context" "fmt" - "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" @@ -370,8 +369,8 @@ func IterateRepositoryIDsWithLFSMetaObjects(ctx context.Context, f func(ctx cont // IterateLFSMetaObjectsForRepoOptions provides options for IterateLFSMetaObjectsForRepo type IterateLFSMetaObjectsForRepoOptions struct { - OlderThan time.Time - UpdatedLessRecentlyThan time.Time + OlderThan timeutil.TimeStamp + UpdatedLessRecentlyThan timeutil.TimeStamp OrderByUpdated bool LoopFunctionAlwaysUpdates bool } @@ -382,8 +381,8 @@ func IterateLFSMetaObjectsForRepo(ctx context.Context, repoID int64, f func(cont batchSize := setting.Database.IterateBufferSize engine := db.GetEngine(ctx) type CountLFSMetaObject struct { - Count int64 - LFSMetaObject + Count int64 + LFSMetaObject `xorm:"extends"` } id := int64(0) diff --git a/services/repository/lfs.go b/services/repository/lfs.go index 0bd4d53a5c4da..8e654b6f13bcd 100644 --- a/services/repository/lfs.go +++ b/services/repository/lfs.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" ) // GarbageCollectLFSMetaObjectsOptions provides options for GarbageCollectLFSMetaObjects function @@ -120,8 +121,8 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R // // It is likely that a week is potentially excessive but it should definitely be enough that any // unassociated LFS object is genuinely unassociated. - OlderThan: opts.OlderThan, - UpdatedLessRecentlyThan: opts.UpdatedLessRecentlyThan, + OlderThan: timeutil.TimeStamp(opts.OlderThan.Unix()), + UpdatedLessRecentlyThan: timeutil.TimeStamp(opts.UpdatedLessRecentlyThan.Unix()), OrderByUpdated: true, LoopFunctionAlwaysUpdates: true, }) diff --git a/services/repository/lfs_test.go b/services/repository/lfs_test.go new file mode 100644 index 0000000000000..e88befdfefe96 --- /dev/null +++ b/services/repository/lfs_test.go @@ -0,0 +1,64 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "bytes" + "context" + "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" + "code.gitea.io/gitea/modules/lfs" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" + + "github.com/stretchr/testify/assert" +) + +func TestGarbageCollectLFSMetaObjects(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + setting.LFS.StartServer = true + err := storage.Init() + assert.NoError(t, err) + + repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1") + assert.NoError(t, err) + + // add lfs object + lfsContent := []byte("gitea1") + lfsOid := storeObjectInRepo(t, repo.ID, &lfsContent) + + // gc + err = GarbageCollectLFSMetaObjects(context.Background(), GarbageCollectLFSMetaObjectsOptions{ + AutoFix: true, + OlderThan: time.Now().Add(7 * 24 * time.Hour).Add(5 * 24 * time.Hour), + UpdatedLessRecentlyThan: time.Now().Add(7 * 24 * time.Hour).Add(3 * 24 * time.Hour), + }) + assert.NoError(t, err) + + // lfs meta has been deleted + _, err = git_model.GetLFSMetaObjectByOid(db.DefaultContext, repo.ID, lfsOid) + assert.ErrorIs(t, err, git_model.ErrLFSObjectNotExist) +} + +func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string { + pointer, err := lfs.GeneratePointer(bytes.NewReader(*content)) + assert.NoError(t, err) + + _, err = git_model.NewLFSMetaObject(db.DefaultContext, &git_model.LFSMetaObject{Pointer: pointer, RepositoryID: repositoryID}) + assert.NoError(t, err) + contentStore := lfs.NewContentStore() + exist, err := contentStore.Exists(pointer) + assert.NoError(t, err) + if !exist { + err := contentStore.Put(pointer, bytes.NewReader(*content)) + assert.NoError(t, err) + } + return pointer.Oid +} From df9afe3aa8ccc1a91858bb8a2d4120cfb603e001 Mon Sep 17 00:00:00 2001 From: Upstream8022 <105393306+Upstream8022@users.noreply.github.com> Date: Wed, 26 Jul 2023 15:28:44 +0800 Subject: [PATCH 03/21] Update Chinese documents (#26139) Update part of the documents, translate English to Chinese. --- .../content/installation/from-source.zh-cn.md | 136 +++++++++++++----- .../installation/on-cloud-provider.zh-cn.md | 10 ++ .../installation/upgrade-from-gitea.zh-cn.md | 6 +- 3 files changed, 113 insertions(+), 39 deletions(-) diff --git a/docs/content/installation/from-source.zh-cn.md b/docs/content/installation/from-source.zh-cn.md index c1f00904d4feb..260ccbee3c627 100644 --- a/docs/content/installation/from-source.zh-cn.md +++ b/docs/content/installation/from-source.zh-cn.md @@ -17,94 +17,158 @@ menu: # 使用源代码安装 -首先你需要安装Golang,关于Golang的安装,参见[官方文档](https://golang.google.cn/doc/install)。 +你需要 [安装Go](https://golang.google.cn/doc/install) 并正确设置Go环境。特别的,建议设置`$GOPATH`环境变量,并将 Go 的二进制目录或目录`${GOPATH//://bin:}/bin`添加到`$PATH`中。请参阅 Go 百科上关于 [GOPATH](https://github.com/golang/go/wiki/GOPATH) 的词条。 -其次你需要[安装Node.js](https://nodejs.org/zh-cn/download/),Node.js 和 npm 将用于构建 Gitea 前端。 +接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-cn/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。 + +**注意**:当执行需要外部工具的 make 任务(如`make misspell-check`)时,Gitea 将根据需要自动下载和构建这些工具。为了能够实现这个目的,你必须将`"$GOPATH/bin"`目录添加到可执行路径中。如果没有将 Go 的二进制目录添加到可执行路径中,你需要自行解决产生的问题。 + +**注意2**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 ## 下载 -你需要获取Gitea的源码,最方便的方式是使用 `git` 命令。执行以下命令: +首先,我们需要获取源码。由于引入了 Go 模块,最简单的方法是直接使用 Git,因为我们不再需要在 GOPATH 内构建 Gitea。 -``` +```bash git clone https://github.com/go-gitea/gitea -cd gitea ``` -然后你可以选择编译和安装的版本,当前你有多个选择。如果你想编译 `main` 版本,你可以直接跳到 [编译](#编译) 部分,这是我们的开发分支,虽然也很稳定但不建议您在正式产品中使用。 +(之前的版本中建议使用 `go get`,但现在不再需要。) + +你可以选择编译和安装的版本,当前有多个选择。`main` 分支代表当前的开发版本。如果你想编译 `main` 版本,你可以直接跳到 [构建](#构建) 部分。 -如果你想编译最新稳定分支,你可以执行以下命令签出源码: +如果你想编译带有标签的发行版本,可以使用以下命令签出: ```bash git branch -a git checkout v@version@ ``` -最后,你也可以直接使用标签版本如 `v@version@`。你可以执行以下命令列出可用的版本并选择某个版本签出: +要验证一个拉取请求(Pull Request, PR),要先启用新的分支(其中 `xyz` 是 PR 的 ID;例如,对于 [#2663](https://github.com/go-gitea/gitea/pull/2663),ID是 `2663 `): + +```bash +git fetch origin pull/xyz/head:pr-xyz +``` + +要以指定发行版本(如 v@version@ )的源代码来构建 Gitea,可执行以下命令列出可用的版本并选择某个版本签出。 +使用以下命令列出可用的版本: ```bash git tag -l -git checkout v@version@ +git checkout v@version@ # or git checkout pr-xyz ``` -## 编译 +## 构建 -要从源代码进行编译,以下依赖程序必须事先安装好: +要从源代码进行构建,系统必须预先安装以下程序: -- `go` @minGoVersion@ 或以上版本, 详见[这里](https://golang.google.cn/doc/install) -- `node` @minNodeVersion@ 或以上版本,并且安装 `npm`, 详见[这里](https://nodejs.org/zh-cn/download/) -- `make`, 详见[这里](/zh-cn/hacking-on-gitea/) +- `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://golang.org/dl/) +- `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-cn/download/) +- `make`, 请参阅 [这里](/zh-cn/hacking-on-gitea/) -各种可用的 [make 任务](https://github.com/go-gitea/gitea/blob/main/Makefile) -可以用来使编译过程更方便。 +为了尽可能简化编译过程,提供了各种 [make任务](https://github.com/go-gitea/gitea/blob/main/Makefile)。 -按照您的编译需求,以下 tags 可以使用: +根据你的构建需求,以下 tags 可以使用: -- `bindata`: 这个编译选项将会把运行Gitea所需的所有外部资源都打包到可执行文件中,这样部署将非常简单因为除了可执行程序将不再需要任何其他文件。 -- `sqlite sqlite_unlock_notify`: 这个编译选项将启用SQLite3数据库的支持,建议只在少数人使用时使用这个模式。 -- `pam`: 这个编译选项将会启用 PAM (Linux Pluggable Authentication Modules) 认证,如果你使用这一认证模式的话需要开启这个选项。 +- `bindata`: 构建一个单一的整体二进制文件,包含所有资源。适用于构建生产环境版本。 +- `sqlite sqlite_unlock_notify`: 启用对 [SQLite3](https://sqlite.org/) 数据库的支持。仅建议在少数人使用时使用这个模式。 +- `pam`: 启用对 PAM( Linux 可插拔认证模块)的支持。可用于对本地用户进行身份验证或扩展身份验证到 PAM 可用的方法。 +- `gogit`:(实验性功能)使用 go-git 变体的 Git 命令。 -使用 bindata 可以打包资源文件到二进制可以使开发和测试更容易,你可以根据自己的需求决定是否打包资源文件。 -要包含资源文件,请使用 `bindata` tag: +将所有资源(JS/CSS/模板等)打包到二进制文件中。在生产环境部署时,使用`bindata`构建标签是必需的。在开发/测试 Gitea 或能够明确分离资源时,可以不用`bindata`。 + +要包含所有资源,请使用 `bindata` 标签: ```bash TAGS="bindata" make build ``` -默认的发布版本中的编译选项是: `TAGS="bindata sqlite sqlite_unlock_notify"`。以下为推荐的编译方式: +在我们的持续集成系统的默认发行版中,构建标签为:`TAGS="bindata sqlite sqlite_unlock_notify"`。因此,从源码构建的最简单、推荐方式是: ```bash TAGS="bindata sqlite sqlite_unlock_notify" make build ``` +`build`目标分为两个子目标: + +- `make backend` 需要 [Go @minGoVersion@](https://golang.google.cn/doc/install) 或更高版本。 +- `make frontend` 需要 [Node.js @minNodeVersion@](https://nodejs.org/zh-cn/download/) 或更高版本。 + +如果存在预构建的前端文件,可以仅构建后端: + +```bash +TAGS="bindata" make backend +``` + +在开发构建中,默认启用 Webpack 源映射,在生产构建中禁用。可以通过设置`ENABLE_SOURCEMAP=true`环境变量来启用它们。 + ## 测试 -在执行了以上步骤之后,你将会获得 `gitea` 的二进制文件,在你复制到部署的机器之前可以先测试一下。在命令行执行完后,你可以 `Ctrl + C` 关掉程序。 +按照上述步骤完成后,工作目录中将会有一个`gitea`二进制文件。可以从该目录进行测试,或将其移动到带有测试数据的目录中。当手动从命令行启动 Gitea 时,可以通过按下`Ctrl + C`来停止程序。 ```bash ./gitea web ``` +## 更改默认路径 + +Gitea 将从`CustomPath`中查找许多信息。默认的,这会在运行 Gitea 时当前工作目录下的`custom/`目录中(译者案:即`$PATH_TO_YOUR_GITEA$/custom/`)。它还将在`$(CustomPath)/conf/app.ini`中查找其配置文件`CustomConf`,并将当前工作目录用作一些可配置值的相对基本路径`AppWorkPath`。最后,静态文件将从默认为 `AppWorkPath`的`StaticRootPath`提供。 + +尽管在开发时这些值很有用,但可能与下游用户的偏好冲突。 + +一种选择是使用脚本文件来隐藏`gitea`二进制文件,并在运行Gitea之前创建适当的环境。然而,在构建时,可以使用`make`的`LDFLAGS`环境变量来更改这些默认值。适当的设置如下: + +- 要设置`CustomPath`,请使用`LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.CustomPath=custom-path\""` +- 对于`CustomConf`,应该使用`-X \"code.gitea.io/gitea/modules/setting.CustomConf=conf.ini\"` +- 对于`AppWorkPath`,应该使用`-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=working-path\"` +- 对于`StaticRootPath`,应该使用`-X \"code.gitea.io/gitea/modules/setting.StaticRootPath=static-root-path\"` +- 要更改默认的 PID 文件位置,请使用`-X \"code.gitea.io/gitea/cmd.PIDFile=/run/gitea.pid\"` + +将这些字符串与其前导的`-X`添加到`LDFLAGS`变量中,并像上面那样使用适当的`TAGS`运行`make build`。 + +运行`gitea help`将允许您查看配置的`gitea`设置。 + ## 交叉编译 -Go 编译器支持交叉编译到不同的目标架构。有关 Go 支持的目标架构列表,请参见 [Optional environment variables](https://go.dev/doc/install/source#environment)。 +`go`编译器工具链支持将代码交叉编译到不同的目标架构上。请参考[`GOOS`和`GOARCH`环境变量](https://golang.org/doc/install/source#environment) 以获取支持的目标列表。如果您想为性能较弱的系统(如树莓派)构建 Gitea,交叉编译非常有用。 -交叉构建适用于 Linux ARM64 的 Gitea: +要使用构建标签(`TAGS`)进行交叉编译Gitea,您还需要一个 C 交叉编译器,该编译器的目标架构与`GOOS`和`GOARCH`变量选择的架构相同。例如,要为 Linux ARM64(`GOOS=linux`和`GOARCH=arm64`)进行交叉编译,您需要`aarch64-unknown-linux-gnu-gcc`交叉编译器。这是因为 Gitea 构建标签使用了`cgo`的外部函数接口(FFI)。 -```bash +在没有任何标签的情况下,交叉编译的 Gitea 为 Linux ARM64 版本: + +``` GOOS=linux GOARCH=arm64 make build ``` -交叉构建适用于 Linux ARM64 的 Gitea,并且带上 Gitea 发行版采用的编译选项: +要交叉编译 Linux ARM64 下的Gitea,这是推荐的构建标签: -```bash +``` CC=aarch64-unknown-linux-gnu-gcc GOOS=linux GOARCH=arm64 TAGS="bindata sqlite sqlite_unlock_notify" make build ``` -## 使用Linux与Zig编译或交叉编译 +根据您的目标架构,适当替换`CC`、`GOOS`和`GOARCH`。 + +有时您需要构建一个静态编译的镜像。为此,您需要添加以下内容: + +``` +LDFLAGS="-linkmode external -extldflags '-static' $LDFLAGS" TAGS="netgo osusergo $TAGS" make build +``` + +这可以与上述的`CC`、`GOOS`和`GOARCH`结合使用。 + +### 添加 bash/zsh 自动补全(从 1.19 版本起) + +在[`contrib/autocompletion/bash_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/bash_autocomplete)中可以找到一个启用 bash 自动补全的脚本。您可以根据需要进行修改,并在您的 `.bashrc` 中使用 `source` 命令加载该脚本,或者将其复制到 `/usr/share/bash-completion/completions/gitea`。 + +类似地,可以在[`contrib/autocompletion/zsh_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/zsh_autocomplete)中找到一个用于 zsh 自动补全的脚本。您可以将其复制到 `/usr/share/zsh/_gitea`,或者在您的 `.zshrc` 中使用 `source` 命令加载该脚本。 + +可能需要你根据具体情况进一步改进这些脚本。 + +## 在 Linux 上使用 Zig 进行编译或交叉编译 -按照[Getting Started of Zig](https://ziglang.org/learn/getting-started/#installing-zig)来安装zig。 +请按照 [Zig 的入门指南](https://ziglang.org/learn/getting-started/#installing-zig) 安装 Zig。 -- 编译(Linux ➝ Linux) +- 编译 (Linux ➝ Linux) ```sh CC="zig cc -target x86_64-linux-gnu" \ @@ -117,7 +181,7 @@ TAGS="bindata sqlite sqlite_unlock_notify" \ make build ``` -- 交叉编译(Linux ➝ Windows) +- 交叉编译 (Linux ➝ Windows) ```sh CC="zig cc -target x86_64-windows-gnu" \ @@ -129,11 +193,11 @@ TAGS="bindata sqlite sqlite_unlock_notify" \ make build ``` -## 使用Windows与Zig编译或交叉编译 +## 在 Windows 上使用 Zig 进行编译或交叉编译 使用`GIT BASH`编译。 -- 编译(Windows ➝ Windows) +- 编译 (Windows ➝ Windows) ```sh CC="zig cc -target x86_64-windows-gnu" \ @@ -145,7 +209,7 @@ TAGS="bindata sqlite sqlite_unlock_notify" \ make build ``` -- 交叉编译(Windows ➝ Linux) +- 交叉编译 (Windows ➝ Linux) ```sh CC="zig cc -target x86_64-linux-gnu" \ diff --git a/docs/content/installation/on-cloud-provider.zh-cn.md b/docs/content/installation/on-cloud-provider.zh-cn.md index 7a2f3709ca139..7b9a7bdf4047e 100644 --- a/docs/content/installation/on-cloud-provider.zh-cn.md +++ b/docs/content/installation/on-cloud-provider.zh-cn.md @@ -51,3 +51,13 @@ Gitea 可以在 [Vultr](https://www.vultr.com) 的市场中被找到。 [alwaysdata](https://www.alwaysdata.com/) 将 Gitea 作为其市场中的一个 droplet. 要将 Gitea 部署到 alwaysdata, 请参考 [alwaysdata Marketplace](https://www.alwaysdata.com/en/marketplace/gitea/). + +## Exoscale + +[Exoscale](https://www.exoscale.com/) 在其市场中提供由 [Glasskube](https://glasskube.eu/) 管理的 Gitea。 + +Exoscale 是一家欧洲的云服务提供商。 + +该软件包通过开源的 [Glasskube Kubernetes Operator](https://github.com/glasskube/operator) 进行维护和更新。 + +要在 Exoscale 上部署 Gitea,请参考 [Exoscale Marketplace](https://www.exoscale.com/marketplace/listing/glasskube-gitea/)。 diff --git a/docs/content/installation/upgrade-from-gitea.zh-cn.md b/docs/content/installation/upgrade-from-gitea.zh-cn.md index 8c919e15f327e..c0ad8d551a1a6 100644 --- a/docs/content/installation/upgrade-from-gitea.zh-cn.md +++ b/docs/content/installation/upgrade-from-gitea.zh-cn.md @@ -39,7 +39,7 @@ Gitea 会保留首二位版本号相同的版本的兼容性 (`a.b.x` -> `a.b.y` | 1.4.0 | 1.4.1 | ✅ | | 1.4.1 | 1.4.0 | ⚠️ 不建议,后果自负!尽管数据库结构可能不会变更,让它可以正常工作。我们强烈建议降级前进行完全的备份。 | | 1.4.x | 1.5.y | ✅ 数据库会被自动升级。你可以直接从 1.4.x 升级到最新的 1.5.y。 | -| 1.5.y | 1.4.x | ❌ 数据库已被升级且不可被旧版 Gitea 利用,使用备份来进行降级。 | +| 1.5.y | 1.4.x | ❌ 数据库已被升级且无法用于旧版本Gitea,使用备份来进行降级。 | **因为你不能基于升级后的数据库运行旧版 Gitea,所以你应该在数据库升级前完成数据备份。** @@ -60,7 +60,7 @@ Gitea 会保留首二位版本号相同的版本的兼容性 (`a.b.x` -> `a.b.y` * `docker pull` 拉取 Gitea 的最新发布版。 * 停止运行中的实例,备份数据。 -* 使用 `docker` 或 `docker-compose` 启动更新的 Gitea Docker 容器. +* 使用 `docker` 或 `docker-compose` 启动较新的 Gitea Docker 容器. ## 从包升级 @@ -82,6 +82,6 @@ Gitea 会保留首二位版本号相同的版本的兼容性 (`a.b.x` -> `a.b.y` Gitea 的模板结构与变量可能会随着各个版本的发布发生变化,如果你使用了自定义模板, 你得注意你的模板与你使用的 Gitea 版本的兼容性。 -如果自定义模板与 Gitea 版本不兼容,你可能会得到: +如果自定义模板与 Gitea 版本不兼容,你可能会遇到: `50x` 服务器错误,页面元素丢失或故障,莫名其妙的页面布局,等等… 移除或更新不兼容的模板,Gitea Web 才可以正常工作。 From 13359581df51a25ff9f7492419206a9b6e2edbc4 Mon Sep 17 00:00:00 2001 From: caicandong <50507092+CaiCandong@users.noreply.github.com> Date: Wed, 26 Jul 2023 16:52:07 +0800 Subject: [PATCH 04/21] refactor improve NoBetterThan (#26126) - The `NoBetterThan` function can only handle comparisons between "pending," "success," "error," and "failure." For any other comparison, we directly return false. This prevents logic errors like the one in #26121. - The callers of the `NoBetterThan` function should also avoid making incomparable calls. --------- Co-authored-by: yp05327 <576951401@qq.com> Co-authored-by: puni9869 <80308335+puni9869@users.noreply.github.com> --- modules/structs/commit_status.go | 23 +++- modules/structs/commit_status_test.go | 174 ++++++++++++++++++++++++++ services/convert/status.go | 2 +- templates/swagger/v1_json.tmpl | 2 +- 4 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 modules/structs/commit_status_test.go diff --git a/modules/structs/commit_status.go b/modules/structs/commit_status.go index ff31f2d2ac3de..de1d8fa566cd0 100644 --- a/modules/structs/commit_status.go +++ b/modules/structs/commit_status.go @@ -4,7 +4,7 @@ package structs // CommitStatusState holds the state of a CommitStatus -// It can be "pending", "success", "error", "failure", and "warning" +// It can be "pending", "success", "error" and "failure" type CommitStatusState string const ( @@ -18,14 +18,25 @@ const ( CommitStatusFailure CommitStatusState = "failure" ) +var commitStatusPriorities = map[CommitStatusState]int{ + CommitStatusError: 0, + CommitStatusFailure: 1, + CommitStatusPending: 2, + CommitStatusSuccess: 3, +} + // NoBetterThan returns true if this State is no better than the given State +// This function only handles the states defined in CommitStatusPriorities func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool { - commitStatusPriorities := map[CommitStatusState]int{ - CommitStatusError: 0, - CommitStatusFailure: 1, - CommitStatusPending: 2, - CommitStatusSuccess: 3, + // NoBetterThan only handles the 4 states above + if _, exist := commitStatusPriorities[css]; !exist { + return false } + + if _, exist := commitStatusPriorities[css2]; !exist { + return false + } + return commitStatusPriorities[css] <= commitStatusPriorities[css2] } diff --git a/modules/structs/commit_status_test.go b/modules/structs/commit_status_test.go new file mode 100644 index 0000000000000..f06808534c408 --- /dev/null +++ b/modules/structs/commit_status_test.go @@ -0,0 +1,174 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +import ( + "testing" +) + +func TestNoBetterThan(t *testing.T) { + type args struct { + css CommitStatusState + css2 CommitStatusState + } + var unExpectedState CommitStatusState + tests := []struct { + name string + args args + want bool + }{ + { + name: "success is no better than success", + args: args{ + css: CommitStatusSuccess, + css2: CommitStatusSuccess, + }, + want: true, + }, + { + name: "success is no better than pending", + args: args{ + css: CommitStatusSuccess, + css2: CommitStatusPending, + }, + want: false, + }, + { + name: "success is no better than failure", + args: args{ + css: CommitStatusSuccess, + css2: CommitStatusFailure, + }, + want: false, + }, + { + name: "success is no better than error", + args: args{ + css: CommitStatusSuccess, + css2: CommitStatusError, + }, + want: false, + }, + { + name: "pending is no better than success", + args: args{ + css: CommitStatusPending, + css2: CommitStatusSuccess, + }, + want: true, + }, + { + name: "pending is no better than pending", + args: args{ + css: CommitStatusPending, + css2: CommitStatusPending, + }, + want: true, + }, + { + name: "pending is no better than failure", + args: args{ + css: CommitStatusPending, + css2: CommitStatusFailure, + }, + want: false, + }, + { + name: "pending is no better than error", + args: args{ + css: CommitStatusPending, + css2: CommitStatusError, + }, + want: false, + }, + { + name: "failure is no better than success", + args: args{ + css: CommitStatusFailure, + css2: CommitStatusSuccess, + }, + want: true, + }, + { + name: "failure is no better than pending", + args: args{ + css: CommitStatusFailure, + css2: CommitStatusPending, + }, + want: true, + }, + { + name: "failure is no better than failure", + args: args{ + css: CommitStatusFailure, + css2: CommitStatusFailure, + }, + want: true, + }, + { + name: "failure is no better than error", + args: args{ + css: CommitStatusFailure, + css2: CommitStatusError, + }, + want: false, + }, + { + name: "error is no better than success", + args: args{ + css: CommitStatusError, + css2: CommitStatusSuccess, + }, + want: true, + }, + { + name: "error is no better than pending", + args: args{ + css: CommitStatusError, + css2: CommitStatusPending, + }, + want: true, + }, + { + name: "error is no better than failure", + args: args{ + css: CommitStatusError, + css2: CommitStatusFailure, + }, + want: true, + }, + { + name: "error is no better than error", + args: args{ + css: CommitStatusError, + css2: CommitStatusError, + }, + want: true, + }, + { + name: "unExpectedState is no better than success", + args: args{ + css: unExpectedState, + css2: CommitStatusSuccess, + }, + want: false, + }, + { + name: "unExpectedState is no better than unExpectedState", + args: args{ + css: unExpectedState, + css2: unExpectedState, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.args.css.NoBetterThan(tt.args.css2) + if result != tt.want { + t.Errorf("NoBetterThan() = %v, want %v", result, tt.want) + } + }) + } +} diff --git a/services/convert/status.go b/services/convert/status.go index c7b6450e272d3..6cef63c1cdadf 100644 --- a/services/convert/status.go +++ b/services/convert/status.go @@ -48,7 +48,7 @@ func ToCombinedStatus(ctx context.Context, statuses []*git_model.CommitStatus, r retStatus.Statuses = make([]*api.CommitStatus, 0, len(statuses)) for _, status := range statuses { retStatus.Statuses = append(retStatus.Statuses, ToCommitStatus(ctx, status)) - if status.State.NoBetterThan(retStatus.State) { + if retStatus.State == "" || status.State.NoBetterThan(retStatus.State) { retStatus.State = status.State } } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 7cb9bac95d38d..10ad8f555caf4 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -16514,7 +16514,7 @@ "x-go-package": "code.gitea.io/gitea/modules/structs" }, "CommitStatusState": { - "description": "CommitStatusState holds the state of a CommitStatus\nIt can be \"pending\", \"success\", \"error\", \"failure\", and \"warning\"", + "description": "CommitStatusState holds the state of a CommitStatus\nIt can be \"pending\", \"success\", \"error\" and \"failure\"", "type": "string", "x-go-package": "code.gitea.io/gitea/modules/structs" }, From a5e09a5595a05098e5f2ce55b5ba78fc7c5cdb77 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 26 Jul 2023 17:46:59 +0800 Subject: [PATCH 05/21] Fix UI regression of asciinema player (#26159) It was caused by updating `asciinema-player`, the upstream changed the CSS class prefix: `https://github.com/asciinema/asciinema-player/commit/40505e479e8ba6833f178a3b7e85503c72491614`
Before: image
After: image
--- web_src/css/markup/asciicast.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/css/markup/asciicast.css b/web_src/css/markup/asciicast.css index a52b2ae12e9dc..89696bc710581 100644 --- a/web_src/css/markup/asciicast.css +++ b/web_src/css/markup/asciicast.css @@ -3,6 +3,6 @@ height: auto; } -.asciinema-terminal { +.ap-terminal { overflow: hidden !important; } From f2cc4daf60c906b2e1b67bac0cbe4fb7a7558bde Mon Sep 17 00:00:00 2001 From: caicandong <50507092+CaiCandong@users.noreply.github.com> Date: Wed, 26 Jul 2023 18:22:56 +0800 Subject: [PATCH 06/21] Doc update swagger doc for POST /orgs/{org}/teams (#26155) close #26111 --- modules/structs/org_team.go | 4 ++-- templates/swagger/v1_json.tmpl | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/modules/structs/org_team.go b/modules/structs/org_team.go index 95db0debadca4..78dc4abaefd32 100644 --- a/modules/structs/org_team.go +++ b/modules/structs/org_team.go @@ -29,10 +29,10 @@ type CreateTeamOption struct { IncludesAllRepositories bool `json:"includes_all_repositories"` // enum: read,write,admin Permission string `json:"permission"` - // example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"] + // example: ["repo.actions","repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.ext_wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"] // Deprecated: This variable should be replaced by UnitsMap and will be dropped in later versions. Units []string `json:"units"` - // example: {"repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"} + // example: {"repo.actions","repo.packages","repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"} UnitsMap map[string]string `json:"units_map"` CanCreateOrgRepo bool `json:"can_create_org_repo"` } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 10ad8f555caf4..8cf5332bafc48 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -17483,10 +17483,12 @@ }, "x-go-name": "Units", "example": [ + "repo.actions", "repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", + "repo.ext_wiki", "repo.pulls", "repo.releases", "repo.projects", @@ -17499,16 +17501,7 @@ "type": "string" }, "x-go-name": "UnitsMap", - "example": { - "repo.code": "read", - "repo.ext_issues": "none", - "repo.ext_wiki": "none", - "repo.issues": "write", - "repo.projects": "none", - "repo.pulls": "owner", - "repo.releases": "none", - "repo.wiki": "admin" - } + "example": "{\"repo.actions\",\"repo.packages\",\"repo.code\":\"read\",\"repo.issues\":\"write\",\"repo.ext_issues\":\"none\",\"repo.wiki\":\"admin\",\"repo.pulls\":\"owner\",\"repo.releases\":\"none\",\"repo.projects\":\"none\",\"repo.ext_wiki\":\"none\"}" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" From f9e5d980bc06c23f81873e245bc75e98dfcbf0bc Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Wed, 26 Jul 2023 20:26:17 +0900 Subject: [PATCH 07/21] Fix wrong branch name in rename branch modal (#26146) Before: ![image](https://github.com/go-gitea/gitea/assets/18380374/b4dc68e8-b85b-4097-a432-940e291ac582) After: ![image](https://github.com/go-gitea/gitea/assets/18380374/7e692dd2-6b8b-4ba5-a251-ae4b9b917492) --- templates/repo/branch/list.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index 297427eeebd55..b32e8cace7748 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -56,7 +56,7 @@
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index 6768bcb5137f0..ef9d0654566f5 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -70,7 +70,7 @@ {{end}} {{if IsMultilineCommitMessage .Message}} - + {{end}} {{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses "root" $}} {{if IsMultilineCommitMessage .Message}} diff --git a/templates/repo/commits_list_small.tmpl b/templates/repo/commits_list_small.tmpl index 6bbc19529f942..57c9fd17ef775 100644 --- a/templates/repo/commits_list_small.tmpl +++ b/templates/repo/commits_list_small.tmpl @@ -40,7 +40,7 @@ {{RenderCommitMessageLinkSubject $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.Link|Escape) $commitLink $.comment.Issue.PullRequest.BaseRepo.ComposeMetas}} {{if IsMultilineCommitMessage .Message}} - + {{end}} {{if IsMultilineCommitMessage .Message}}
{{RenderCommitBody $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.Link|Escape) $.comment.Issue.PullRequest.BaseRepo.ComposeMetas}}
diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl index 13b4d3d3d322f..3eabf9f181e57 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -28,7 +28,7 @@ {{$commitLink:= printf "%s/commit/%s" .RepoLink (PathEscape .LatestCommit.ID.String)}} {{RenderCommitMessageLinkSubject $.Context .LatestCommit.Message $.RepoLink $commitLink $.Repository.ComposeMetas}} {{if IsMultilineCommitMessage .LatestCommit.Message}} - +
{{RenderCommitBody $.Context .LatestCommit.Message $.RepoLink $.Repository.ComposeMetas}}
{{end}}
diff --git a/web_src/js/features/repo-commit.js b/web_src/js/features/repo-commit.js index 7e4e40806b6c1..7240bf398aec6 100644 --- a/web_src/js/features/repo-commit.js +++ b/web_src/js/features/repo-commit.js @@ -5,7 +5,7 @@ import {toggleElem} from '../utils/dom.js'; const {csrfToken} = window.config; export function initRepoEllipsisButton() { - $('.ellipsis-button').on('click', function (e) { + $('.js-toggle-commit-body').on('click', function (e) { e.preventDefault(); const expanded = $(this).attr('aria-expanded') === 'true'; toggleElem($(this).parent().find('.commit-body')); diff --git a/web_src/js/features/repo-diff-commit.js b/web_src/js/features/repo-diff-commit.js new file mode 100644 index 0000000000000..968f318e63d5d --- /dev/null +++ b/web_src/js/features/repo-diff-commit.js @@ -0,0 +1,52 @@ +import {hideElem, showElem, toggleElem} from '../utils/dom.js'; + +async function loadBranchesAndTags(area, loadingButton) { + loadingButton.classList.add('disabled'); + try { + const res = await fetch(loadingButton.getAttribute('data-fetch-url')); + const data = await res.json(); + hideElem(loadingButton); + addTags(area, data.tags); + addBranches(area, data.branches, data.default_branch); + showElem(area.querySelectorAll('.branch-and-tag-detail')); + } finally { + loadingButton.classList.remove('disabled'); + } +} + +function addTags(area, tags) { + const tagArea = area.querySelector('.tag-area'); + toggleElem(tagArea, tags.length > 0); + for (const tag of tags) { + addLink(tagArea, tag.web_link, tag.name); + } +} + +function addBranches(area, branches, defaultBranch) { + const defaultBranchTooltip = area.getAttribute('data-text-default-branch-tooltip'); + const branchArea = area.querySelector('.branch-area'); + toggleElem(branchArea, branches.length > 0); + for (const branch of branches) { + const tooltip = defaultBranch === branch.name ? defaultBranchTooltip : null; + addLink(branchArea, branch.web_link, branch.name, tooltip); + } +} + +function addLink(parent, href, text, tooltip) { + const link = document.createElement('a'); + link.classList.add('muted', 'gt-px-2'); + link.href = href; + link.textContent = text; + if (tooltip) { + link.classList.add('gt-border-secondary', 'gt-rounded'); + link.setAttribute('data-tooltip-content', tooltip); + } + parent.append(link); +} + +export function initRepoDiffCommitBranchesAndTags() { + for (const area of document.querySelectorAll('.branch-and-tag-area')) { + const btn = area.querySelector('.load-branches-and-tags'); + btn.addEventListener('click', () => loadBranchesAndTags(area, btn)); + } +} diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index f23ff45470c10..5991df6322c57 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -459,7 +459,7 @@ async function onEditContent(event) { } export function initRepository() { - if ($('.repository').length === 0) { + if ($('.page-content.repository').length === 0) { return; } diff --git a/web_src/js/index.js b/web_src/js/index.js index 0c786f96fbef2..8bd219bbe1576 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -83,6 +83,7 @@ import {initGiteaFomantic} from './modules/fomantic.js'; import {onDomReady} from './utils/dom.js'; import {initRepoIssueList} from './features/repo-issue-list.js'; import {initCommonIssueListQuickGoto} from './features/common-issue-list.js'; +import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.js'; // Init Gitea's Fomantic settings initGiteaFomantic(); @@ -141,6 +142,7 @@ onDomReady(() => { initRepoCodeView(); initRepoCommentForm(); initRepoEllipsisButton(); + initRepoDiffCommitBranchesAndTags(); initRepoCommitLastCommitLoader(); initRepoEditor(); initRepoGraphGit(); From 16afe4f63181a68565785c04885ed7d38b408fa9 Mon Sep 17 00:00:00 2001 From: puni9869 <80308335+puni9869@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:09:09 +0530 Subject: [PATCH 19/21] Add tooltip to describe LFS table column and color `delete LFS file` button red (#26181) Fix: https://github.com/go-gitea/gitea/issues/26152 Thease changes are related to UX and accessibility changes in desktop mode. image Also this is incomplete header image Lets add a tooltip if it is applicable or add `title` attribute so that it will be clearly visible. After ![image](https://github.com/go-gitea/gitea/assets/80308335/e1f91458-a0ab-4a9a-b32a-d1eaaac05b37) ![image](https://github.com/go-gitea/gitea/assets/80308335/fe2031d3-0b26-427f-8438-49e8f54bc12f) --- templates/repo/settings/lfs.tmpl | 4 ++-- templates/repo/settings/lfs_pointers.tmpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/repo/settings/lfs.tmpl b/templates/repo/settings/lfs.tmpl index 0d3a618e8d9eb..c4c27dce6429a 100644 --- a/templates/repo/settings/lfs.tmpl +++ b/templates/repo/settings/lfs.tmpl @@ -20,8 +20,8 @@ {{TimeSince .CreatedUnix.AsTime $.locale}} {{$.locale.Tr "repo.settings.lfs_findcommits"}} - diff --git a/templates/repo/settings/lfs_pointers.tmpl b/templates/repo/settings/lfs_pointers.tmpl index 0fffdadc3f366..b6b58a37720a8 100644 --- a/templates/repo/settings/lfs_pointers.tmpl +++ b/templates/repo/settings/lfs_pointers.tmpl @@ -24,7 +24,7 @@ {{.locale.Tr "repo.settings.lfs_pointers.oid"}} {{.locale.Tr "repo.settings.lfs_pointers.inRepo"}} {{.locale.Tr "repo.settings.lfs_pointers.exists"}} - {{.locale.Tr "repo.settings.lfs_pointers.accessible"}} + {{.locale.Tr "repo.settings.lfs_pointers.accessible"}} From eaea530d6bc84b23e6ff14ff8c2a74aa3b67ecd0 Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Thu, 27 Jul 2023 16:15:31 +0200 Subject: [PATCH 20/21] Render plaintext task list items for markdown files (#26186) - The library that's being used for org-mode, [doesn't render the status of list items](https://github.com/niklasfasching/go-org/issues/63). - Add a modified version of the proposed CSS snippet to still display the status for the list items. The alternative was parsing HTML and transforming it, which is too complicated for this small task. - Resolves https://codeberg.org/Codeberg/Community/issues/1099 (cherry picked from commit 9753c7e4b8490b8f1e3d19cb06187503b88afb88) Refs: https://codeberg.org/forgejo/forgejo/pulls/1071 Co-authored-by: Gusted --- modules/markup/sanitizer.go | 3 +++ modules/markup/sanitizer_test.go | 5 +++++ web_src/css/markup/content.css | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index 9f97f1d5b13e0..48c08831f1661 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -96,6 +96,9 @@ func createDefaultPolicy() *bluemonday.Policy { // Allow classes for task lists policy.AllowAttrs("class").Matching(regexp.MustCompile(`task-list-item`)).OnElements("li") + // Allow classes for org mode list item status. + policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(unchecked|checked|indeterminate)$`)).OnElements("li") + // Allow icons policy.AllowAttrs("class").Matching(regexp.MustCompile(`^icon(\s+[\p{L}\p{N}_-]+)+$`)).OnElements("i") diff --git a/modules/markup/sanitizer_test.go b/modules/markup/sanitizer_test.go index 4d85cbf9f303b..0bc63ff0a7cb3 100644 --- a/modules/markup/sanitizer_test.go +++ b/modules/markup/sanitizer_test.go @@ -53,6 +53,11 @@ func Test_Sanitizer(t *testing.T) { `

Hello World

`, `

Hello World

`, `Hello World`, `Hello World`, + // Org mode status of list items. + `
  • `, `
  • `, + `
  • `, `
  • `, + `
  • `, `
  • `, + // URLs `my custom URL scheme`, `my custom URL scheme`, `my custom URL scheme`, `my custom URL scheme`, diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index 2a645e522a174..d89e02c6404f4 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -556,3 +556,26 @@ border-top-left-radius: 0 !important; border-top-right-radius: 0 !important; } + +.file-view.markup.orgmode li.unchecked::before { + content: "[ ] "; +} + +.file-view.markup.orgmode li.checked::before { + content: "[x] "; +} + +.file-view.markup.orgmode li.indeterminate::before { + content: "[-] "; +} + +/* This is only needed for

    because they are literally acting as paragraphs, + * and thus having an ::before on the same line would force the paragraph to + * move to the next line. This can be avoided by an inline-block display that + * avoids that property while still having the other properties of the block + * display. */ +.file-view.markup.orgmode li.unchecked > p, +.file-view.markup.orgmode li.checked > p, +.file-view.markup.orgmode li.indeterminate > p { + display: inline-block; +} From 494ee56de28a52568413dfa30b5ddd99411fc2fc Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:24:40 +0200 Subject: [PATCH 21/21] improve unit test for caching (#26185) - Configure `setting.CacheService.TTL` which will force the code to go trough the caching mechanism. - Remove the TODO and uncomment the test code. (cherry picked from commit a201f2f1896c1a086f3e37f86b1306d44c07f2e4) Refs: https://codeberg.org/forgejo/forgejo/pulls/974 --------- Co-authored-by: Gusted --- modules/cache/cache_test.go | 76 ++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/modules/cache/cache_test.go b/modules/cache/cache_test.go index 1c8f7d55ba8c2..cf464af392d53 100644 --- a/modules/cache/cache_test.go +++ b/modules/cache/cache_test.go @@ -18,6 +18,7 @@ func createTestCache() { Adapter: "memory", TTL: time.Minute, }) + setting.CacheService.TTL = 24 * time.Hour } func TestNewContext(t *testing.T) { @@ -54,12 +55,12 @@ func TestGetString(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "", data) - // data, err = GetString("key", func() (string, error) { - // return "some data", nil - // }) - // assert.NoError(t, err) - // assert.Equal(t, "", data) - // Remove("key") + data, err = GetString("key", func() (string, error) { + return "some data", nil + }) + assert.NoError(t, err) + assert.Equal(t, "", data) + Remove("key") data, err = GetString("key", func() (string, error) { return "some data", nil @@ -67,13 +68,12 @@ func TestGetString(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "some data", data) - // data, err = GetString("key", func() (string, error) { - // return "", fmt.Errorf("some error") - // }) - // assert.NoError(t, err) - // assert.Equal(t, "some data", data) - - // TODO: uncommented code works in IDE but not with go test + data, err = GetString("key", func() (string, error) { + return "", fmt.Errorf("some error") + }) + assert.NoError(t, err) + assert.Equal(t, "some data", data) + Remove("key") } func TestGetInt(t *testing.T) { @@ -91,12 +91,12 @@ func TestGetInt(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 0, data) - // data, err = GetInt("key", func() (int, error) { - // return 100, nil - // }) - // assert.NoError(t, err) - // assert.Equal(t, 0, data) - // Remove("key") + data, err = GetInt("key", func() (int, error) { + return 100, nil + }) + assert.NoError(t, err) + assert.Equal(t, 0, data) + Remove("key") data, err = GetInt("key", func() (int, error) { return 100, nil @@ -104,13 +104,12 @@ func TestGetInt(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 100, data) - // data, err = GetInt("key", func() (int, error) { - // return 0, fmt.Errorf("some error") - // }) - // assert.NoError(t, err) - // assert.Equal(t, 100, data) - - // TODO: uncommented code works in IDE but not with go test + data, err = GetInt("key", func() (int, error) { + return 0, fmt.Errorf("some error") + }) + assert.NoError(t, err) + assert.Equal(t, 100, data) + Remove("key") } func TestGetInt64(t *testing.T) { @@ -128,12 +127,12 @@ func TestGetInt64(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 0, data) - // data, err = GetInt64("key", func() (int64, error) { - // return 100, nil - // }) - // assert.NoError(t, err) - // assert.EqualValues(t, 0, data) - // Remove("key") + data, err = GetInt64("key", func() (int64, error) { + return 100, nil + }) + assert.NoError(t, err) + assert.EqualValues(t, 0, data) + Remove("key") data, err = GetInt64("key", func() (int64, error) { return 100, nil @@ -141,11 +140,10 @@ func TestGetInt64(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 100, data) - // data, err = GetInt64("key", func() (int, error) { - // return 0, fmt.Errorf("some error") - // }) - // assert.NoError(t, err) - // assert.EqualValues(t, 100, data) - - // TODO: uncommented code works in IDE but not with go test + data, err = GetInt64("key", func() (int64, error) { + return 0, fmt.Errorf("some error") + }) + assert.NoError(t, err) + assert.EqualValues(t, 100, data) + Remove("key") }