新增:直接迁移项目接口

This commit is contained in:
yystopf 2022-12-28 15:35:23 +08:00
parent 6973f230e6
commit 15018595fe
2 changed files with 102 additions and 0 deletions

View File

@ -65,6 +65,7 @@ func Routers(ctx gocontext.Context) *web.Route {
m.Get("/version", misc.Version)
m.Group("/repos", func() {
m.Group("/{username}/{reponame}", func() {
m.Post("/transfer", reqOwner(), bind(gitea_api.TransferRepoOption{}), repo.Transfer)
m.Get("/branch_name_set", context.ReferencesGitRepo(), repo.BranchNameSet)
m.Get("/tag_name_set", context.ReferencesGitRepo(), repo.TagNameSet)
m.Group("/branches", func() {
@ -317,6 +318,15 @@ func bind(obj interface{}) http.HandlerFunc {
})
}
func reqOwner() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo")
return
}
}
}
func reqAdmin() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {

View File

@ -0,0 +1,92 @@
package repo
import (
"fmt"
"net/http"
"code.gitea.io/gitea/models"
organization "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
hat_repo_service "code.gitea.io/gitea/services/repository"
)
func Transfer(ctx *context.APIContext) {
opts := web.GetForm(ctx).(*api.TransferRepoOption)
newOwner, err := user_model.GetUserByName(ctx, opts.NewOwner)
if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found")
return
}
ctx.InternalServerError(err)
return
}
if newOwner.Type == user_model.UserTypeOrganization {
if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
ctx.Error(http.StatusNotFound, "", "The new owner does ot exist or cannot be found")
return
}
}
var teams []*organization.Team
if opts.TeamIDs != nil {
if !newOwner.IsOrganization() {
ctx.Error(http.StatusUnprocessableEntity, "repoTrasfer", "Teams can only be added to organization-owned repositories")
return
}
org := convert.ToOrganization(organization.OrgFromUser(newOwner))
for _, tID := range *opts.TeamIDs {
team, err := organization.GetTeamByID(ctx, tID)
if err != nil {
ctx.Error(http.StatusUnprocessableEntity, "team", fmt.Errorf("team %d not found", tID))
return
}
if team.OrgID != org.ID {
ctx.Error(http.StatusForbidden, "team", fmt.Errorf("team %d belongs not to org %d", tID, org.ID))
return
}
teams = append(teams, team)
}
}
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
oldFullName := ctx.Repo.Repository.FullName()
if err := hat_repo_service.TransferOwnership(ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
if models.IsErrRepoTransferInProgress(err) {
ctx.Error(http.StatusConflict, "TransferOwnership", err)
return
}
if repo_model.IsErrRepoAlreadyExist(err) {
ctx.Error(http.StatusUnprocessableEntity, "TransferOwnership", err)
return
}
ctx.InternalServerError(err)
return
}
if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
log.Trace("Repository transfer initiated: %s -> %s", oldFullName, ctx.Repo.Repository.FullName())
ctx.JSON(http.StatusCreated, convert.ToRepo(ctx.Repo.Repository, perm.AccessModeAdmin))
}
log.Trace("Repository transferred: %s -> %s", oldFullName, ctx.Repo.Repository.FullName())
ctx.JSON(http.StatusAccepted, convert.ToRepo(ctx.Repo.Repository, perm.AccessModeAdmin))
}