mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-02 20:06:06 +01:00 
			
		
		
		
	Move some errors to their own sub packages (#32880)
This commit is contained in:
		
							
								
								
									
										510
									
								
								models/error.go
									
									
									
									
									
								
							
							
						
						
									
										510
									
								
								models/error.go
									
									
									
									
									
								
							@@ -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)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -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).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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()),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 you’re trying to create a subdirectory [path: %s]", subTreePath),
 | 
											Message: fmt.Sprintf("a file exists where you’re 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 you’re trying to create a subdirectory [path: %s]", subTreePath),
 | 
										Message: fmt.Sprintf("a symbolic link exists where you’re 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 you’re trying to create a file [path: %s]", subTreePath),
 | 
										Message: fmt.Sprintf("a directory exists where you’re 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,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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!"})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user