Move some errors to their own sub packages (#32880)

This commit is contained in:
Lunny Xiao 2024-12-20 10:05:29 -08:00 committed by GitHub
parent 4774151e53
commit 751fe8b714
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
52 changed files with 728 additions and 781 deletions

View File

@ -1,510 +0,0 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package models
import (
"fmt"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/util"
)
// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
type ErrUserOwnRepos struct {
UID int64
}
// IsErrUserOwnRepos checks if an error is a ErrUserOwnRepos.
func IsErrUserOwnRepos(err error) bool {
_, ok := err.(ErrUserOwnRepos)
return ok
}
func (err ErrUserOwnRepos) Error() string {
return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID)
}
// ErrUserHasOrgs represents a "UserHasOrgs" kind of error.
type ErrUserHasOrgs struct {
UID int64
}
// IsErrUserHasOrgs checks if an error is a ErrUserHasOrgs.
func IsErrUserHasOrgs(err error) bool {
_, ok := err.(ErrUserHasOrgs)
return ok
}
func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
// ErrUserOwnPackages notifies that the user (still) owns the packages.
type ErrUserOwnPackages struct {
UID int64
}
// IsErrUserOwnPackages checks if an error is an ErrUserOwnPackages.
func IsErrUserOwnPackages(err error) bool {
_, ok := err.(ErrUserOwnPackages)
return ok
}
func (err ErrUserOwnPackages) Error() string {
return fmt.Sprintf("user still has ownership of packages [uid: %d]", err.UID)
}
// ErrDeleteLastAdminUser represents a "DeleteLastAdminUser" kind of error.
type ErrDeleteLastAdminUser struct {
UID int64
}
// IsErrDeleteLastAdminUser checks if an error is a ErrDeleteLastAdminUser.
func IsErrDeleteLastAdminUser(err error) bool {
_, ok := err.(ErrDeleteLastAdminUser)
return ok
}
func (err ErrDeleteLastAdminUser) Error() string {
return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
}
// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
type ErrInvalidCloneAddr struct {
Host string
IsURLError bool
IsInvalidPath bool
IsProtocolInvalid bool
IsPermissionDenied bool
LocalPath bool
}
// IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
func IsErrInvalidCloneAddr(err error) bool {
_, ok := err.(*ErrInvalidCloneAddr)
return ok
}
func (err *ErrInvalidCloneAddr) Error() string {
if err.IsInvalidPath {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
}
if err.IsProtocolInvalid {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
}
if err.IsPermissionDenied {
return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
}
if err.IsURLError {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
}
return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
}
func (err *ErrInvalidCloneAddr) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrUpdateTaskNotExist represents a "UpdateTaskNotExist" kind of error.
type ErrUpdateTaskNotExist struct {
UUID string
}
// IsErrUpdateTaskNotExist checks if an error is a ErrUpdateTaskNotExist.
func IsErrUpdateTaskNotExist(err error) bool {
_, ok := err.(ErrUpdateTaskNotExist)
return ok
}
func (err ErrUpdateTaskNotExist) Error() string {
return fmt.Sprintf("update task does not exist [uuid: %s]", err.UUID)
}
func (err ErrUpdateTaskNotExist) Unwrap() error {
return util.ErrNotExist
}
// ErrInvalidTagName represents a "InvalidTagName" kind of error.
type ErrInvalidTagName struct {
TagName string
}
// IsErrInvalidTagName checks if an error is a ErrInvalidTagName.
func IsErrInvalidTagName(err error) bool {
_, ok := err.(ErrInvalidTagName)
return ok
}
func (err ErrInvalidTagName) Error() string {
return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
}
func (err ErrInvalidTagName) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrProtectedTagName represents a "ProtectedTagName" kind of error.
type ErrProtectedTagName struct {
TagName string
}
// IsErrProtectedTagName checks if an error is a ErrProtectedTagName.
func IsErrProtectedTagName(err error) bool {
_, ok := err.(ErrProtectedTagName)
return ok
}
func (err ErrProtectedTagName) Error() string {
return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName)
}
func (err ErrProtectedTagName) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error.
type ErrRepoFileAlreadyExists struct {
Path string
}
// IsErrRepoFileAlreadyExists checks if an error is a ErrRepoFileAlreadyExists.
func IsErrRepoFileAlreadyExists(err error) bool {
_, ok := err.(ErrRepoFileAlreadyExists)
return ok
}
func (err ErrRepoFileAlreadyExists) Error() string {
return fmt.Sprintf("repository file already exists [path: %s]", err.Path)
}
func (err ErrRepoFileAlreadyExists) Unwrap() error {
return util.ErrAlreadyExist
}
// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error.
type ErrRepoFileDoesNotExist struct {
Path string
Name string
}
// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist.
func IsErrRepoFileDoesNotExist(err error) bool {
_, ok := err.(ErrRepoFileDoesNotExist)
return ok
}
func (err ErrRepoFileDoesNotExist) Error() string {
return fmt.Sprintf("repository file does not exist [path: %s]", err.Path)
}
func (err ErrRepoFileDoesNotExist) Unwrap() error {
return util.ErrNotExist
}
// ErrFilenameInvalid represents a "FilenameInvalid" kind of error.
type ErrFilenameInvalid struct {
Path string
}
// IsErrFilenameInvalid checks if an error is an ErrFilenameInvalid.
func IsErrFilenameInvalid(err error) bool {
_, ok := err.(ErrFilenameInvalid)
return ok
}
func (err ErrFilenameInvalid) Error() string {
return fmt.Sprintf("path contains a malformed path component [path: %s]", err.Path)
}
func (err ErrFilenameInvalid) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrUserCannotCommit represents "UserCannotCommit" kind of error.
type ErrUserCannotCommit struct {
UserName string
}
// IsErrUserCannotCommit checks if an error is an ErrUserCannotCommit.
func IsErrUserCannotCommit(err error) bool {
_, ok := err.(ErrUserCannotCommit)
return ok
}
func (err ErrUserCannotCommit) Error() string {
return fmt.Sprintf("user cannot commit to repo [user: %s]", err.UserName)
}
func (err ErrUserCannotCommit) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrFilePathInvalid represents a "FilePathInvalid" kind of error.
type ErrFilePathInvalid struct {
Message string
Path string
Name string
Type git.EntryMode
}
// IsErrFilePathInvalid checks if an error is an ErrFilePathInvalid.
func IsErrFilePathInvalid(err error) bool {
_, ok := err.(ErrFilePathInvalid)
return ok
}
func (err ErrFilePathInvalid) Error() string {
if err.Message != "" {
return err.Message
}
return fmt.Sprintf("path is invalid [path: %s]", err.Path)
}
func (err ErrFilePathInvalid) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrFilePathProtected represents a "FilePathProtected" kind of error.
type ErrFilePathProtected struct {
Message string
Path string
}
// IsErrFilePathProtected checks if an error is an ErrFilePathProtected.
func IsErrFilePathProtected(err error) bool {
_, ok := err.(ErrFilePathProtected)
return ok
}
func (err ErrFilePathProtected) Error() string {
if err.Message != "" {
return err.Message
}
return fmt.Sprintf("path is protected and can not be changed [path: %s]", err.Path)
}
func (err ErrFilePathProtected) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrDisallowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it.
type ErrDisallowedToMerge struct {
Reason string
}
// IsErrDisallowedToMerge checks if an error is an ErrDisallowedToMerge.
func IsErrDisallowedToMerge(err error) bool {
_, ok := err.(ErrDisallowedToMerge)
return ok
}
func (err ErrDisallowedToMerge) Error() string {
return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason)
}
func (err ErrDisallowedToMerge) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrTagAlreadyExists represents an error that tag with such name already exists.
type ErrTagAlreadyExists struct {
TagName string
}
// IsErrTagAlreadyExists checks if an error is an ErrTagAlreadyExists.
func IsErrTagAlreadyExists(err error) bool {
_, ok := err.(ErrTagAlreadyExists)
return ok
}
func (err ErrTagAlreadyExists) Error() string {
return fmt.Sprintf("tag already exists [name: %s]", err.TagName)
}
func (err ErrTagAlreadyExists) Unwrap() error {
return util.ErrAlreadyExist
}
// ErrSHADoesNotMatch represents a "SHADoesNotMatch" kind of error.
type ErrSHADoesNotMatch struct {
Path string
GivenSHA string
CurrentSHA string
}
// IsErrSHADoesNotMatch checks if an error is a ErrSHADoesNotMatch.
func IsErrSHADoesNotMatch(err error) bool {
_, ok := err.(ErrSHADoesNotMatch)
return ok
}
func (err ErrSHADoesNotMatch) Error() string {
return fmt.Sprintf("sha does not match [given: %s, expected: %s]", err.GivenSHA, err.CurrentSHA)
}
// ErrSHANotFound represents a "SHADoesNotMatch" kind of error.
type ErrSHANotFound struct {
SHA string
}
// IsErrSHANotFound checks if an error is a ErrSHANotFound.
func IsErrSHANotFound(err error) bool {
_, ok := err.(ErrSHANotFound)
return ok
}
func (err ErrSHANotFound) Error() string {
return fmt.Sprintf("sha not found [%s]", err.SHA)
}
func (err ErrSHANotFound) Unwrap() error {
return util.ErrNotExist
}
// ErrCommitIDDoesNotMatch represents a "CommitIDDoesNotMatch" kind of error.
type ErrCommitIDDoesNotMatch struct {
GivenCommitID string
CurrentCommitID string
}
// IsErrCommitIDDoesNotMatch checks if an error is a ErrCommitIDDoesNotMatch.
func IsErrCommitIDDoesNotMatch(err error) bool {
_, ok := err.(ErrCommitIDDoesNotMatch)
return ok
}
func (err ErrCommitIDDoesNotMatch) Error() string {
return fmt.Sprintf("file CommitID does not match [given: %s, expected: %s]", err.GivenCommitID, err.CurrentCommitID)
}
// ErrSHAOrCommitIDNotProvided represents a "SHAOrCommitIDNotProvided" kind of error.
type ErrSHAOrCommitIDNotProvided struct{}
// IsErrSHAOrCommitIDNotProvided checks if an error is a ErrSHAOrCommitIDNotProvided.
func IsErrSHAOrCommitIDNotProvided(err error) bool {
_, ok := err.(ErrSHAOrCommitIDNotProvided)
return ok
}
func (err ErrSHAOrCommitIDNotProvided) Error() string {
return "a SHA or commit ID must be proved when updating a file"
}
// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy
type ErrInvalidMergeStyle struct {
ID int64
Style repo_model.MergeStyle
}
// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle.
func IsErrInvalidMergeStyle(err error) bool {
_, ok := err.(ErrInvalidMergeStyle)
return ok
}
func (err ErrInvalidMergeStyle) Error() string {
return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]",
err.ID, err.Style)
}
func (err ErrInvalidMergeStyle) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrMergeConflicts represents an error if merging fails with a conflict
type ErrMergeConflicts struct {
Style repo_model.MergeStyle
StdOut string
StdErr string
Err error
}
// IsErrMergeConflicts checks if an error is a ErrMergeConflicts.
func IsErrMergeConflicts(err error) bool {
_, ok := err.(ErrMergeConflicts)
return ok
}
func (err ErrMergeConflicts) Error() string {
return fmt.Sprintf("Merge Conflict Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
// ErrMergeUnrelatedHistories represents an error if merging fails due to unrelated histories
type ErrMergeUnrelatedHistories struct {
Style repo_model.MergeStyle
StdOut string
StdErr string
Err error
}
// IsErrMergeUnrelatedHistories checks if an error is a ErrMergeUnrelatedHistories.
func IsErrMergeUnrelatedHistories(err error) bool {
_, ok := err.(ErrMergeUnrelatedHistories)
return ok
}
func (err ErrMergeUnrelatedHistories) Error() string {
return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge
type ErrMergeDivergingFastForwardOnly struct {
StdOut string
StdErr string
Err error
}
// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly.
func IsErrMergeDivergingFastForwardOnly(err error) bool {
_, ok := err.(ErrMergeDivergingFastForwardOnly)
return ok
}
func (err ErrMergeDivergingFastForwardOnly) Error() string {
return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
// ErrRebaseConflicts represents an error if rebase fails with a conflict
type ErrRebaseConflicts struct {
Style repo_model.MergeStyle
CommitSHA string
StdOut string
StdErr string
Err error
}
// IsErrRebaseConflicts checks if an error is a ErrRebaseConflicts.
func IsErrRebaseConflicts(err error) bool {
_, ok := err.(ErrRebaseConflicts)
return ok
}
func (err ErrRebaseConflicts) Error() string {
return fmt.Sprintf("Rebase Error: %v: Whilst Rebasing: %s\n%s\n%s", err.Err, err.CommitSHA, err.StdErr, err.StdOut)
}
// ErrPullRequestHasMerged represents a "PullRequestHasMerged"-error
type ErrPullRequestHasMerged struct {
ID int64
IssueID int64
HeadRepoID int64
BaseRepoID int64
HeadBranch string
BaseBranch string
}
// IsErrPullRequestHasMerged checks if an error is a ErrPullRequestHasMerged.
func IsErrPullRequestHasMerged(err error) bool {
_, ok := err.(ErrPullRequestHasMerged)
return ok
}
// Error does pretty-printing :D
func (err ErrPullRequestHasMerged) Error() string {
return fmt.Sprintf("pull request has merged [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
}

View File

@ -36,6 +36,21 @@ func init() {
db.RegisterModel(new(OrgUser)) db.RegisterModel(new(OrgUser))
} }
// ErrUserHasOrgs represents a "UserHasOrgs" kind of error.
type ErrUserHasOrgs struct {
UID int64
}
// IsErrUserHasOrgs checks if an error is a ErrUserHasOrgs.
func IsErrUserHasOrgs(err error) bool {
_, ok := err.(ErrUserHasOrgs)
return ok
}
func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
// GetOrganizationCount returns count of membership of organization of the user. // GetOrganizationCount returns count of membership of organization of the user.
func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) { func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) {
return db.GetEngine(ctx). return db.GetEngine(ctx).

View File

@ -301,6 +301,21 @@ func FindUnreferencedPackages(ctx context.Context) ([]*Package, error) {
Find(&ps) Find(&ps)
} }
// ErrUserOwnPackages notifies that the user (still) owns the packages.
type ErrUserOwnPackages struct {
UID int64
}
// IsErrUserOwnPackages checks if an error is an ErrUserOwnPackages.
func IsErrUserOwnPackages(err error) bool {
_, ok := err.(ErrUserOwnPackages)
return ok
}
func (err ErrUserOwnPackages) Error() string {
return fmt.Sprintf("user still has ownership of packages [uid: %d]", err.UID)
}
// HasOwnerPackages tests if a user/org has accessible packages // HasOwnerPackages tests if a user/org has accessible packages
func HasOwnerPackages(ctx context.Context, ownerID int64) (bool, error) { func HasOwnerPackages(ctx context.Context, ownerID int64) (bool, error) {
return db.GetEngine(ctx). return db.GetEngine(ctx).

View File

@ -37,7 +37,7 @@ type ErrUserDoesNotHaveAccessToRepo struct {
RepoName string RepoName string
} }
// IsErrUserDoesNotHaveAccessToRepo checks if an error is a ErrRepoFileAlreadyExists. // IsErrUserDoesNotHaveAccessToRepo checks if an error is a ErrUserDoesNotHaveAccessToRepo.
func IsErrUserDoesNotHaveAccessToRepo(err error) bool { func IsErrUserDoesNotHaveAccessToRepo(err error) bool {
_, ok := err.(ErrUserDoesNotHaveAccessToRepo) _, ok := err.(ErrUserDoesNotHaveAccessToRepo)
return ok return ok
@ -866,6 +866,21 @@ func (repo *Repository) TemplateRepo(ctx context.Context) *Repository {
return repo return repo
} }
// ErrUserOwnRepos represents a "UserOwnRepos" kind of error.
type ErrUserOwnRepos struct {
UID int64
}
// IsErrUserOwnRepos checks if an error is a ErrUserOwnRepos.
func IsErrUserOwnRepos(err error) bool {
_, ok := err.(ErrUserOwnRepos)
return ok
}
func (err ErrUserOwnRepos) Error() string {
return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID)
}
type CountRepositoryOptions struct { type CountRepositoryOptions struct {
OwnerID int64 OwnerID int64
Private optional.Option[bool] Private optional.Option[bool]

View File

@ -788,6 +788,21 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
return committer.Commit() return committer.Commit()
} }
// ErrDeleteLastAdminUser represents a "DeleteLastAdminUser" kind of error.
type ErrDeleteLastAdminUser struct {
UID int64
}
// IsErrDeleteLastAdminUser checks if an error is a ErrDeleteLastAdminUser.
func IsErrDeleteLastAdminUser(err error) bool {
_, ok := err.(ErrDeleteLastAdminUser)
return ok
}
func (err ErrDeleteLastAdminUser) Error() string {
return fmt.Sprintf("can not delete the last admin user [uid: %d]", err.UID)
}
// IsLastAdminUser check whether user is the last admin // IsLastAdminUser check whether user is the last admin
func IsLastAdminUser(ctx context.Context, user *User) bool { func IsLastAdminUser(ctx context.Context, user *User) bool {
if user.IsAdmin && CountUsers(ctx, &CountUserFilter{IsAdmin: optional.Some(true)}) <= 1 { if user.IsAdmin && CountUsers(ctx, &CountUserFilter{IsAdmin: optional.Some(true)}) <= 1 {

View File

@ -5,8 +5,12 @@ package git
import ( import (
"context" "context"
"fmt"
"net/url"
"strings"
giturl "code.gitea.io/gitea/modules/git/url" giturl "code.gitea.io/gitea/modules/git/url"
"code.gitea.io/gitea/modules/util"
) )
// GetRemoteAddress returns remote url of git repository in the repoPath with special remote name // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name
@ -37,3 +41,61 @@ func GetRemoteURL(ctx context.Context, repoPath, remoteName string) (*giturl.Git
} }
return giturl.Parse(addr) return giturl.Parse(addr)
} }
// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
type ErrInvalidCloneAddr struct {
Host string
IsURLError bool
IsInvalidPath bool
IsProtocolInvalid bool
IsPermissionDenied bool
LocalPath bool
}
// IsErrInvalidCloneAddr checks if an error is a ErrInvalidCloneAddr.
func IsErrInvalidCloneAddr(err error) bool {
_, ok := err.(*ErrInvalidCloneAddr)
return ok
}
func (err *ErrInvalidCloneAddr) Error() string {
if err.IsInvalidPath {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided path is invalid", err.Host)
}
if err.IsProtocolInvalid {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url protocol is not allowed", err.Host)
}
if err.IsPermissionDenied {
return fmt.Sprintf("migration/cloning from '%s' is not allowed.", err.Host)
}
if err.IsURLError {
return fmt.Sprintf("migration/cloning from '%s' is not allowed: the provided url is invalid", err.Host)
}
return fmt.Sprintf("migration/cloning from '%s' is not allowed", err.Host)
}
func (err *ErrInvalidCloneAddr) Unwrap() error {
return util.ErrInvalidArgument
}
// ParseRemoteAddr checks if given remote address is valid,
// and returns composed URL with needed username and password.
func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
remoteAddr = strings.TrimSpace(remoteAddr)
// Remote address can be HTTP/HTTPS/Git URL or local path.
if strings.HasPrefix(remoteAddr, "http://") ||
strings.HasPrefix(remoteAddr, "https://") ||
strings.HasPrefix(remoteAddr, "git://") {
u, err := url.Parse(remoteAddr)
if err != nil {
return "", &ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
}
if len(authUsername)+len(authPassword) > 0 {
u.User = url.UserPassword(authUsername, authPassword)
}
remoteAddr = u.String()
}
return remoteAddr, nil
}

View File

@ -9,10 +9,12 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey" asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization"
packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@ -247,7 +249,7 @@ func EditUser(ctx *context.APIContext) {
} }
if err := user_service.UpdateUser(ctx, ctx.ContextUser, opts); err != nil { if err := user_service.UpdateUser(ctx, ctx.ContextUser, opts); err != nil {
if models.IsErrDeleteLastAdminUser(err) { if user_model.IsErrDeleteLastAdminUser(err) {
ctx.Error(http.StatusBadRequest, "LastAdmin", err) ctx.Error(http.StatusBadRequest, "LastAdmin", err)
} else { } else {
ctx.Error(http.StatusInternalServerError, "UpdateUser", err) ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
@ -299,10 +301,10 @@ func DeleteUser(ctx *context.APIContext) {
} }
if err := user_service.DeleteUser(ctx, ctx.ContextUser, ctx.FormBool("purge")); err != nil { if err := user_service.DeleteUser(ctx, ctx.ContextUser, ctx.FormBool("purge")); err != nil {
if models.IsErrUserOwnRepos(err) || if repo_model.IsErrUserOwnRepos(err) ||
models.IsErrUserHasOrgs(err) || org_model.IsErrUserHasOrgs(err) ||
models.IsErrUserOwnPackages(err) || packages_model.IsErrUserOwnPackages(err) ||
models.IsErrDeleteLastAdminUser(err) { user_model.IsErrDeleteLastAdminUser(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err) ctx.Error(http.StatusUnprocessableEntity, "", err)
} else { } else {
ctx.Error(http.StatusInternalServerError, "DeleteUser", err) ctx.Error(http.StatusInternalServerError, "DeleteUser", err)

View File

@ -9,7 +9,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
@ -24,6 +23,7 @@ import (
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
pull_service "code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
) )
@ -247,7 +247,7 @@ func CreateBranch(ctx *context.APIContext) {
if err != nil { if err != nil {
if git_model.IsErrBranchNotExist(err) { if git_model.IsErrBranchNotExist(err) {
ctx.Error(http.StatusNotFound, "", "The old branch does not exist") ctx.Error(http.StatusNotFound, "", "The old branch does not exist")
} else if models.IsErrTagAlreadyExists(err) { } else if release_service.IsErrTagAlreadyExists(err) {
ctx.Error(http.StatusConflict, "", "The branch with the same tag already exists.") ctx.Error(http.StatusConflict, "", "The branch with the same tag already exists.")
} else if git_model.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) { } else if git_model.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) {
ctx.Error(http.StatusConflict, "", "The branch already exists.") ctx.Error(http.StatusConflict, "", "The branch already exists.")

View File

@ -15,7 +15,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
@ -30,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
pull_service "code.gitea.io/gitea/services/pull"
archiver_service "code.gitea.io/gitea/services/repository/archiver" archiver_service "code.gitea.io/gitea/services/repository/archiver"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
) )
@ -736,12 +736,12 @@ func UpdateFile(ctx *context.APIContext) {
} }
func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) { func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) {
if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) { if files_service.IsErrUserCannotCommit(err) || pull_service.IsErrFilePathProtected(err) {
ctx.Error(http.StatusForbidden, "Access", err) ctx.Error(http.StatusForbidden, "Access", err)
return return
} }
if git_model.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) || if git_model.IsErrBranchAlreadyExists(err) || files_service.IsErrFilenameInvalid(err) || pull_service.IsErrSHADoesNotMatch(err) ||
models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) { files_service.IsErrFilePathInvalid(err) || files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err) ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
return return
} }
@ -887,17 +887,17 @@ func DeleteFile(ctx *context.APIContext) {
} }
if filesResponse, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, opts); err != nil { if filesResponse, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, opts); err != nil {
if git.IsErrBranchNotExist(err) || models.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) { if git.IsErrBranchNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "DeleteFile", err) ctx.Error(http.StatusNotFound, "DeleteFile", err)
return return
} else if git_model.IsErrBranchAlreadyExists(err) || } else if git_model.IsErrBranchAlreadyExists(err) ||
models.IsErrFilenameInvalid(err) || files_service.IsErrFilenameInvalid(err) ||
models.IsErrSHADoesNotMatch(err) || pull_service.IsErrSHADoesNotMatch(err) ||
models.IsErrCommitIDDoesNotMatch(err) || files_service.IsErrCommitIDDoesNotMatch(err) ||
models.IsErrSHAOrCommitIDNotProvided(err) { files_service.IsErrSHAOrCommitIDNotProvided(err) {
ctx.Error(http.StatusBadRequest, "DeleteFile", err) ctx.Error(http.StatusBadRequest, "DeleteFile", err)
return return
} else if models.IsErrUserCannotCommit(err) { } else if files_service.IsErrUserCannotCommit(err) {
ctx.Error(http.StatusForbidden, "DeleteFile", err) ctx.Error(http.StatusForbidden, "DeleteFile", err)
return return
} }

View File

@ -10,13 +10,13 @@ import (
"net/http" "net/http"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access" access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@ -27,7 +27,6 @@ import (
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations" "code.gitea.io/gitea/services/migrations"
notify_service "code.gitea.io/gitea/services/notify" notify_service "code.gitea.io/gitea/services/notify"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
@ -104,7 +103,7 @@ func Migrate(ctx *context.APIContext) {
} }
} }
remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword) remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer) err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
} }
@ -237,7 +236,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The username '%s' contains invalid characters.", err.(db.ErrNameCharsNotAllowed).Name)) ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The username '%s' contains invalid characters.", err.(db.ErrNameCharsNotAllowed).Name))
case db.IsErrNamePatternNotAllowed(err): case db.IsErrNamePatternNotAllowed(err):
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(db.ErrNamePatternNotAllowed).Pattern)) ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(db.ErrNamePatternNotAllowed).Pattern))
case models.IsErrInvalidCloneAddr(err): case git.IsErrInvalidCloneAddr(err):
ctx.Error(http.StatusUnprocessableEntity, "", err) ctx.Error(http.StatusUnprocessableEntity, "", err)
case base.IsErrNotSupported(err): case base.IsErrNotSupported(err):
ctx.Error(http.StatusUnprocessableEntity, "", err) ctx.Error(http.StatusUnprocessableEntity, "", err)
@ -256,8 +255,8 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *user_model.User, err
} }
func handleRemoteAddrError(ctx *context.APIContext, err error) { func handleRemoteAddrError(ctx *context.APIContext, err error) {
if models.IsErrInvalidCloneAddr(err) { if git.IsErrInvalidCloneAddr(err) {
addrErr := err.(*models.ErrInvalidCloneAddr) addrErr := err.(*git.ErrInvalidCloneAddr)
switch { switch {
case addrErr.IsURLError: case addrErr.IsURLError:
ctx.Error(http.StatusUnprocessableEntity, "", err) ctx.Error(http.StatusUnprocessableEntity, "", err)

View File

@ -9,10 +9,10 @@ import (
"net/http" "net/http"
"time" "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -20,7 +20,6 @@ import (
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations" "code.gitea.io/gitea/services/migrations"
mirror_service "code.gitea.io/gitea/services/mirror" mirror_service "code.gitea.io/gitea/services/mirror"
) )
@ -344,7 +343,7 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
return return
} }
address, err := forms.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword) address, err := git.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.ContextUser) err = migrations.IsMigrateURLAllowed(address, ctx.ContextUser)
} }
@ -397,8 +396,8 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
} }
func HandleRemoteAddressError(ctx *context.APIContext, err error) { func HandleRemoteAddressError(ctx *context.APIContext, err error) {
if models.IsErrInvalidCloneAddr(err) { if git.IsErrInvalidCloneAddr(err) {
addrErr := err.(*models.ErrInvalidCloneAddr) addrErr := err.(*git.ErrInvalidCloneAddr)
switch { switch {
case addrErr.IsProtocolInvalid: case addrErr.IsProtocolInvalid:
ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Invalid mirror protocol") ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Invalid mirror protocol")

View File

@ -7,13 +7,13 @@ import (
"net/http" "net/http"
"time" "time"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
pull_service "code.gitea.io/gitea/services/pull"
"code.gitea.io/gitea/services/repository/files" "code.gitea.io/gitea/services/repository/files"
) )
@ -92,12 +92,12 @@ func ApplyDiffPatch(ctx *context.APIContext) {
fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts) fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts)
if err != nil { if err != nil {
if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) { if files.IsErrUserCannotCommit(err) || pull_service.IsErrFilePathProtected(err) {
ctx.Error(http.StatusForbidden, "Access", err) ctx.Error(http.StatusForbidden, "Access", err)
return return
} }
if git_model.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) || if git_model.IsErrBranchAlreadyExists(err) || files.IsErrFilenameInvalid(err) || pull_service.IsErrSHADoesNotMatch(err) ||
models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) { files.IsErrFilePathInvalid(err) || files.IsErrRepoFileAlreadyExists(err) {
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err) ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
return return
} }

View File

@ -12,7 +12,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
activities_model "code.gitea.io/gitea/models/activities" activities_model "code.gitea.io/gitea/models/activities"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -765,7 +764,7 @@ func EditPullRequest(ctx *context.APIContext) {
} else if issues_model.IsErrIssueIsClosed(err) { } else if issues_model.IsErrIssueIsClosed(err) {
ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err) ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err)
return return
} else if models.IsErrPullRequestHasMerged(err) { } else if pull_service.IsErrPullRequestHasMerged(err) {
ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err) ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err)
return return
} }
@ -941,7 +940,7 @@ func MergePullRequest(ctx *context.APIContext) {
ctx.Error(http.StatusMethodNotAllowed, "PR is a work in progress", "Work in progress PRs cannot be merged") ctx.Error(http.StatusMethodNotAllowed, "PR is a work in progress", "Work in progress PRs cannot be merged")
} else if errors.Is(err, pull_service.ErrNotMergeableState) { } else if errors.Is(err, pull_service.ErrNotMergeableState) {
ctx.Error(http.StatusMethodNotAllowed, "PR not in mergeable state", "Please try again later") ctx.Error(http.StatusMethodNotAllowed, "PR not in mergeable state", "Please try again later")
} else if models.IsErrDisallowedToMerge(err) { } else if pull_service.IsErrDisallowedToMerge(err) {
ctx.Error(http.StatusMethodNotAllowed, "PR is not ready to be merged", err) ctx.Error(http.StatusMethodNotAllowed, "PR is not ready to be merged", err)
} else if asymkey_service.IsErrWontSign(err) { } else if asymkey_service.IsErrWontSign(err) {
ctx.Error(http.StatusMethodNotAllowed, fmt.Sprintf("Protected branch %s requires signed commits but this merge would not be signed", pr.BaseBranch), err) ctx.Error(http.StatusMethodNotAllowed, fmt.Sprintf("Protected branch %s requires signed commits but this merge would not be signed", pr.BaseBranch), err)
@ -954,7 +953,7 @@ func MergePullRequest(ctx *context.APIContext) {
// handle manually-merged mark // handle manually-merged mark
if manuallyMerged { if manuallyMerged {
if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
if models.IsErrInvalidMergeStyle(err) { if pull_service.IsErrInvalidMergeStyle(err) {
ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do))) ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
return return
} }
@ -1004,20 +1003,20 @@ func MergePullRequest(ctx *context.APIContext) {
} }
if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil { if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil {
if models.IsErrInvalidMergeStyle(err) { if pull_service.IsErrInvalidMergeStyle(err) {
ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do))) ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
} else if models.IsErrMergeConflicts(err) { } else if pull_service.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts) conflictError := err.(pull_service.ErrMergeConflicts)
ctx.JSON(http.StatusConflict, conflictError) ctx.JSON(http.StatusConflict, conflictError)
} else if models.IsErrRebaseConflicts(err) { } else if pull_service.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts) conflictError := err.(pull_service.ErrRebaseConflicts)
ctx.JSON(http.StatusConflict, conflictError) ctx.JSON(http.StatusConflict, conflictError)
} else if models.IsErrMergeUnrelatedHistories(err) { } else if pull_service.IsErrMergeUnrelatedHistories(err) {
conflictError := err.(models.ErrMergeUnrelatedHistories) conflictError := err.(pull_service.ErrMergeUnrelatedHistories)
ctx.JSON(http.StatusConflict, conflictError) ctx.JSON(http.StatusConflict, conflictError)
} else if git.IsErrPushOutOfDate(err) { } else if git.IsErrPushOutOfDate(err) {
ctx.Error(http.StatusConflict, "Merge", "merge push out of date") ctx.Error(http.StatusConflict, "Merge", "merge push out of date")
} else if models.IsErrSHADoesNotMatch(err) { } else if pull_service.IsErrSHADoesNotMatch(err) {
ctx.Error(http.StatusConflict, "Merge", "head out of date") ctx.Error(http.StatusConflict, "Merge", "head out of date")
} else if git.IsErrPushRejected(err) { } else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected) errPushRej := err.(*git.ErrPushRejected)
@ -1308,10 +1307,10 @@ func UpdatePullRequest(ctx *context.APIContext) {
message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch) message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch)
if err = pull_service.Update(ctx, pr, ctx.Doer, message, rebase); err != nil { if err = pull_service.Update(ctx, pr, ctx.Doer, message, rebase); err != nil {
if models.IsErrMergeConflicts(err) { if pull_service.IsErrMergeConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict") ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict")
return return
} else if models.IsErrRebaseConflicts(err) { } else if pull_service.IsErrRebaseConflicts(err) {
ctx.Error(http.StatusConflict, "Update", "rebase failed because of conflict") ctx.Error(http.StatusConflict, "Update", "rebase failed because of conflict")
return return
} }

View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
@ -250,7 +249,7 @@ func CreateRelease(ctx *context.APIContext) {
if err := release_service.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil { if err := release_service.CreateRelease(ctx.Repo.GitRepo, rel, nil, ""); err != nil {
if repo_model.IsErrReleaseAlreadyExist(err) { if repo_model.IsErrReleaseAlreadyExist(err) {
ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err) ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err)
} else if models.IsErrProtectedTagName(err) { } else if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "ProtectedTagName", err) ctx.Error(http.StatusUnprocessableEntity, "ProtectedTagName", err)
} else if git.IsErrNotExist(err) { } else if git.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "ErrNotExist", fmt.Errorf("target \"%v\" not found: %w", rel.Target, err)) ctx.Error(http.StatusNotFound, "ErrNotExist", fmt.Errorf("target \"%v\" not found: %w", rel.Target, err))
@ -408,7 +407,7 @@ func DeleteRelease(ctx *context.APIContext) {
return return
} }
if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil { if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }

View File

@ -6,11 +6,10 @@ package repo
import ( import (
"net/http" "net/http"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
releaseservice "code.gitea.io/gitea/services/release" release_service "code.gitea.io/gitea/services/release"
) )
// GetReleaseByTag get a single release of a repository by tag name // GetReleaseByTag get a single release of a repository by tag name
@ -112,8 +111,8 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
return return
} }
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil { if err = release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }

View File

@ -9,7 +9,6 @@ import (
"net/http" "net/http"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
@ -19,7 +18,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
releaseservice "code.gitea.io/gitea/services/release" release_service "code.gitea.io/gitea/services/release"
) )
// ListTags list all the tags of a repository // ListTags list all the tags of a repository
@ -205,12 +204,12 @@ func CreateTag(ctx *context.APIContext) {
return return
} }
if err := releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil { if err := release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil {
if models.IsErrTagAlreadyExists(err) { if release_service.IsErrTagAlreadyExists(err) {
ctx.Error(http.StatusConflict, "tag exist", err) ctx.Error(http.StatusConflict, "tag exist", err)
return return
} }
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "CreateNewTag", "user not allowed to create protected tag") ctx.Error(http.StatusUnprocessableEntity, "CreateNewTag", "user not allowed to create protected tag")
return return
} }
@ -280,8 +279,8 @@ func DeleteTag(ctx *context.APIContext) {
return return
} }
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil { if err = release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil {
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusUnprocessableEntity, "delTag", "user not allowed to delete protected tag")
return return
} }

View File

@ -8,7 +8,6 @@ import (
"net/http" "net/http"
"os" "os"
"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey" asymkey_model "code.gitea.io/gitea/models/asymkey"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -237,7 +236,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
if len(globs) > 0 { if len(globs) > 0 {
_, err := pull_service.CheckFileProtection(gitRepo, branchName, oldCommitID, newCommitID, globs, 1, ctx.env) _, err := pull_service.CheckFileProtection(gitRepo, branchName, oldCommitID, newCommitID, globs, 1, ctx.env)
if err != nil { if err != nil {
if !models.IsErrFilePathProtected(err) { if !pull_service.IsErrFilePathProtected(err) {
log.Error("Unable to check file protection for commits from %s to %s in %-v: %v", oldCommitID, newCommitID, repo, err) log.Error("Unable to check file protection for commits from %s to %s in %-v: %v", oldCommitID, newCommitID, repo, err)
ctx.JSON(http.StatusInternalServerError, private.Response{ ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Unable to check file protection for commits from %s to %s: %v", oldCommitID, newCommitID, err), Err: fmt.Sprintf("Unable to check file protection for commits from %s to %s: %v", oldCommitID, newCommitID, err),
@ -246,7 +245,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
} }
changedProtectedfiles = true changedProtectedfiles = true
protectedFilePath = err.(models.ErrFilePathProtected).Path protectedFilePath = err.(pull_service.ErrFilePathProtected).Path
} }
} }
@ -374,7 +373,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
// Check all status checks and reviews are ok // Check all status checks and reviews are ok
if err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil { if err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil {
if models.IsErrDisallowedToMerge(err) { if pull_service.IsErrDisallowedToMerge(err) {
log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error()) log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error())
ctx.JSON(http.StatusForbidden, private.Response{ ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("Not allowed to push to protected branch %s and pr #%d is not ready to be merged: %s", branchName, ctx.opts.PullRequestID, err.Error()), UserMsg: fmt.Sprintf("Not allowed to push to protected branch %s and pr #%d is not ready to be merged: %s", branchName, ctx.opts.PullRequestID, err.Error()),

View File

@ -11,10 +11,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization" org_model "code.gitea.io/gitea/models/organization"
packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/auth/password"
@ -446,7 +446,7 @@ func EditUserPost(ctx *context.Context) {
} }
if err := user_service.UpdateUser(ctx, u, opts); err != nil { if err := user_service.UpdateUser(ctx, u, opts); err != nil {
if models.IsErrDeleteLastAdminUser(err) { if user_model.IsErrDeleteLastAdminUser(err) {
ctx.RenderWithErr(ctx.Tr("auth.last_admin"), tplUserEdit, &form) ctx.RenderWithErr(ctx.Tr("auth.last_admin"), tplUserEdit, &form)
} else { } else {
ctx.ServerError("UpdateUser", err) ctx.ServerError("UpdateUser", err)
@ -501,16 +501,16 @@ func DeleteUser(ctx *context.Context) {
if err = user_service.DeleteUser(ctx, u, ctx.FormBool("purge")); err != nil { if err = user_service.DeleteUser(ctx, u, ctx.FormBool("purge")); err != nil {
switch { switch {
case models.IsErrUserOwnRepos(err): case repo_model.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo")) ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid"))) ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
case models.IsErrUserHasOrgs(err): case org_model.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_has_org")) ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid"))) ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
case models.IsErrUserOwnPackages(err): case packages_model.IsErrUserOwnPackages(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_own_packages")) ctx.Flash.Error(ctx.Tr("admin.users.still_own_packages"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid"))) ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
case models.IsErrDeleteLastAdminUser(err): case user_model.IsErrDeleteLastAdminUser(err):
ctx.Flash.Error(ctx.Tr("auth.last_admin")) ctx.Flash.Error(ctx.Tr("auth.last_admin"))
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid"))) ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
default: default:

View File

@ -8,8 +8,8 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/models/webhook"
@ -178,10 +178,10 @@ func SettingsDelete(ctx *context.Context) {
} }
if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil { if err := org_service.DeleteOrganization(ctx, ctx.Org.Organization, false); err != nil {
if models.IsErrUserOwnRepos(err) { if repo_model.IsErrUserOwnRepos(err) {
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
} else if models.IsErrUserOwnPackages(err) { } else if packages_model.IsErrUserOwnPackages(err) {
ctx.Flash.Error(ctx.Tr("form.org_still_own_packages")) ctx.Flash.Error(ctx.Tr("form.org_still_own_packages"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/delete") ctx.Redirect(ctx.Org.OrgLink + "/settings/delete")
} else { } else {

View File

@ -11,7 +11,6 @@ import (
"net/url" "net/url"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
@ -26,6 +25,7 @@ import (
"code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/routers/utils"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/forms"
pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release" release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
) )
@ -203,14 +203,14 @@ func CreateBranch(ctx *context.Context) {
err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.Repo.CommitID, form.NewBranchName) err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.Repo.CommitID, form.NewBranchName)
} }
if err != nil { if err != nil {
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return return
} }
if models.IsErrTagAlreadyExists(err) { if release_service.IsErrTagAlreadyExists(err) {
e := err.(models.ErrTagAlreadyExists) e := err.(release_service.ErrTagAlreadyExists)
ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName)) ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return return
@ -267,7 +267,7 @@ func MergeUpstream(ctx *context.Context) {
if errors.Is(err, util.ErrNotExist) { if errors.Is(err, util.ErrNotExist) {
ctx.JSONError(ctx.Tr("error.not_found")) ctx.JSONError(ctx.Tr("error.not_found"))
return return
} else if models.IsErrMergeConflicts(err) { } else if pull_service.IsErrMergeConflicts(err) {
ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict")) ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict"))
return return
} }

View File

@ -8,7 +8,6 @@ import (
"errors" "errors"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@ -131,7 +130,7 @@ func CherryPickPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form)
return return
} else if models.IsErrCommitIDDoesNotMatch(err) { } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return return
} }
@ -168,7 +167,7 @@ func CherryPickPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplCherryPick, &form)
return return
} else if models.IsErrCommitIDDoesNotMatch(err) { } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return return
} }

View File

@ -10,7 +10,6 @@ import (
"path" "path"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
@ -303,12 +302,12 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else if git_model.IsErrLFSFileLocked(err) { } else if git_model.IsErrLFSFileLocked(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplEditFile, &form)
} else if models.IsErrFilenameInvalid(err) { } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplEditFile, &form)
} else if models.IsErrFilePathInvalid(err) { } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
if fileErr, ok := err.(models.ErrFilePathInvalid); ok { if fileErr, ok := err.(files_service.ErrFilePathInvalid); ok {
switch fileErr.Type { switch fileErr.Type {
case git.EntryModeSymlink: case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form)
@ -322,7 +321,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else { } else {
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
} }
} else if models.IsErrRepoFileAlreadyExists(err) { } else if files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplEditFile, &form)
} else if git.IsErrBranchNotExist(err) { } else if git.IsErrBranchNotExist(err) {
@ -340,7 +339,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} else { } else {
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
} }
} else if models.IsErrCommitIDDoesNotMatch(err) { } else if files_service.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching"), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching"), tplEditFile, &form)
} else if git.IsErrPushOutOfDate(err) { } else if git.IsErrPushOutOfDate(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date"), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date"), tplEditFile, &form)
@ -506,14 +505,14 @@ func DeleteFilePost(ctx *context.Context) {
Signoff: form.Signoff, Signoff: form.Signoff,
}); err != nil { }); err != nil {
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile // This is where we handle all the errors thrown by repofiles.DeleteRepoFile
if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) { if git.IsErrNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplDeleteFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplDeleteFile, &form)
} else if models.IsErrFilenameInvalid(err) { } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplDeleteFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplDeleteFile, &form)
} else if models.IsErrFilePathInvalid(err) { } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
if fileErr, ok := err.(models.ErrFilePathInvalid); ok { if fileErr, ok := err.(files_service.ErrFilePathInvalid); ok {
switch fileErr.Type { switch fileErr.Type {
case git.EntryModeSymlink: case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplDeleteFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplDeleteFile, &form)
@ -541,7 +540,7 @@ func DeleteFilePost(ctx *context.Context) {
} else { } else {
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
} }
} else if models.IsErrCommitIDDoesNotMatch(err) || git.IsErrPushOutOfDate(err) { } else if files_service.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_deleting", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplDeleteFile, &form)
} else if git.IsErrPushRejected(err) { } else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected) errPushRej := err.(*git.ErrPushRejected)
@ -715,12 +714,12 @@ func UploadFilePost(ctx *context.Context) {
if git_model.IsErrLFSFileLocked(err) { if git_model.IsErrLFSFileLocked(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplUploadFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_is_locked", err.(git_model.ErrLFSFileLocked).Path, err.(git_model.ErrLFSFileLocked).UserName), tplUploadFile, &form)
} else if models.IsErrFilenameInvalid(err) { } else if files_service.IsErrFilenameInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplUploadFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", form.TreePath), tplUploadFile, &form)
} else if models.IsErrFilePathInvalid(err) { } else if files_service.IsErrFilePathInvalid(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
fileErr := err.(models.ErrFilePathInvalid) fileErr := err.(files_service.ErrFilePathInvalid)
switch fileErr.Type { switch fileErr.Type {
case git.EntryModeSymlink: case git.EntryModeSymlink:
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplUploadFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplUploadFile, &form)
@ -731,7 +730,7 @@ func UploadFilePost(ctx *context.Context) {
default: default:
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
} }
} else if models.IsErrRepoFileAlreadyExists(err) { } else if files_service.IsErrRepoFileAlreadyExists(err) {
ctx.Data["Err_TreePath"] = true ctx.Data["Err_TreePath"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplUploadFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), tplUploadFile, &form)
} else if git.IsErrBranchNotExist(err) { } else if git.IsErrBranchNotExist(err) {

View File

@ -9,12 +9,12 @@ import (
"net/url" "net/url"
"strings" "strings"
"code.gitea.io/gitea/models"
admin_model "code.gitea.io/gitea/models/admin" admin_model "code.gitea.io/gitea/models/admin"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@ -123,8 +123,8 @@ func handleMigrateError(ctx *context.Context, owner *user_model.User, err error,
} }
func handleMigrateRemoteAddrError(ctx *context.Context, err error, tpl base.TplName, form *forms.MigrateRepoForm) { func handleMigrateRemoteAddrError(ctx *context.Context, err error, tpl base.TplName, form *forms.MigrateRepoForm) {
if models.IsErrInvalidCloneAddr(err) { if git.IsErrInvalidCloneAddr(err) {
addrErr := err.(*models.ErrInvalidCloneAddr) addrErr := err.(*git.ErrInvalidCloneAddr)
switch { switch {
case addrErr.IsProtocolInvalid: case addrErr.IsProtocolInvalid:
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tpl, form) ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tpl, form)
@ -176,7 +176,7 @@ func MigratePost(ctx *context.Context) {
return return
} }
remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword) remoteAddr, err := git.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer) err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
} }

View File

@ -6,7 +6,6 @@ package repo
import ( import (
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@ -101,7 +100,7 @@ func NewDiffPatchPost(ctx *context.Context) {
ctx.Data["Err_NewBranchName"] = true ctx.Data["Err_NewBranchName"] = true
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplEditFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplEditFile, &form)
return return
} else if models.IsErrCommitIDDoesNotMatch(err) { } else if files.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form) ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplPatchFile, &form)
return return
} }

View File

@ -14,7 +14,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
activities_model "code.gitea.io/gitea/models/activities" activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
@ -968,8 +967,8 @@ func UpdatePullRequest(ctx *context.Context) {
message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch) message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch)
if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil { if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
if models.IsErrMergeConflicts(err) { if pull_service.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts) conflictError := err.(pull_service.ErrMergeConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.merge_conflict"), "Message": ctx.Tr("repo.pulls.merge_conflict"),
"Summary": ctx.Tr("repo.pulls.merge_conflict_summary"), "Summary": ctx.Tr("repo.pulls.merge_conflict_summary"),
@ -982,8 +981,8 @@ func UpdatePullRequest(ctx *context.Context) {
ctx.Flash.Error(flashError) ctx.Flash.Error(flashError)
ctx.Redirect(issue.Link()) ctx.Redirect(issue.Link())
return return
} else if models.IsErrRebaseConflicts(err) { } else if pull_service.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts) conflictError := err.(pull_service.ErrRebaseConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)), "Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"), "Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
@ -1047,7 +1046,7 @@ func MergePullRequest(ctx *context.Context) {
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_wip")) ctx.JSONError(ctx.Tr("repo.pulls.no_merge_wip"))
case errors.Is(err, pull_service.ErrNotMergeableState): case errors.Is(err, pull_service.ErrNotMergeableState):
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready")) ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
case models.IsErrDisallowedToMerge(err): case pull_service.IsErrDisallowedToMerge(err):
ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready")) ctx.JSONError(ctx.Tr("repo.pulls.no_merge_not_ready"))
case asymkey_service.IsErrWontSign(err): case asymkey_service.IsErrWontSign(err):
ctx.JSONError(err.Error()) // has no translation ... ctx.JSONError(err.Error()) // has no translation ...
@ -1064,7 +1063,7 @@ func MergePullRequest(ctx *context.Context) {
if manuallyMerged { if manuallyMerged {
if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { if err := pull_service.MergedManually(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
switch { switch {
case models.IsErrInvalidMergeStyle(err): case pull_service.IsErrInvalidMergeStyle(err):
ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option")) ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
case strings.Contains(err.Error(), "Wrong commit ID"): case strings.Contains(err.Error(), "Wrong commit ID"):
ctx.JSONError(ctx.Tr("repo.pulls.wrong_commit_id")) ctx.JSONError(ctx.Tr("repo.pulls.wrong_commit_id"))
@ -1111,10 +1110,10 @@ func MergePullRequest(ctx *context.Context) {
} }
if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil { if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message, false); err != nil {
if models.IsErrInvalidMergeStyle(err) { if pull_service.IsErrInvalidMergeStyle(err) {
ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option")) ctx.JSONError(ctx.Tr("repo.pulls.invalid_merge_option"))
} else if models.IsErrMergeConflicts(err) { } else if pull_service.IsErrMergeConflicts(err) {
conflictError := err.(models.ErrMergeConflicts) conflictError := err.(pull_service.ErrMergeConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.editor.merge_conflict"), "Message": ctx.Tr("repo.editor.merge_conflict"),
"Summary": ctx.Tr("repo.editor.merge_conflict_summary"), "Summary": ctx.Tr("repo.editor.merge_conflict_summary"),
@ -1126,8 +1125,8 @@ func MergePullRequest(ctx *context.Context) {
} }
ctx.Flash.Error(flashError) ctx.Flash.Error(flashError)
ctx.JSONRedirect(issue.Link()) ctx.JSONRedirect(issue.Link())
} else if models.IsErrRebaseConflicts(err) { } else if pull_service.IsErrRebaseConflicts(err) {
conflictError := err.(models.ErrRebaseConflicts) conflictError := err.(pull_service.ErrRebaseConflicts)
flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{ flashError, err := ctx.RenderToHTML(tplAlertDetails, map[string]any{
"Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)), "Message": ctx.Tr("repo.pulls.rebase_conflict", utils.SanitizeFlashErrorString(conflictError.CommitSHA)),
"Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"), "Summary": ctx.Tr("repo.pulls.rebase_conflict_summary"),
@ -1139,7 +1138,7 @@ func MergePullRequest(ctx *context.Context) {
} }
ctx.Flash.Error(flashError) ctx.Flash.Error(flashError)
ctx.JSONRedirect(issue.Link()) ctx.JSONRedirect(issue.Link())
} else if models.IsErrMergeUnrelatedHistories(err) { } else if pull_service.IsErrMergeUnrelatedHistories(err) {
log.Debug("MergeUnrelatedHistories error: %v", err) log.Debug("MergeUnrelatedHistories error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories")) ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories"))
ctx.JSONRedirect(issue.Link()) ctx.JSONRedirect(issue.Link())
@ -1147,7 +1146,7 @@ func MergePullRequest(ctx *context.Context) {
log.Debug("MergePushOutOfDate error: %v", err) log.Debug("MergePushOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date")) ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date"))
ctx.JSONRedirect(issue.Link()) ctx.JSONRedirect(issue.Link())
} else if models.IsErrSHADoesNotMatch(err) { } else if pull_service.IsErrSHADoesNotMatch(err) {
log.Debug("MergeHeadOutOfDate error: %v", err) log.Debug("MergeHeadOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.head_out_of_date")) ctx.Flash.Error(ctx.Tr("repo.pulls.head_out_of_date"))
ctx.JSONRedirect(issue.Link()) ctx.JSONRedirect(issue.Link())
@ -1606,7 +1605,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
"error": err.Error(), "error": err.Error(),
"user_error": errorMessage, "user_error": errorMessage,
}) })
} else if models.IsErrPullRequestHasMerged(err) { } else if pull_service.IsErrPullRequestHasMerged(err) {
errorMessage := ctx.Tr("repo.pulls.has_merged") errorMessage := ctx.Tr("repo.pulls.has_merged")
ctx.Flash.Error(errorMessage) ctx.Flash.Error(errorMessage)

View File

@ -10,7 +10,6 @@ import (
"net/http" "net/http"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/renderhelper" "code.gitea.io/gitea/models/renderhelper"
@ -30,7 +29,7 @@ import (
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/context/upload" "code.gitea.io/gitea/services/context/upload"
"code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/forms"
releaseservice "code.gitea.io/gitea/services/release" release_service "code.gitea.io/gitea/services/release"
) )
const ( const (
@ -432,27 +431,27 @@ func NewReleasePost(ctx *context.Context) {
} }
if len(form.TagOnly) > 0 { if len(form.TagOnly) > 0 {
if err = releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil { if err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
if models.IsErrTagAlreadyExists(err) { if release_service.IsErrTagAlreadyExists(err) {
e := err.(models.ErrTagAlreadyExists) e := err.(release_service.ErrTagAlreadyExists)
ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName)) ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return return
} }
if models.IsErrInvalidTagName(err) { if release_service.IsErrInvalidTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_invalid")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_invalid"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return return
} }
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()) ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL())
return return
} }
ctx.ServerError("releaseservice.CreateNewTag", err) ctx.ServerError("release_service.CreateNewTag", err)
return return
} }
@ -475,14 +474,14 @@ func NewReleasePost(ctx *context.Context) {
IsTag: false, IsTag: false,
} }
if err = releaseservice.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil { if err = release_service.CreateRelease(ctx.Repo.GitRepo, rel, attachmentUUIDs, msg); err != nil {
ctx.Data["Err_TagName"] = true ctx.Data["Err_TagName"] = true
switch { switch {
case repo_model.IsErrReleaseAlreadyExist(err): case repo_model.IsErrReleaseAlreadyExist(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form) ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), tplReleaseNew, &form)
case models.IsErrInvalidTagName(err): case release_service.IsErrInvalidTagName(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form) ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), tplReleaseNew, &form)
case models.IsErrProtectedTagName(err): case release_service.IsErrProtectedTagName(err):
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_protected"), tplReleaseNew, &form) ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_protected"), tplReleaseNew, &form)
default: default:
ctx.ServerError("CreateRelease", err) ctx.ServerError("CreateRelease", err)
@ -504,7 +503,7 @@ func NewReleasePost(ctx *context.Context) {
rel.PublisherID = ctx.Doer.ID rel.PublisherID = ctx.Doer.ID
rel.IsTag = false rel.IsTag = false
if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil { if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
ctx.Data["Err_TagName"] = true ctx.Data["Err_TagName"] = true
ctx.ServerError("UpdateRelease", err) ctx.ServerError("UpdateRelease", err)
return return
@ -610,7 +609,7 @@ func EditReleasePost(ctx *context.Context) {
rel.Note = form.Content rel.Note = form.Content
rel.IsDraft = len(form.Draft) > 0 rel.IsDraft = len(form.Draft) > 0
rel.IsPrerelease = form.Prerelease rel.IsPrerelease = form.Prerelease
if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo,
rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments); err != nil { rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments); err != nil {
ctx.ServerError("UpdateRelease", err) ctx.ServerError("UpdateRelease", err)
return return
@ -649,8 +648,8 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
return return
} }
if err := releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil { if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil {
if models.IsErrProtectedTagName(err) { if release_service.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
} else { } else {
ctx.Flash.Error("DeleteReleaseByID: " + err.Error()) ctx.Flash.Error("DeleteReleaseByID: " + err.Error())

View File

@ -11,7 +11,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions" actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
@ -223,7 +222,7 @@ func SettingsPost(ctx *context.Context) {
form.MirrorPassword, _ = u.User.Password() form.MirrorPassword, _ = u.User.Password()
} }
address, err := forms.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword) address, err := git.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.Doer) err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
} }
@ -385,7 +384,7 @@ func SettingsPost(ctx *context.Context) {
return return
} }
address, err := forms.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword) address, err := git.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword)
if err == nil { if err == nil {
err = migrations.IsMigrateURLAllowed(address, ctx.Doer) err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
} }
@ -980,8 +979,8 @@ func SettingsPost(ctx *context.Context) {
} }
func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.RepoSettingForm) { func handleSettingRemoteAddrError(ctx *context.Context, err error, form *forms.RepoSettingForm) {
if models.IsErrInvalidCloneAddr(err) { if git.IsErrInvalidCloneAddr(err) {
addrErr := err.(*models.ErrInvalidCloneAddr) addrErr := err.(*git.ErrInvalidCloneAddr)
switch { switch {
case addrErr.IsProtocolInvalid: case addrErr.IsProtocolInvalid:
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, form) ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, form)

View File

@ -10,7 +10,9 @@ import (
"net/http" "net/http"
"time" "time"
"code.gitea.io/gitea/models" org_model "code.gitea.io/gitea/models/organization"
packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@ -301,16 +303,16 @@ func DeleteAccount(ctx *context.Context) {
if err := user.DeleteUser(ctx, ctx.Doer, false); err != nil { if err := user.DeleteUser(ctx, ctx.Doer, false); err != nil {
switch { switch {
case models.IsErrUserOwnRepos(err): case repo_model.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("form.still_own_repo")) ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account") ctx.Redirect(setting.AppSubURL + "/user/settings/account")
case models.IsErrUserHasOrgs(err): case org_model.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("form.still_has_org")) ctx.Flash.Error(ctx.Tr("form.still_has_org"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account") ctx.Redirect(setting.AppSubURL + "/user/settings/account")
case models.IsErrUserOwnPackages(err): case packages_model.IsErrUserOwnPackages(err):
ctx.Flash.Error(ctx.Tr("form.still_own_packages")) ctx.Flash.Error(ctx.Tr("form.still_own_packages"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account") ctx.Redirect(setting.AppSubURL + "/user/settings/account")
case models.IsErrDeleteLastAdminUser(err): case user_model.IsErrDeleteLastAdminUser(err):
ctx.Flash.Error(ctx.Tr("auth.last_admin")) ctx.Flash.Error(ctx.Tr("auth.last_admin"))
ctx.Redirect(setting.AppSubURL + "/user/settings/account") ctx.Redirect(setting.AppSubURL + "/user/settings/account")
default: default:

View File

@ -6,10 +6,8 @@ package forms
import ( import (
"net/http" "net/http"
"net/url"
"strings" "strings"
"code.gitea.io/gitea/models"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
project_model "code.gitea.io/gitea/models/project" project_model "code.gitea.io/gitea/models/project"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -90,27 +88,6 @@ func (f *MigrateRepoForm) Validate(req *http.Request, errs binding.Errors) bindi
return middleware.Validate(errs, ctx.Data, f, ctx.Locale) return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
} }
// ParseRemoteAddr checks if given remote address is valid,
// and returns composed URL with needed username and password.
func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
remoteAddr = strings.TrimSpace(remoteAddr)
// Remote address can be HTTP/HTTPS/Git URL or local path.
if strings.HasPrefix(remoteAddr, "http://") ||
strings.HasPrefix(remoteAddr, "https://") ||
strings.HasPrefix(remoteAddr, "git://") {
u, err := url.Parse(remoteAddr)
if err != nil {
return "", &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteAddr}
}
if len(authUsername)+len(authPassword) > 0 {
u.User = url.UserPassword(authUsername, authPassword)
}
remoteAddr = u.String()
}
return remoteAddr, nil
}
// RepoSettingForm form for changing repository settings // RepoSettingForm form for changing repository settings
type RepoSettingForm struct { type RepoSettingForm struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`

View File

@ -12,10 +12,10 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
system_model "code.gitea.io/gitea/models/system" system_model "code.gitea.io/gitea/models/system"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/hostmatcher"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration" base "code.gitea.io/gitea/modules/migration"
@ -43,16 +43,16 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
// Remote address can be HTTP/HTTPS/Git URL or local path. // Remote address can be HTTP/HTTPS/Git URL or local path.
u, err := url.Parse(remoteURL) u, err := url.Parse(remoteURL)
if err != nil { if err != nil {
return &models.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL} return &git.ErrInvalidCloneAddr{IsURLError: true, Host: remoteURL}
} }
if u.Scheme == "file" || u.Scheme == "" { if u.Scheme == "file" || u.Scheme == "" {
if !doer.CanImportLocal() { if !doer.CanImportLocal() {
return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsPermissionDenied: true, LocalPath: true} return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsPermissionDenied: true, LocalPath: true}
} }
isAbs := filepath.IsAbs(u.Host + u.Path) isAbs := filepath.IsAbs(u.Host + u.Path)
if !isAbs { if !isAbs {
return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true}
} }
isDir, err := util.IsDir(u.Host + u.Path) isDir, err := util.IsDir(u.Host + u.Path)
if err != nil { if err != nil {
@ -60,18 +60,18 @@ func IsMigrateURLAllowed(remoteURL string, doer *user_model.User) error {
return err return err
} }
if !isDir { if !isDir {
return &models.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true} return &git.ErrInvalidCloneAddr{Host: "<LOCAL_FILESYSTEM>", IsInvalidPath: true, LocalPath: true}
} }
return nil return nil
} }
if u.Scheme == "git" && u.Port() != "" && (strings.Contains(remoteURL, "%0d") || strings.Contains(remoteURL, "%0a")) { if u.Scheme == "git" && u.Port() != "" && (strings.Contains(remoteURL, "%0d") || strings.Contains(remoteURL, "%0a")) {
return &models.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true} return &git.ErrInvalidCloneAddr{Host: u.Host, IsURLError: true}
} }
if u.Opaque != "" || u.Scheme != "" && u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "git" { if u.Opaque != "" || u.Scheme != "" && u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "git" {
return &models.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true} return &git.ErrInvalidCloneAddr{Host: u.Host, IsProtocolInvalid: true, IsPermissionDenied: true, IsURLError: true}
} }
hostName, _, err := net.SplitHostPort(u.Host) hostName, _, err := net.SplitHostPort(u.Host)
@ -95,12 +95,12 @@ func checkByAllowBlockList(hostName string, addrList []net.IP) error {
} }
var blockedError error var blockedError error
if blockList.MatchHostName(hostName) || ipBlocked { if blockList.MatchHostName(hostName) || ipBlocked {
blockedError = &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} blockedError = &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
} }
// if we have an allow-list, check the allow-list before return to get the more accurate error // if we have an allow-list, check the allow-list before return to get the more accurate error
if !allowList.IsEmpty() { if !allowList.IsEmpty() {
if !allowList.MatchHostName(hostName) && !ipAllowed { if !allowList.MatchHostName(hostName) && !ipAllowed {
return &models.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true} return &git.ErrInvalidCloneAddr{Host: hostName, IsPermissionDenied: true}
} }
} }
// otherwise, we always follow the blocked list // otherwise, we always follow the blocked list

View File

@ -7,7 +7,6 @@ import (
"context" "context"
"fmt" "fmt"
"code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions" actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization" org_model "code.gitea.io/gitea/models/organization"
@ -67,14 +66,14 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge
if err != nil { if err != nil {
return fmt.Errorf("GetRepositoryCount: %w", err) return fmt.Errorf("GetRepositoryCount: %w", err)
} else if count > 0 { } else if count > 0 {
return models.ErrUserOwnRepos{UID: org.ID} return repo_model.ErrUserOwnRepos{UID: org.ID}
} }
// Check ownership of packages. // Check ownership of packages.
if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil { if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil {
return fmt.Errorf("HasOwnerPackages: %w", err) return fmt.Errorf("HasOwnerPackages: %w", err)
} else if ownsPackages { } else if ownsPackages {
return models.ErrUserOwnPackages{UID: org.ID} return packages_model.ErrUserOwnPackages{UID: org.ID}
} }
if err := deleteOrganization(ctx, org); err != nil { if err := deleteOrganization(ctx, org); err != nil {

View File

@ -6,9 +6,9 @@ package org
import ( import (
"testing" "testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -30,7 +30,7 @@ func TestDeleteOrganization(t *testing.T) {
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
err := DeleteOrganization(db.DefaultContext, org, false) err := DeleteOrganization(db.DefaultContext, org, false)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, models.IsErrUserOwnRepos(err)) assert.True(t, repo_model.IsErrUserOwnRepos(err))
user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5})
assert.Error(t, DeleteOrganization(db.DefaultContext, user, false)) assert.Error(t, DeleteOrganization(db.DefaultContext, user, false))

View File

@ -11,7 +11,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -36,7 +35,7 @@ var prPatchCheckerQueue *queue.WorkerPoolQueue[string]
var ( var (
ErrIsClosed = errors.New("pull is closed") ErrIsClosed = errors.New("pull is closed")
ErrUserNotAllowedToMerge = models.ErrDisallowedToMerge{} ErrUserNotAllowedToMerge = ErrDisallowedToMerge{}
ErrHasMerged = errors.New("has already been merged") ErrHasMerged = errors.New("has already been merged")
ErrIsWorkInProgress = errors.New("work in progress PRs cannot be merged") ErrIsWorkInProgress = errors.New("work in progress PRs cannot be merged")
ErrIsChecking = errors.New("cannot merge while conflict checking is in progress") ErrIsChecking = errors.New("cannot merge while conflict checking is in progress")
@ -106,7 +105,7 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc
} }
if err := CheckPullBranchProtections(ctx, pr, false); err != nil { if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
if !models.IsErrDisallowedToMerge(err) { if !IsErrDisallowedToMerge(err) {
log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err) log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err)
return err return err
} }

View File

@ -13,7 +13,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -30,6 +29,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
issue_service "code.gitea.io/gitea/services/issue" issue_service "code.gitea.io/gitea/services/issue"
notify_service "code.gitea.io/gitea/services/notify" notify_service "code.gitea.io/gitea/services/notify"
) )
@ -159,6 +159,27 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr
return getMergeMessage(ctx, baseGitRepo, pr, mergeStyle, nil) return getMergeMessage(ctx, baseGitRepo, pr, mergeStyle, nil)
} }
// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy
type ErrInvalidMergeStyle struct {
ID int64
Style repo_model.MergeStyle
}
// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle.
func IsErrInvalidMergeStyle(err error) bool {
_, ok := err.(ErrInvalidMergeStyle)
return ok
}
func (err ErrInvalidMergeStyle) Error() string {
return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]",
err.ID, err.Style)
}
func (err ErrInvalidMergeStyle) Unwrap() error {
return util.ErrInvalidArgument
}
// Merge merges pull request to base repository. // Merge merges pull request to base repository.
// Caller should check PR is ready to be merged (review and status checks) // Caller should check PR is ready to be merged (review and status checks)
func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error { func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error {
@ -179,7 +200,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
// Check if merge style is correct and allowed // Check if merge style is correct and allowed
if !prConfig.IsMergeStyleAllowed(mergeStyle) { if !prConfig.IsMergeStyleAllowed(mergeStyle) {
return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
} }
releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID)) releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID))
@ -283,7 +304,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
return "", err return "", err
} }
default: default:
return "", models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} return "", ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
} }
// OK we should cache our current head and origin/headbranch // OK we should cache our current head and origin/headbranch
@ -374,13 +395,66 @@ func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
return nil return nil
} }
// ErrMergeConflicts represents an error if merging fails with a conflict
type ErrMergeConflicts struct {
Style repo_model.MergeStyle
StdOut string
StdErr string
Err error
}
// IsErrMergeConflicts checks if an error is a ErrMergeConflicts.
func IsErrMergeConflicts(err error) bool {
_, ok := err.(ErrMergeConflicts)
return ok
}
func (err ErrMergeConflicts) Error() string {
return fmt.Sprintf("Merge Conflict Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
// ErrMergeUnrelatedHistories represents an error if merging fails due to unrelated histories
type ErrMergeUnrelatedHistories struct {
Style repo_model.MergeStyle
StdOut string
StdErr string
Err error
}
// IsErrMergeUnrelatedHistories checks if an error is a ErrMergeUnrelatedHistories.
func IsErrMergeUnrelatedHistories(err error) bool {
_, ok := err.(ErrMergeUnrelatedHistories)
return ok
}
func (err ErrMergeUnrelatedHistories) Error() string {
return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge
type ErrMergeDivergingFastForwardOnly struct {
StdOut string
StdErr string
Err error
}
// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly.
func IsErrMergeDivergingFastForwardOnly(err error) bool {
_, ok := err.(ErrMergeDivergingFastForwardOnly)
return ok
}
func (err ErrMergeDivergingFastForwardOnly) Error() string {
return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error { func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error {
if err := cmd.Run(ctx.RunOpts()); err != nil { if err := cmd.Run(ctx.RunOpts()); err != nil {
// Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict // Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict
if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil { if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil {
// We have a merge conflict error // We have a merge conflict error
log.Debug("MergeConflict %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Debug("MergeConflict %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrMergeConflicts{ return ErrMergeConflicts{
Style: mergeStyle, Style: mergeStyle,
StdOut: ctx.outbuf.String(), StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(), StdErr: ctx.errbuf.String(),
@ -388,7 +462,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g
} }
} else if strings.Contains(ctx.errbuf.String(), "refusing to merge unrelated histories") { } else if strings.Contains(ctx.errbuf.String(), "refusing to merge unrelated histories") {
log.Debug("MergeUnrelatedHistories %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Debug("MergeUnrelatedHistories %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrMergeUnrelatedHistories{ return ErrMergeUnrelatedHistories{
Style: mergeStyle, Style: mergeStyle,
StdOut: ctx.outbuf.String(), StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(), StdErr: ctx.errbuf.String(),
@ -396,7 +470,7 @@ func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *g
} }
} else if mergeStyle == repo_model.MergeStyleFastForwardOnly && strings.Contains(ctx.errbuf.String(), "Not possible to fast-forward, aborting") { } else if mergeStyle == repo_model.MergeStyleFastForwardOnly && strings.Contains(ctx.errbuf.String(), "Not possible to fast-forward, aborting") {
log.Debug("MergeDivergingFastForwardOnly %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Debug("MergeDivergingFastForwardOnly %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrMergeDivergingFastForwardOnly{ return ErrMergeDivergingFastForwardOnly{
StdOut: ctx.outbuf.String(), StdOut: ctx.outbuf.String(),
StdErr: ctx.errbuf.String(), StdErr: ctx.errbuf.String(),
Err: err, Err: err,
@ -431,6 +505,25 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a
return false, nil return false, nil
} }
// ErrDisallowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it.
type ErrDisallowedToMerge struct {
Reason string
}
// IsErrDisallowedToMerge checks if an error is an ErrDisallowedToMerge.
func IsErrDisallowedToMerge(err error) bool {
_, ok := err.(ErrDisallowedToMerge)
return ok
}
func (err ErrDisallowedToMerge) Error() string {
return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason)
}
func (err ErrDisallowedToMerge) Unwrap() error {
return util.ErrPermissionDenied
}
// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks) // CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks)
func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) { func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) {
if err = pr.LoadBaseRepo(ctx); err != nil { if err = pr.LoadBaseRepo(ctx); err != nil {
@ -450,29 +543,29 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
return err return err
} }
if !isPass { if !isPass {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "Not all required status checks successful", Reason: "Not all required status checks successful",
} }
} }
if !issues_model.HasEnoughApprovals(ctx, pb, pr) { if !issues_model.HasEnoughApprovals(ctx, pb, pr) {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "Does not have enough approvals", Reason: "Does not have enough approvals",
} }
} }
if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) { if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "There are requested changes", Reason: "There are requested changes",
} }
} }
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) { if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "There are official review requests", Reason: "There are official review requests",
} }
} }
if issues_model.MergeBlockedByOutdatedBranch(pb, pr) { if issues_model.MergeBlockedByOutdatedBranch(pb, pr) {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "The head branch is behind the base branch", Reason: "The head branch is behind the base branch",
} }
} }
@ -482,7 +575,7 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
} }
if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) { if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
return models.ErrDisallowedToMerge{ return ErrDisallowedToMerge{
Reason: "Changed protected files", Reason: "Changed protected files",
} }
} }
@ -511,7 +604,7 @@ func MergedManually(ctx context.Context, pr *issues_model.PullRequest, doer *use
// Check if merge style is correct and allowed // Check if merge style is correct and allowed
if !prConfig.IsMergeStyleAllowed(repo_model.MergeStyleManuallyMerged) { if !prConfig.IsMergeStyleAllowed(repo_model.MergeStyleManuallyMerged) {
return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged} return ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: repo_model.MergeStyleManuallyMerged}
} }
objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName) objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName)

View File

@ -14,7 +14,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -43,6 +42,23 @@ func (ctx *mergeContext) RunOpts() *git.RunOpts {
} }
} }
// ErrSHADoesNotMatch represents a "SHADoesNotMatch" kind of error.
type ErrSHADoesNotMatch struct {
Path string
GivenSHA string
CurrentSHA string
}
// IsErrSHADoesNotMatch checks if an error is a ErrSHADoesNotMatch.
func IsErrSHADoesNotMatch(err error) bool {
_, ok := err.(ErrSHADoesNotMatch)
return ok
}
func (err ErrSHADoesNotMatch) Error() string {
return fmt.Sprintf("sha does not match [given: %s, expected: %s]", err.GivenSHA, err.CurrentSHA)
}
func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, expectedHeadCommitID string) (mergeCtx *mergeContext, cancel context.CancelFunc, err error) { func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, expectedHeadCommitID string) (mergeCtx *mergeContext, cancel context.CancelFunc, err error) {
// Clone base repo. // Clone base repo.
prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr) prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
@ -65,7 +81,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
} }
if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID { if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID {
defer cancel() defer cancel()
return nil, nil, models.ErrSHADoesNotMatch{ return nil, nil, ErrSHADoesNotMatch{
GivenSHA: expectedHeadCommitID, GivenSHA: expectedHeadCommitID,
CurrentSHA: trackingCommitID, CurrentSHA: trackingCommitID,
} }
@ -233,8 +249,27 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, o
return err return err
} }
// ErrRebaseConflicts represents an error if rebase fails with a conflict
type ErrRebaseConflicts struct {
Style repo_model.MergeStyle
CommitSHA string
StdOut string
StdErr string
Err error
}
// IsErrRebaseConflicts checks if an error is a ErrRebaseConflicts.
func IsErrRebaseConflicts(err error) bool {
_, ok := err.(ErrRebaseConflicts)
return ok
}
func (err ErrRebaseConflicts) Error() string {
return fmt.Sprintf("Rebase Error: %v: Whilst Rebasing: %s\n%s\n%s", err.Err, err.CommitSHA, err.StdErr, err.StdOut)
}
// rebaseTrackingOnToBase checks out the tracking branch as staging and rebases it on to the base branch // rebaseTrackingOnToBase checks out the tracking branch as staging and rebases it on to the base branch
// if there is a conflict it will return a models.ErrRebaseConflicts // if there is a conflict it will return an ErrRebaseConflicts
func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error { func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error {
// Checkout head branch // Checkout head branch
if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch).
@ -268,11 +303,11 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle)
} }
} }
if !ok { if !ok {
log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as models.ErrRebaseConflicts.", ctx.pr) log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as ErrRebaseConflicts.", ctx.pr)
return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
} }
log.Debug("Conflict when rebasing staging on to base in %-v at %s: %v\n%s\n%s", ctx.pr, commitSha, err, ctx.outbuf.String(), ctx.errbuf.String()) log.Debug("Conflict when rebasing staging on to base in %-v at %s: %v\n%s\n%s", ctx.pr, commitSha, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrRebaseConflicts{ return ErrRebaseConflicts{
CommitSHA: commitSha, CommitSHA: commitSha,
Style: mergeStyle, Style: mergeStyle,
StdOut: ctx.outbuf.String(), StdOut: ctx.outbuf.String(),

View File

@ -13,7 +13,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
@ -502,6 +501,29 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
return false, nil return false, nil
} }
// ErrFilePathProtected represents a "FilePathProtected" kind of error.
type ErrFilePathProtected struct {
Message string
Path string
}
// IsErrFilePathProtected checks if an error is an ErrFilePathProtected.
func IsErrFilePathProtected(err error) bool {
_, ok := err.(ErrFilePathProtected)
return ok
}
func (err ErrFilePathProtected) Error() string {
if err.Message != "" {
return err.Message
}
return fmt.Sprintf("path is protected and can not be changed [path: %s]", err.Path)
}
func (err ErrFilePathProtected) Unwrap() error {
return util.ErrPermissionDenied
}
// CheckFileProtection check file Protection // CheckFileProtection check file Protection
func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) { func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string) ([]string, error) {
if len(patterns) == 0 { if len(patterns) == 0 {
@ -525,7 +547,7 @@ func CheckFileProtection(repo *git.Repository, branchName, oldCommitID, newCommi
} }
} }
if len(changedProtectedFiles) > 0 { if len(changedProtectedFiles) > 0 {
err = models.ErrFilePathProtected{ err = ErrFilePathProtected{
Path: changedProtectedFiles[0], Path: changedProtectedFiles[0],
} }
} }
@ -575,7 +597,7 @@ func checkPullFilesProtection(ctx context.Context, pr *issues_model.PullRequest,
} }
pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.HeadBranch, pr.MergeBase, "tracking", pb.GetProtectedFilePatterns(), 10, os.Environ()) pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.HeadBranch, pr.MergeBase, "tracking", pb.GetProtectedFilePatterns(), 10, os.Environ())
if err != nil && !models.IsErrFilePathProtected(err) { if err != nil && !IsErrFilePathProtected(err) {
return err return err
} }
return nil return nil

View File

@ -13,7 +13,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -224,6 +223,28 @@ func NewPullRequest(ctx context.Context, opts *NewPullRequestOptions) error {
return nil return nil
} }
// ErrPullRequestHasMerged represents a "PullRequestHasMerged"-error
type ErrPullRequestHasMerged struct {
ID int64
IssueID int64
HeadRepoID int64
BaseRepoID int64
HeadBranch string
BaseBranch string
}
// IsErrPullRequestHasMerged checks if an error is a ErrPullRequestHasMerged.
func IsErrPullRequestHasMerged(err error) bool {
_, ok := err.(ErrPullRequestHasMerged)
return ok
}
// Error does pretty-printing :D
func (err ErrPullRequestHasMerged) Error() string {
return fmt.Sprintf("pull request has merged [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
}
// ChangeTargetBranch changes the target branch of this pull request, as the given user. // ChangeTargetBranch changes the target branch of this pull request, as the given user.
func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, targetBranch string) (err error) { func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, targetBranch string) (err error) {
releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID)) releaser, err := globallock.Lock(ctx, getPullWorkingLockKey(pr.ID))
@ -247,7 +268,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
} }
if pr.HasMerged { if pr.HasMerged {
return models.ErrPullRequestHasMerged{ return ErrPullRequestHasMerged{
ID: pr.ID, ID: pr.ID,
IssueID: pr.Index, IssueID: pr.Index,
HeadRepoID: pr.HeadRepoID, HeadRepoID: pr.HeadRepoID,
@ -654,7 +675,7 @@ func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int6
if err = pr.Issue.LoadRepo(ctx); err != nil { if err = pr.Issue.LoadRepo(ctx); err != nil {
errs = append(errs, err) errs = append(errs, err)
} else if err = ChangeTargetBranch(ctx, pr, doer, targetBranch); err != nil && } else if err = ChangeTargetBranch(ctx, pr, doer, targetBranch); err != nil &&
!issues_model.IsErrIssueIsClosed(err) && !models.IsErrPullRequestHasMerged(err) && !issues_model.IsErrIssueIsClosed(err) && !IsErrPullRequestHasMerged(err) &&
!issues_model.IsErrPullRequestAlreadyExists(err) { !issues_model.IsErrPullRequestAlreadyExists(err) {
errs = append(errs, err) errs = append(errs, err)
} }

View File

@ -9,7 +9,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
@ -26,6 +25,44 @@ import (
notify_service "code.gitea.io/gitea/services/notify" notify_service "code.gitea.io/gitea/services/notify"
) )
// ErrInvalidTagName represents a "InvalidTagName" kind of error.
type ErrInvalidTagName struct {
TagName string
}
// IsErrInvalidTagName checks if an error is a ErrInvalidTagName.
func IsErrInvalidTagName(err error) bool {
_, ok := err.(ErrInvalidTagName)
return ok
}
func (err ErrInvalidTagName) Error() string {
return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
}
func (err ErrInvalidTagName) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrProtectedTagName represents a "ProtectedTagName" kind of error.
type ErrProtectedTagName struct {
TagName string
}
// IsErrProtectedTagName checks if an error is a ErrProtectedTagName.
func IsErrProtectedTagName(err error) bool {
_, ok := err.(ErrProtectedTagName)
return ok
}
func (err ErrProtectedTagName) Error() string {
return fmt.Sprintf("release tag name is protected [tag_name: %s]", err.TagName)
}
func (err ErrProtectedTagName) Unwrap() error {
return util.ErrPermissionDenied
}
func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) { func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Release, msg string) (bool, error) {
err := rel.LoadAttributes(ctx) err := rel.LoadAttributes(ctx)
if err != nil { if err != nil {
@ -58,7 +95,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
return false, err return false, err
} }
if !isAllowed { if !isAllowed {
return false, models.ErrProtectedTagName{ return false, ErrProtectedTagName{
TagName: rel.TagName, TagName: rel.TagName,
} }
} }
@ -71,7 +108,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
if len(msg) > 0 { if len(msg) > 0 {
if err = gitRepo.CreateAnnotatedTag(rel.TagName, msg, commit.ID.String()); err != nil { if err = gitRepo.CreateAnnotatedTag(rel.TagName, msg, commit.ID.String()); err != nil {
if strings.Contains(err.Error(), "is not a valid tag name") { if strings.Contains(err.Error(), "is not a valid tag name") {
return false, models.ErrInvalidTagName{ return false, ErrInvalidTagName{
TagName: rel.TagName, TagName: rel.TagName,
} }
} }
@ -79,7 +116,7 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
} }
} else if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { } else if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
if strings.Contains(err.Error(), "is not a valid tag name") { if strings.Contains(err.Error(), "is not a valid tag name") {
return false, models.ErrInvalidTagName{ return false, ErrInvalidTagName{
TagName: rel.TagName, TagName: rel.TagName,
} }
} }
@ -159,13 +196,32 @@ func CreateRelease(gitRepo *git.Repository, rel *repo_model.Release, attachmentU
return nil return nil
} }
// ErrTagAlreadyExists represents an error that tag with such name already exists.
type ErrTagAlreadyExists struct {
TagName string
}
// IsErrTagAlreadyExists checks if an error is an ErrTagAlreadyExists.
func IsErrTagAlreadyExists(err error) bool {
_, ok := err.(ErrTagAlreadyExists)
return ok
}
func (err ErrTagAlreadyExists) Error() string {
return fmt.Sprintf("tag already exists [name: %s]", err.TagName)
}
func (err ErrTagAlreadyExists) Unwrap() error {
return util.ErrAlreadyExist
}
// CreateNewTag creates a new repository tag // CreateNewTag creates a new repository tag
func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commit, tagName, msg string) error { func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commit, tagName, msg string) error {
has, err := repo_model.IsReleaseExist(ctx, repo.ID, tagName) has, err := repo_model.IsReleaseExist(ctx, repo.ID, tagName)
if err != nil { if err != nil {
return err return err
} else if has { } else if has {
return models.ErrTagAlreadyExists{ return ErrTagAlreadyExists{
TagName: tagName, TagName: tagName,
} }
} }
@ -320,7 +376,7 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
return err return err
} }
if !isAllowed { if !isAllowed {
return models.ErrProtectedTagName{ return ErrProtectedTagName{
TagName: rel.TagName, TagName: rel.TagName,
} }
} }

View File

@ -9,7 +9,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"code.gitea.io/gitea/models"
actions_model "code.gitea.io/gitea/models/actions" actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
@ -31,6 +30,7 @@ import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook" webhook_module "code.gitea.io/gitea/modules/webhook"
notify_service "code.gitea.io/gitea/services/notify" notify_service "code.gitea.io/gitea/services/notify"
release_service "code.gitea.io/gitea/services/release"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
"xorm.io/builder" "xorm.io/builder"
@ -274,7 +274,7 @@ func checkBranchName(ctx context.Context, repo *repo_model.Repository, name stri
BranchName: branchRefName, BranchName: branchRefName,
} }
case refName == git.TagPrefix+name: case refName == git.TagPrefix+name:
return models.ErrTagAlreadyExists{ return release_service.ErrTagAlreadyExists{
TagName: name, TagName: name,
} }
} }

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
@ -17,6 +16,22 @@ import (
"code.gitea.io/gitea/services/pull" "code.gitea.io/gitea/services/pull"
) )
// ErrCommitIDDoesNotMatch represents a "CommitIDDoesNotMatch" kind of error.
type ErrCommitIDDoesNotMatch struct {
GivenCommitID string
CurrentCommitID string
}
// IsErrCommitIDDoesNotMatch checks if an error is a ErrCommitIDDoesNotMatch.
func IsErrCommitIDDoesNotMatch(err error) bool {
_, ok := err.(ErrCommitIDDoesNotMatch)
return ok
}
func (err ErrCommitIDDoesNotMatch) Error() string {
return fmt.Sprintf("file CommitID does not match [given: %s, expected: %s]", err.GivenCommitID, err.CurrentCommitID)
}
// CherryPick cherrypicks or reverts a commit to the given repository // CherryPick cherrypicks or reverts a commit to the given repository
func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, revert bool, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) { func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, revert bool, opts *ApplyDiffPatchOptions) (*structs.FileResponse, error) {
if err := opts.Validate(ctx, repo, doer); err != nil { if err := opts.Validate(ctx, repo, doer); err != nil {
@ -57,7 +72,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
} }
opts.LastCommitID = lastCommitID.String() opts.LastCommitID = lastCommitID.String()
if commit.ID.String() != opts.LastCommitID { if commit.ID.String() != opts.LastCommitID {
return nil, models.ErrCommitIDDoesNotMatch{ return nil, ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID, GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID,
} }

View File

@ -10,7 +10,6 @@ import (
"path" "path"
"strings" "strings"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/gitrepo"
@ -53,7 +52,7 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, treePat
// Check that the path given in opts.treePath is valid (not a git path) // Check that the path given in opts.treePath is valid (not a git path)
cleanTreePath := CleanUploadFileName(treePath) cleanTreePath := CleanUploadFileName(treePath)
if cleanTreePath == "" && treePath != "" { if cleanTreePath == "" && treePath != "" {
return nil, models.ErrFilenameInvalid{ return nil, ErrFilenameInvalid{
Path: treePath, Path: treePath,
} }
} }
@ -128,7 +127,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
// Check that the path given in opts.treePath is valid (not a git path) // Check that the path given in opts.treePath is valid (not a git path)
cleanTreePath := CleanUploadFileName(treePath) cleanTreePath := CleanUploadFileName(treePath)
if cleanTreePath == "" && treePath != "" { if cleanTreePath == "" && treePath != "" {
return nil, models.ErrFilenameInvalid{ return nil, ErrFilenameInvalid{
Path: treePath, Path: treePath,
} }
} }

View File

@ -156,6 +156,25 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m
return authorUser, committerUser return authorUser, committerUser
} }
// ErrFilenameInvalid represents a "FilenameInvalid" kind of error.
type ErrFilenameInvalid struct {
Path string
}
// IsErrFilenameInvalid checks if an error is an ErrFilenameInvalid.
func IsErrFilenameInvalid(err error) bool {
_, ok := err.(ErrFilenameInvalid)
return ok
}
func (err ErrFilenameInvalid) Error() string {
return fmt.Sprintf("path contains a malformed path component [path: %s]", err.Path)
}
func (err ErrFilenameInvalid) Unwrap() error {
return util.ErrInvalidArgument
}
// CleanUploadFileName Trims a filename and returns empty string if it is a .git directory // CleanUploadFileName Trims a filename and returns empty string if it is a .git directory
func CleanUploadFileName(name string) string { func CleanUploadFileName(name string) string {
// Rebase the filename // Rebase the filename

View File

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -16,9 +15,29 @@ import (
"code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
asymkey_service "code.gitea.io/gitea/services/asymkey" asymkey_service "code.gitea.io/gitea/services/asymkey"
) )
// ErrUserCannotCommit represents "UserCannotCommit" kind of error.
type ErrUserCannotCommit struct {
UserName string
}
// IsErrUserCannotCommit checks if an error is an ErrUserCannotCommit.
func IsErrUserCannotCommit(err error) bool {
_, ok := err.(ErrUserCannotCommit)
return ok
}
func (err ErrUserCannotCommit) Error() string {
return fmt.Sprintf("user cannot commit to repo [user: %s]", err.UserName)
}
func (err ErrUserCannotCommit) Unwrap() error {
return util.ErrPermissionDenied
}
// ApplyDiffPatchOptions holds the repository diff patch update options // ApplyDiffPatchOptions holds the repository diff patch update options
type ApplyDiffPatchOptions struct { type ApplyDiffPatchOptions struct {
LastCommitID string LastCommitID string
@ -74,7 +93,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
if protectedBranch != nil { if protectedBranch != nil {
protectedBranch.Repo = repo protectedBranch.Repo = repo
if !protectedBranch.CanUserPush(ctx, doer) { if !protectedBranch.CanUserPush(ctx, doer) {
return models.ErrUserCannotCommit{ return ErrUserCannotCommit{
UserName: doer.LowerName, UserName: doer.LowerName,
} }
} }
@ -85,7 +104,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
if !asymkey_service.IsErrWontSign(err) { if !asymkey_service.IsErrWontSign(err) {
return err return err
} }
return models.ErrUserCannotCommit{ return ErrUserCannotCommit{
UserName: doer.LowerName, UserName: doer.LowerName,
} }
} }
@ -137,7 +156,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
} }
opts.LastCommitID = lastCommitID.String() opts.LastCommitID = lastCommitID.String()
if commit.ID.String() != opts.LastCommitID { if commit.ID.String() != opts.LastCommitID {
return nil, models.ErrCommitIDDoesNotMatch{ return nil, ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID, GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID,
} }

View File

@ -13,7 +13,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
@ -187,7 +186,7 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(mode, objectHash, objectPat
if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil { if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil {
stderr := err.Error() stderr := err.Error()
if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched { if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
return models.ErrFilePathInvalid{ return ErrFilePathInvalid{
Message: objectPath, Message: objectPath,
Path: objectPath, Path: objectPath,
} }

View File

@ -8,18 +8,37 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
) )
// ErrSHANotFound represents a "SHADoesNotMatch" kind of error.
type ErrSHANotFound struct {
SHA string
}
// IsErrSHANotFound checks if an error is a ErrSHANotFound.
func IsErrSHANotFound(err error) bool {
_, ok := err.(ErrSHANotFound)
return ok
}
func (err ErrSHANotFound) Error() string {
return fmt.Sprintf("sha not found [%s]", err.SHA)
}
func (err ErrSHANotFound) Unwrap() error {
return util.ErrNotExist
}
// GetTreeBySHA get the GitTreeResponse of a repository using a sha hash. // GetTreeBySHA get the GitTreeResponse of a repository using a sha hash.
func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) { func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) {
gitTree, err := gitRepo.GetTree(sha) gitTree, err := gitRepo.GetTree(sha)
if err != nil || gitTree == nil { if err != nil || gitTree == nil {
return nil, models.ErrSHANotFound{ return nil, ErrSHANotFound{ // TODO: this error has never been catch outside of this function
SHA: sha, SHA: sha,
} }
} }

View File

@ -11,7 +11,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -21,7 +20,9 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
asymkey_service "code.gitea.io/gitea/services/asymkey" asymkey_service "code.gitea.io/gitea/services/asymkey"
pull_service "code.gitea.io/gitea/services/pull"
) )
// IdentityOptions for a person's identity like an author or committer // IdentityOptions for a person's identity like an author or committer
@ -64,6 +65,26 @@ type RepoFileOptions struct {
executable bool executable bool
} }
// ErrRepoFileDoesNotExist represents a "RepoFileDoesNotExist" kind of error.
type ErrRepoFileDoesNotExist struct {
Path string
Name string
}
// IsErrRepoFileDoesNotExist checks if an error is a ErrRepoDoesNotExist.
func IsErrRepoFileDoesNotExist(err error) bool {
_, ok := err.(ErrRepoFileDoesNotExist)
return ok
}
func (err ErrRepoFileDoesNotExist) Error() string {
return fmt.Sprintf("repository file does not exist [path: %s]", err.Path)
}
func (err ErrRepoFileDoesNotExist) Unwrap() error {
return util.ErrNotExist
}
// ChangeRepoFiles adds, updates or removes multiple files in the given repository // ChangeRepoFiles adds, updates or removes multiple files in the given repository
func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ChangeRepoFilesOptions) (*structs.FilesResponse, error) { func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ChangeRepoFilesOptions) (*structs.FilesResponse, error) {
err := repo.MustNotBeArchived() err := repo.MustNotBeArchived()
@ -100,14 +121,14 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
// Check that the path given in opts.treePath is valid (not a git path) // Check that the path given in opts.treePath is valid (not a git path)
treePath := CleanUploadFileName(file.TreePath) treePath := CleanUploadFileName(file.TreePath)
if treePath == "" { if treePath == "" {
return nil, models.ErrFilenameInvalid{ return nil, ErrFilenameInvalid{
Path: file.TreePath, Path: file.TreePath,
} }
} }
// If there is a fromTreePath (we are copying it), also clean it up // If there is a fromTreePath (we are copying it), also clean it up
fromTreePath := CleanUploadFileName(file.FromTreePath) fromTreePath := CleanUploadFileName(file.FromTreePath)
if fromTreePath == "" && file.FromTreePath != "" { if fromTreePath == "" && file.FromTreePath != "" {
return nil, models.ErrFilenameInvalid{ return nil, ErrFilenameInvalid{
Path: file.FromTreePath, Path: file.FromTreePath,
} }
} }
@ -185,7 +206,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
} }
} }
if !inFilelist { if !inFilelist {
return nil, models.ErrRepoFileDoesNotExist{ return nil, ErrRepoFileDoesNotExist{
Path: file.TreePath, Path: file.TreePath,
} }
} }
@ -276,6 +297,63 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
return filesResponse, nil return filesResponse, nil
} }
// ErrRepoFileAlreadyExists represents a "RepoFileAlreadyExist" kind of error.
type ErrRepoFileAlreadyExists struct {
Path string
}
// IsErrRepoFileAlreadyExists checks if an error is a ErrRepoFileAlreadyExists.
func IsErrRepoFileAlreadyExists(err error) bool {
_, ok := err.(ErrRepoFileAlreadyExists)
return ok
}
func (err ErrRepoFileAlreadyExists) Error() string {
return fmt.Sprintf("repository file already exists [path: %s]", err.Path)
}
func (err ErrRepoFileAlreadyExists) Unwrap() error {
return util.ErrAlreadyExist
}
// ErrFilePathInvalid represents a "FilePathInvalid" kind of error.
type ErrFilePathInvalid struct {
Message string
Path string
Name string
Type git.EntryMode
}
// IsErrFilePathInvalid checks if an error is an ErrFilePathInvalid.
func IsErrFilePathInvalid(err error) bool {
_, ok := err.(ErrFilePathInvalid)
return ok
}
func (err ErrFilePathInvalid) Error() string {
if err.Message != "" {
return err.Message
}
return fmt.Sprintf("path is invalid [path: %s]", err.Path)
}
func (err ErrFilePathInvalid) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrSHAOrCommitIDNotProvided represents a "SHAOrCommitIDNotProvided" kind of error.
type ErrSHAOrCommitIDNotProvided struct{}
// IsErrSHAOrCommitIDNotProvided checks if an error is a ErrSHAOrCommitIDNotProvided.
func IsErrSHAOrCommitIDNotProvided(err error) bool {
_, ok := err.(ErrSHAOrCommitIDNotProvided)
return ok
}
func (err ErrSHAOrCommitIDNotProvided) Error() string {
return "a SHA or commit ID must be proved when updating a file"
}
// handles the check for various issues for ChangeRepoFiles // handles the check for various issues for ChangeRepoFiles
func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error { func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRepoFilesOptions) error {
if file.Operation == "update" || file.Operation == "delete" { if file.Operation == "update" || file.Operation == "delete" {
@ -286,7 +364,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
if file.SHA != "" { if file.SHA != "" {
// If a SHA was given and the SHA given doesn't match the SHA of the fromTreePath, throw error // If a SHA was given and the SHA given doesn't match the SHA of the fromTreePath, throw error
if file.SHA != fromEntry.ID.String() { if file.SHA != fromEntry.ID.String() {
return models.ErrSHADoesNotMatch{ return pull_service.ErrSHADoesNotMatch{
Path: file.Options.treePath, Path: file.Options.treePath,
GivenSHA: file.SHA, GivenSHA: file.SHA,
CurrentSHA: fromEntry.ID.String(), CurrentSHA: fromEntry.ID.String(),
@ -299,7 +377,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
if changed, err := commit.FileChangedSinceCommit(file.Options.treePath, opts.LastCommitID); err != nil { if changed, err := commit.FileChangedSinceCommit(file.Options.treePath, opts.LastCommitID); err != nil {
return err return err
} else if changed { } else if changed {
return models.ErrCommitIDDoesNotMatch{ return ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID, GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID, CurrentCommitID: opts.LastCommitID,
} }
@ -309,7 +387,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
} else { } else {
// When updating a file, a lastCommitID or SHA needs to be given to make sure other commits // When updating a file, a lastCommitID or SHA needs to be given to make sure other commits
// haven't been made. We throw an error if one wasn't provided. // haven't been made. We throw an error if one wasn't provided.
return models.ErrSHAOrCommitIDNotProvided{} return ErrSHAOrCommitIDNotProvided{}
} }
file.Options.executable = fromEntry.IsExecutable() file.Options.executable = fromEntry.IsExecutable()
} }
@ -332,7 +410,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
} }
if index < len(treePathParts)-1 { if index < len(treePathParts)-1 {
if !entry.IsDir() { if !entry.IsDir() {
return models.ErrFilePathInvalid{ return ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where youre trying to create a subdirectory [path: %s]", subTreePath), Message: fmt.Sprintf("a file exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath, Path: subTreePath,
Name: part, Name: part,
@ -340,14 +418,14 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
} }
} }
} else if entry.IsLink() { } else if entry.IsLink() {
return models.ErrFilePathInvalid{ return ErrFilePathInvalid{
Message: fmt.Sprintf("a symbolic link exists where youre trying to create a subdirectory [path: %s]", subTreePath), Message: fmt.Sprintf("a symbolic link exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath, Path: subTreePath,
Name: part, Name: part,
Type: git.EntryModeSymlink, Type: git.EntryModeSymlink,
} }
} else if entry.IsDir() { } else if entry.IsDir() {
return models.ErrFilePathInvalid{ return ErrFilePathInvalid{
Message: fmt.Sprintf("a directory exists where youre trying to create a file [path: %s]", subTreePath), Message: fmt.Sprintf("a directory exists where youre trying to create a file [path: %s]", subTreePath),
Path: subTreePath, Path: subTreePath,
Name: part, Name: part,
@ -355,7 +433,7 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
} }
} else if file.Options.fromTreePath != file.Options.treePath || file.Operation == "create" { } else if file.Options.fromTreePath != file.Options.treePath || file.Operation == "create" {
// The entry shouldn't exist if we are creating new file or moving to a new path // The entry shouldn't exist if we are creating new file or moving to a new path
return models.ErrRepoFileAlreadyExists{ return ErrRepoFileAlreadyExists{
Path: file.Options.treePath, Path: file.Options.treePath,
} }
} }
@ -376,7 +454,7 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
if file.Operation == "create" { if file.Operation == "create" {
for _, indexFile := range filesInIndex { for _, indexFile := range filesInIndex {
if indexFile == file.TreePath { if indexFile == file.TreePath {
return models.ErrRepoFileAlreadyExists{ return ErrRepoFileAlreadyExists{
Path: file.TreePath, Path: file.TreePath,
} }
} }
@ -479,12 +557,12 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do
isUnprotectedFile = protectedBranch.IsUnprotectedFile(globUnprotected, treePath) isUnprotectedFile = protectedBranch.IsUnprotectedFile(globUnprotected, treePath)
} }
if !canUserPush && !isUnprotectedFile { if !canUserPush && !isUnprotectedFile {
return models.ErrUserCannotCommit{ return ErrUserCannotCommit{
UserName: doer.LowerName, UserName: doer.LowerName,
} }
} }
if protectedBranch.IsProtectedFile(globProtected, treePath) { if protectedBranch.IsProtectedFile(globProtected, treePath) {
return models.ErrFilePathProtected{ return pull_service.ErrFilePathProtected{
Path: treePath, Path: treePath,
} }
} }
@ -495,7 +573,7 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do
if !asymkey_service.IsErrWontSign(err) { if !asymkey_service.IsErrWontSign(err) {
return err return err
} }
return models.ErrUserCannotCommit{ return ErrUserCannotCommit{
UserName: doer.LowerName, UserName: doer.LowerName,
} }
} }

View File

@ -7,7 +7,6 @@ import (
"context" "context"
"fmt" "fmt"
"code.gitea.io/gitea/models"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
password_module "code.gitea.io/gitea/modules/auth/password" password_module "code.gitea.io/gitea/modules/auth/password"
@ -113,7 +112,7 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er
} }
if opts.IsAdmin.Has() { if opts.IsAdmin.Has() {
if !opts.IsAdmin.Value() && user_model.IsLastAdminUser(ctx, u) { if !opts.IsAdmin.Value() && user_model.IsLastAdminUser(ctx, u) {
return models.ErrDeleteLastAdminUser{UID: u.ID} return user_model.ErrDeleteLastAdminUser{UID: u.ID}
} }
u.IsAdmin = opts.IsAdmin.Value() u.IsAdmin = opts.IsAdmin.Value()

View File

@ -10,7 +10,6 @@ import (
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
packages_model "code.gitea.io/gitea/models/packages" packages_model "code.gitea.io/gitea/models/packages"
@ -127,7 +126,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
} }
if u.IsActive && user_model.IsLastAdminUser(ctx, u) { if u.IsActive && user_model.IsLastAdminUser(ctx, u) {
return models.ErrDeleteLastAdminUser{UID: u.ID} return user_model.ErrDeleteLastAdminUser{UID: u.ID}
} }
if purge { if purge {
@ -225,7 +224,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
if err != nil { if err != nil {
return fmt.Errorf("GetRepositoryCount: %w", err) return fmt.Errorf("GetRepositoryCount: %w", err)
} else if count > 0 { } else if count > 0 {
return models.ErrUserOwnRepos{UID: u.ID} return repo_model.ErrUserOwnRepos{UID: u.ID}
} }
// Check membership of organization. // Check membership of organization.
@ -233,14 +232,14 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
if err != nil { if err != nil {
return fmt.Errorf("GetOrganizationCount: %w", err) return fmt.Errorf("GetOrganizationCount: %w", err)
} else if count > 0 { } else if count > 0 {
return models.ErrUserHasOrgs{UID: u.ID} return organization.ErrUserHasOrgs{UID: u.ID}
} }
// Check ownership of packages. // Check ownership of packages.
if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil { if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil {
return fmt.Errorf("HasOwnerPackages: %w", err) return fmt.Errorf("HasOwnerPackages: %w", err)
} else if ownsPackages { } else if ownsPackages {
return models.ErrUserOwnPackages{UID: u.ID} return packages_model.ErrUserOwnPackages{UID: u.ID}
} }
if err := deleteUser(ctx, u, purge); err != nil { if err := deleteUser(ctx, u, purge); err != nil {
@ -288,7 +287,7 @@ func DeleteInactiveUsers(ctx context.Context, olderThan time.Duration) error {
for _, u := range inactiveUsers { for _, u := range inactiveUsers {
if err = DeleteUser(ctx, u, false); err != nil { if err = DeleteUser(ctx, u, false); err != nil {
// Ignore inactive users that were ever active but then were set inactive by admin // Ignore inactive users that were ever active but then were set inactive by admin
if models.IsErrUserOwnRepos(err) || models.IsErrUserHasOrgs(err) || models.IsErrUserOwnPackages(err) { if repo_model.IsErrUserOwnRepos(err) || organization.IsErrUserHasOrgs(err) || packages_model.IsErrUserOwnPackages(err) {
log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err) log.Warn("Inactive user %q has repositories, organizations or packages, skipping deletion: %v", u.Name, err)
continue continue
} }

View File

@ -9,7 +9,6 @@ import (
"testing" "testing"
"time" "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
@ -37,7 +36,7 @@ func TestDeleteUser(t *testing.T) {
if len(ownedRepos) > 0 { if len(ownedRepos) > 0 {
err := DeleteUser(db.DefaultContext, user, false) err := DeleteUser(db.DefaultContext, user, false)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, models.IsErrUserOwnRepos(err)) assert.True(t, repo_model.IsErrUserOwnRepos(err))
return return
} }

View File

@ -6,7 +6,6 @@ package integration
import ( import (
"strings" "strings"
"code.gitea.io/gitea/models"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
@ -48,7 +47,7 @@ func deleteFileInBranch(user *user_model.User, repo *repo_model.Repository, tree
func createOrReplaceFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) error { func createOrReplaceFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) error {
_, err := deleteFileInBranch(user, repo, treePath, branchName) _, err := deleteFileInBranch(user, repo, treePath, branchName)
if err != nil && !models.IsErrRepoFileDoesNotExist(err) { if err != nil && !files_service.IsErrRepoFileDoesNotExist(err) {
return err return err
} }

View File

@ -18,7 +18,6 @@ import (
"testing" "testing"
"time" "time"
"code.gitea.io/gitea/models"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
@ -36,7 +35,7 @@ import (
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/services/automerge" "code.gitea.io/gitea/services/automerge"
"code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus" commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
@ -267,13 +266,13 @@ func TestCantMergeConflict(t *testing.T) {
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1)
assert.NoError(t, err) assert.NoError(t, err)
err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false) err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false)
assert.Error(t, err, "Merge should return an error due to conflict") assert.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrMergeConflicts(err), "Merge error is not a conflict error") assert.True(t, pull_service.IsErrMergeConflicts(err), "Merge error is not a conflict error")
err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false) err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false)
assert.Error(t, err, "Merge should return an error due to conflict") assert.Error(t, err, "Merge should return an error due to conflict")
assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error") assert.True(t, pull_service.IsErrRebaseConflicts(err), "Merge error is not a conflict error")
gitRepo.Close() gitRepo.Close()
}) })
} }
@ -366,9 +365,9 @@ func TestCantMergeUnrelated(t *testing.T) {
BaseBranch: "base", BaseBranch: "base",
}) })
err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false) err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false)
assert.Error(t, err, "Merge should return an error due to unrelated") assert.Error(t, err, "Merge should return an error due to unrelated")
assert.True(t, models.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error") assert.True(t, pull_service.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error")
gitRepo.Close() gitRepo.Close()
}) })
} }
@ -406,7 +405,7 @@ func TestFastForwardOnlyMerge(t *testing.T) {
gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name))
assert.NoError(t, err) assert.NoError(t, err)
err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false) err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false)
assert.NoError(t, err) assert.NoError(t, err)
@ -448,10 +447,10 @@ func TestCantFastForwardOnlyMergeDiverging(t *testing.T) {
gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name))
assert.NoError(t, err) assert.NoError(t, err)
err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false) err = pull_service.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false)
assert.Error(t, err, "Merge should return an error due to being for a diverging branch") assert.Error(t, err, "Merge should return an error due to being for a diverging branch")
assert.True(t, models.IsErrMergeDivergingFastForwardOnly(err), "Merge error is not a diverging fast-forward-only error") assert.True(t, pull_service.IsErrMergeDivergingFastForwardOnly(err), "Merge error is not a diverging fast-forward-only error")
gitRepo.Close() gitRepo.Close()
}) })
@ -520,8 +519,8 @@ func TestConflictChecking(t *testing.T) {
BaseRepo: baseRepo, BaseRepo: baseRepo,
Type: issues_model.PullRequestGitea, Type: issues_model.PullRequestGitea,
} }
prOpts := &pull.NewPullRequestOptions{Repo: baseRepo, Issue: pullIssue, PullRequest: pullRequest} prOpts := &pull_service.NewPullRequestOptions{Repo: baseRepo, Issue: pullIssue, PullRequest: pullRequest}
err = pull.NewPullRequest(git.DefaultContext, prOpts) err = pull_service.NewPullRequest(git.DefaultContext, prOpts)
assert.NoError(t, err) assert.NoError(t, err)
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "PR with conflict!"}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: "PR with conflict!"})

View File

@ -9,7 +9,6 @@ import (
"net/url" "net/url"
"testing" "testing"
"code.gitea.io/gitea/models"
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
@ -39,7 +38,7 @@ func TestCreateNewTagProtected(t *testing.T) {
err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag") err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag")
assert.Error(t, err) assert.Error(t, err)
assert.True(t, models.IsErrProtectedTagName(err)) assert.True(t, release.IsErrProtectedTagName(err))
err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag") err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag")
assert.NoError(t, err) assert.NoError(t, err)