summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2024-03-13 18:07:53 +0800
committerGitHub <noreply@github.com>2024-03-13 10:07:53 +0000
commit66edc888ee8b2f77a6f11139acd2d03c561ad5ef (patch)
tree0fa811b88dc45ef0575a5521610f02f2ba27c92a
parent9b1a8888fa754676073bc851b783b2b8f1adecfb (diff)
downloadgitea-66edc888ee8b2f77a6f11139acd2d03c561ad5ef.tar.gz
gitea-66edc888ee8b2f77a6f11139acd2d03c561ad5ef.zip
Move fork router functions to a standalone file (#29756)
To reduce the pull.go file's size.
-rw-r--r--routers/web/repo/fork.go238
-rw-r--r--routers/web/repo/pull.go214
2 files changed, 238 insertions, 214 deletions
diff --git a/routers/web/repo/fork.go b/routers/web/repo/fork.go
new file mode 100644
index 0000000000..60e37476ee
--- /dev/null
+++ b/routers/web/repo/fork.go
@@ -0,0 +1,238 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+ "errors"
+ "net/http"
+ "net/url"
+
+ "code.gitea.io/gitea/models/db"
+ git_model "code.gitea.io/gitea/models/git"
+ "code.gitea.io/gitea/models/organization"
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/forms"
+ repo_service "code.gitea.io/gitea/services/repository"
+)
+
+const (
+ tplFork base.TplName = "repo/pulls/fork"
+)
+
+func getForkRepository(ctx *context.Context) *repo_model.Repository {
+ forkRepo := ctx.Repo.Repository
+ if ctx.Written() {
+ return nil
+ }
+
+ if forkRepo.IsEmpty {
+ log.Trace("Empty repository %-v", forkRepo)
+ ctx.NotFound("getForkRepository", nil)
+ return nil
+ }
+
+ if err := forkRepo.LoadOwner(ctx); err != nil {
+ ctx.ServerError("LoadOwner", err)
+ return nil
+ }
+
+ ctx.Data["repo_name"] = forkRepo.Name
+ ctx.Data["description"] = forkRepo.Description
+ ctx.Data["IsPrivate"] = forkRepo.IsPrivate || forkRepo.Owner.Visibility == structs.VisibleTypePrivate
+ canForkToUser := forkRepo.OwnerID != ctx.Doer.ID && !repo_model.HasForkedRepo(ctx, ctx.Doer.ID, forkRepo.ID)
+
+ ctx.Data["ForkRepo"] = forkRepo
+
+ ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(ctx, ctx.Doer.ID)
+ if err != nil {
+ ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
+ return nil
+ }
+ var orgs []*organization.Organization
+ for _, org := range ownedOrgs {
+ if forkRepo.OwnerID != org.ID && !repo_model.HasForkedRepo(ctx, org.ID, forkRepo.ID) {
+ orgs = append(orgs, org)
+ }
+ }
+
+ traverseParentRepo := forkRepo
+ for {
+ if ctx.Doer.ID == traverseParentRepo.OwnerID {
+ canForkToUser = false
+ } else {
+ for i, org := range orgs {
+ if org.ID == traverseParentRepo.OwnerID {
+ orgs = append(orgs[:i], orgs[i+1:]...)
+ break
+ }
+ }
+ }
+
+ if !traverseParentRepo.IsFork {
+ break
+ }
+ traverseParentRepo, err = repo_model.GetRepositoryByID(ctx, traverseParentRepo.ForkID)
+ if err != nil {
+ ctx.ServerError("GetRepositoryByID", err)
+ return nil
+ }
+ }
+
+ ctx.Data["CanForkToUser"] = canForkToUser
+ ctx.Data["Orgs"] = orgs
+
+ if canForkToUser {
+ ctx.Data["ContextUser"] = ctx.Doer
+ } else if len(orgs) > 0 {
+ ctx.Data["ContextUser"] = orgs[0]
+ } else {
+ ctx.Data["CanForkRepo"] = false
+ ctx.Flash.Error(ctx.Tr("repo.fork_no_valid_owners"), true)
+ return nil
+ }
+
+ branches, err := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{
+ RepoID: ctx.Repo.Repository.ID,
+ ListOptions: db.ListOptions{
+ ListAll: true,
+ },
+ IsDeletedBranch: optional.Some(false),
+ // Add it as the first option
+ ExcludeBranchNames: []string{ctx.Repo.Repository.DefaultBranch},
+ })
+ if err != nil {
+ ctx.ServerError("FindBranchNames", err)
+ return nil
+ }
+ ctx.Data["Branches"] = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
+
+ return forkRepo
+}
+
+// Fork render repository fork page
+func Fork(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("new_fork")
+
+ if ctx.Doer.CanForkRepo() {
+ ctx.Data["CanForkRepo"] = true
+ } else {
+ maxCreationLimit := ctx.Doer.MaxCreationLimit()
+ msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
+ ctx.Flash.Error(msg, true)
+ }
+
+ getForkRepository(ctx)
+ if ctx.Written() {
+ return
+ }
+
+ ctx.HTML(http.StatusOK, tplFork)
+}
+
+// ForkPost response for forking a repository
+func ForkPost(ctx *context.Context) {
+ form := web.GetForm(ctx).(*forms.CreateRepoForm)
+ ctx.Data["Title"] = ctx.Tr("new_fork")
+ ctx.Data["CanForkRepo"] = true
+
+ ctxUser := checkContextUser(ctx, form.UID)
+ if ctx.Written() {
+ return
+ }
+
+ forkRepo := getForkRepository(ctx)
+ if ctx.Written() {
+ return
+ }
+
+ ctx.Data["ContextUser"] = ctxUser
+
+ if ctx.HasError() {
+ ctx.HTML(http.StatusOK, tplFork)
+ return
+ }
+
+ var err error
+ traverseParentRepo := forkRepo
+ for {
+ if ctxUser.ID == traverseParentRepo.OwnerID {
+ ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
+ return
+ }
+ repo := repo_model.GetForkedRepo(ctx, ctxUser.ID, traverseParentRepo.ID)
+ if repo != nil {
+ ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
+ return
+ }
+ if !traverseParentRepo.IsFork {
+ break
+ }
+ traverseParentRepo, err = repo_model.GetRepositoryByID(ctx, traverseParentRepo.ForkID)
+ if err != nil {
+ ctx.ServerError("GetRepositoryByID", err)
+ return
+ }
+ }
+
+ // Check if user is allowed to create repo's on the organization.
+ if ctxUser.IsOrganization() {
+ isAllowedToFork, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx, ctx.Doer.ID)
+ if err != nil {
+ ctx.ServerError("CanCreateOrgRepo", err)
+ return
+ } else if !isAllowedToFork {
+ ctx.Error(http.StatusForbidden)
+ return
+ }
+ }
+
+ repo, err := repo_service.ForkRepository(ctx, ctx.Doer, ctxUser, repo_service.ForkRepoOptions{
+ BaseRepo: forkRepo,
+ Name: form.RepoName,
+ Description: form.Description,
+ SingleBranch: form.ForkSingleBranch,
+ })
+ if err != nil {
+ ctx.Data["Err_RepoName"] = true
+ switch {
+ case repo_model.IsErrReachLimitOfRepo(err):
+ maxCreationLimit := ctxUser.MaxCreationLimit()
+ msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
+ ctx.RenderWithErr(msg, tplFork, &form)
+ case repo_model.IsErrRepoAlreadyExist(err):
+ ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
+ case repo_model.IsErrRepoFilesAlreadyExist(err):
+ switch {
+ case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories):
+ ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tplFork, form)
+ case setting.Repository.AllowAdoptionOfUnadoptedRepositories:
+ ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt"), tplFork, form)
+ case setting.Repository.AllowDeleteOfUnadoptedRepositories:
+ ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.delete"), tplFork, form)
+ default:
+ ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist"), tplFork, form)
+ }
+ case db.IsErrNameReserved(err):
+ ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplFork, &form)
+ case db.IsErrNamePatternNotAllowed(err):
+ ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplFork, &form)
+ case errors.Is(err, user_model.ErrBlockedUser):
+ ctx.RenderWithErr(ctx.Tr("repo.fork.blocked_user"), tplFork, form)
+ default:
+ ctx.ServerError("ForkPost", err)
+ }
+ return
+ }
+
+ log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name)
+ ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
+}
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index ed063715e5..447781602d 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -10,7 +10,6 @@ import (
"fmt"
"html"
"net/http"
- "net/url"
"strconv"
"strings"
"time"
@@ -20,7 +19,6 @@ import (
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
- "code.gitea.io/gitea/models/organization"
access_model "code.gitea.io/gitea/models/perm/access"
pull_model "code.gitea.io/gitea/models/pull"
repo_model "code.gitea.io/gitea/models/repo"
@@ -32,9 +30,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
issue_template "code.gitea.io/gitea/modules/issue/template"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils"
@@ -53,7 +49,6 @@ import (
)
const (
- tplFork base.TplName = "repo/pulls/fork"
tplCompareDiff base.TplName = "repo/diff/compare"
tplPullCommits base.TplName = "repo/pulls/commits"
tplPullFiles base.TplName = "repo/pulls/files"
@@ -112,215 +107,6 @@ func getRepository(ctx *context.Context, repoID int64) *repo_model.Repository {
return repo
}
-func getForkRepository(ctx *context.Context) *repo_model.Repository {
- forkRepo := ctx.Repo.Repository
- if ctx.Written() {
- return nil
- }
-
- if forkRepo.IsEmpty {
- log.Trace("Empty repository %-v", forkRepo)
- ctx.NotFound("getForkRepository", nil)
- return nil
- }
-
- if err := forkRepo.LoadOwner(ctx); err != nil {
- ctx.ServerError("LoadOwner", err)
- return nil
- }
-
- ctx.Data["repo_name"] = forkRepo.Name
- ctx.Data["description"] = forkRepo.Description
- ctx.Data["IsPrivate"] = forkRepo.IsPrivate || forkRepo.Owner.Visibility == structs.VisibleTypePrivate
- canForkToUser := forkRepo.OwnerID != ctx.Doer.ID && !repo_model.HasForkedRepo(ctx, ctx.Doer.ID, forkRepo.ID)
-
- ctx.Data["ForkRepo"] = forkRepo
-
- ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(ctx, ctx.Doer.ID)
- if err != nil {
- ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
- return nil
- }
- var orgs []*organization.Organization
- for _, org := range ownedOrgs {
- if forkRepo.OwnerID != org.ID && !repo_model.HasForkedRepo(ctx, org.ID, forkRepo.ID) {
- orgs = append(orgs, org)
- }
- }
-
- traverseParentRepo := forkRepo
- for {
- if ctx.Doer.ID == traverseParentRepo.OwnerID {
- canForkToUser = false
- } else {
- for i, org := range orgs {
- if org.ID == traverseParentRepo.OwnerID {
- orgs = append(orgs[:i], orgs[i+1:]...)
- break
- }
- }
- }
-
- if !traverseParentRepo.IsFork {
- break
- }
- traverseParentRepo, err = repo_model.GetRepositoryByID(ctx, traverseParentRepo.ForkID)
- if err != nil {
- ctx.ServerError("GetRepositoryByID", err)
- return nil
- }
- }
-
- ctx.Data["CanForkToUser"] = canForkToUser
- ctx.Data["Orgs"] = orgs
-
- if canForkToUser {
- ctx.Data["ContextUser"] = ctx.Doer
- } else if len(orgs) > 0 {
- ctx.Data["ContextUser"] = orgs[0]
- } else {
- ctx.Data["CanForkRepo"] = false
- ctx.Flash.Error(ctx.Tr("repo.fork_no_valid_owners"), true)
- return nil
- }
-
- branches, err := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{
- RepoID: ctx.Repo.Repository.ID,
- ListOptions: db.ListOptions{
- ListAll: true,
- },
- IsDeletedBranch: optional.Some(false),
- // Add it as the first option
- ExcludeBranchNames: []string{ctx.Repo.Repository.DefaultBranch},
- })
- if err != nil {
- ctx.ServerError("FindBranchNames", err)
- return nil
- }
- ctx.Data["Branches"] = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
-
- return forkRepo
-}
-
-// Fork render repository fork page
-func Fork(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("new_fork")
-
- if ctx.Doer.CanForkRepo() {
- ctx.Data["CanForkRepo"] = true
- } else {
- maxCreationLimit := ctx.Doer.MaxCreationLimit()
- msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
- ctx.Flash.Error(msg, true)
- }
-
- getForkRepository(ctx)
- if ctx.Written() {
- return
- }
-
- ctx.HTML(http.StatusOK, tplFork)
-}
-
-// ForkPost response for forking a repository
-func ForkPost(ctx *context.Context) {
- form := web.GetForm(ctx).(*forms.CreateRepoForm)
- ctx.Data["Title"] = ctx.Tr("new_fork")
- ctx.Data["CanForkRepo"] = true
-
- ctxUser := checkContextUser(ctx, form.UID)
- if ctx.Written() {
- return
- }
-
- forkRepo := getForkRepository(ctx)
- if ctx.Written() {
- return
- }
-
- ctx.Data["ContextUser"] = ctxUser
-
- if ctx.HasError() {
- ctx.HTML(http.StatusOK, tplFork)
- return
- }
-
- var err error
- traverseParentRepo := forkRepo
- for {
- if ctxUser.ID == traverseParentRepo.OwnerID {
- ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
- return
- }
- repo := repo_model.GetForkedRepo(ctx, ctxUser.ID, traverseParentRepo.ID)
- if repo != nil {
- ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
- return
- }
- if !traverseParentRepo.IsFork {
- break
- }
- traverseParentRepo, err = repo_model.GetRepositoryByID(ctx, traverseParentRepo.ForkID)
- if err != nil {
- ctx.ServerError("GetRepositoryByID", err)
- return
- }
- }
-
- // Check if user is allowed to create repo's on the organization.
- if ctxUser.IsOrganization() {
- isAllowedToFork, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx, ctx.Doer.ID)
- if err != nil {
- ctx.ServerError("CanCreateOrgRepo", err)
- return
- } else if !isAllowedToFork {
- ctx.Error(http.StatusForbidden)
- return
- }
- }
-
- repo, err := repo_service.ForkRepository(ctx, ctx.Doer, ctxUser, repo_service.ForkRepoOptions{
- BaseRepo: forkRepo,
- Name: form.RepoName,
- Description: form.Description,
- SingleBranch: form.ForkSingleBranch,
- })
- if err != nil {
- ctx.Data["Err_RepoName"] = true
- switch {
- case repo_model.IsErrReachLimitOfRepo(err):
- maxCreationLimit := ctxUser.MaxCreationLimit()
- msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
- ctx.RenderWithErr(msg, tplFork, &form)
- case repo_model.IsErrRepoAlreadyExist(err):
- ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
- case repo_model.IsErrRepoFilesAlreadyExist(err):
- switch {
- case ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories):
- ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt_or_delete"), tplFork, form)
- case setting.Repository.AllowAdoptionOfUnadoptedRepositories:
- ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.adopt"), tplFork, form)
- case setting.Repository.AllowDeleteOfUnadoptedRepositories:
- ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist.delete"), tplFork, form)
- default:
- ctx.RenderWithErr(ctx.Tr("form.repository_files_already_exist"), tplFork, form)
- }
- case db.IsErrNameReserved(err):
- ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tplFork, &form)
- case db.IsErrNamePatternNotAllowed(err):
- ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplFork, &form)
- case errors.Is(err, user_model.ErrBlockedUser):
- ctx.RenderWithErr(ctx.Tr("repo.fork.blocked_user"), tplFork, form)
- default:
- ctx.ServerError("ForkPost", err)
- }
- return
- }
-
- log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name)
- ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(repo.Name))
-}
-
func getPullInfo(ctx *context.Context) (issue *issues_model.Issue, ok bool) {
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
if err != nil {