@@ -12,6 +12,7 @@ import (
"errors"
"fmt"
"html/template"
"math/rand"
"xorm.io/xorm"
"code.gitea.io/gitea/modules/blockchain"
@@ -221,8 +222,10 @@ type Repository struct {
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
Hot int64 `xorm:"-"`
Active int64 `xorm:"-"`
Hot int64 `xorm:"-"`
Active int64 `xorm:"-"`
Alias string `xorm:"INDEX"`
LowerAlias string `xorm:"INDEX"`
}
// SanitizedOriginalURL returns a sanitized OriginalURL
@@ -233,6 +236,14 @@ func (repo *Repository) SanitizedOriginalURL() string {
return util.SanitizeURLCredentials(repo.OriginalURL, false)
}
// GetAlias returns a sanitized OriginalURL
func (repo *Repository) DisplayName() string {
if repo.Alias == "" {
return repo.Name
}
return repo.Alias
}
// ColorFormat returns a colored string to represent this repo
func (repo *Repository) ColorFormat(s fmt.State) {
var ownerName interface{}
@@ -286,6 +297,11 @@ func (repo *Repository) FullName() string {
return repo.OwnerName + "/" + repo.Name
}
// FullDisplayName returns the repository full display name
func (repo *Repository) FullDisplayName() string {
return repo.OwnerName + "/" + repo.DisplayName()
}
// HTMLURL returns the repository HTML URL
func (repo *Repository) HTMLURL() string {
return setting.AppURL + repo.FullName()
@@ -385,7 +401,9 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool)
ID: repo.ID,
Owner: repo.Owner.APIFormat(),
Name: repo.Name,
Alias: repo.Alias,
FullName: repo.FullName(),
FullDisplayName: repo.FullDisplayName(),
Description: repo.Description,
Private: repo.IsPrivate,
Template: repo.IsTemplate,
@@ -921,17 +939,50 @@ func (repo *Repository) DescriptionHTML() template.HTML {
return template.HTML(markup.Sanitize(string(desc)))
}
func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) {
has, err := e.Get(&Repository{
OwnerID: u.ID,
LowerName: strings.ToLower(repoName),
})
return has && com.IsDir(RepoPath(u.Name, repoName)), err
func isRepositoryExist(e Engine, u *User, repoName string, alias string) (bool, error) {
var cond = builder.NewCond()
cond = cond.And(builder.Eq{"owner_id": u.ID})
if alias != "" {
subCon := builder.NewCond()
subCon = subCon.Or(builder.Eq{"lower_alias": strings.ToLower(alias)}, builder.Eq{"lower_name": strings.ToLower(repoName)})
cond = cond.And(subCon)
} else {
cond = cond.And(builder.Eq{"lower_name": strings.ToLower(repoName)})
}
count, err := e.Where(cond).Count(&Repository{})
return count > 0 || com.IsDir(RepoPath(u.Name, repoName)), err
}
// IsRepositoryExist returns true if the repository with given name under user has already existed.
func IsRepositoryExist(u *User, repoName string) (bool, error) {
return isRepositoryExist(x, u, repoName)
func IsRepositoryExist(u *User, repoName string, alias string) (bool, error) {
return isRepositoryExist(x, u, repoName, alias)
}
// IsRepositoryAliasExist returns true if the repository with given alias under user has already existed.
func IsRepositoryAliasExist(u *User, alias string) (bool, error) {
return isRepositoryAliasExist(x, u, alias)
}
func isRepositoryAliasExist(e Engine, u *User, alias string) (bool, error) {
var cond = builder.NewCond()
cond = cond.And(builder.Eq{"owner_id": u.ID})
cond = cond.And(builder.Eq{"lower_alias": strings.ToLower(alias)})
count, err := e.Where(cond).Count(&Repository{})
return count > 0, err
}
func IsRepositoryAliasAvailable(doer *User, alias string) error {
if err := IsUsableRepoAlias(alias); err != nil {
return err
}
has, err := IsRepositoryAliasExist(doer, alias)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{doer.Name, alias}
}
return nil
}
// CloneLink represents different types of clone URLs of repository.
@@ -975,20 +1026,24 @@ func (repo *Repository) CloneLink() (cl *CloneLink) {
}
// CheckCreateRepository check if could created a repository
func CheckCreateRepository(doer, u *User, name string) error {
func CheckCreateRepository(doer, u *User, repoName, alias string) error {
if !doer.CanCreateRepo() {
return ErrReachLimitOfRepo{u.MaxRepoCreation}
}
if err := IsUsableRepoName(n ame); err != nil {
if err := IsUsableRepoName(repoN ame); err != nil {
return err
}
has, err := isRepositoryExist(x, u, name)
if err := IsUsableRepoAlias(alias); err != nil {
return err
}
has, err := isRepositoryExist(x, u, repoName, alias)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{u.Name, name}
return ErrRepoAlreadyExist{u.Name, repoN ame}
}
return nil
}
@@ -996,6 +1051,7 @@ func CheckCreateRepository(doer, u *User, name string) error {
// CreateRepoOptions contains the create repository options
type CreateRepoOptions struct {
Name string
Alias string
Description string
OriginalURL string
GitServiceType api.GitServiceType
@@ -1036,8 +1092,10 @@ func GetRepoInitFile(tp, name string) ([]byte, error) {
}
var (
reservedRepoNames = []string{".", ".."}
reservedRepoPatterns = []string{"*.git", "*.wiki"}
reservedRepoNames = []string{".", ".."}
reservedRepoPatterns = []string{"*.git", "*.wiki"}
reservedRepoAliasNames = []string{}
reservedRepoAliasPatterns = []string{}
)
// IsUsableRepoName returns true when repository is usable
@@ -1045,13 +1103,22 @@ func IsUsableRepoName(name string) error {
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
}
// IsUsableRepoAlias returns true when repository alias is usable
func IsUsableRepoAlias(name string) error {
return isUsableName(reservedRepoAliasNames, reservedRepoAliasPatterns, name)
}
// CreateRepository creates a repository for the user/organization.
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error) {
repo.LowerAlias = strings.ToLower(repo.Alias)
if err = IsUsableRepoName(repo.Name); err != nil {
return err
}
has, err := isRepositoryExist(ctx.e, u, repo.Name)
if err := IsUsableRepoAlias(repo.Alias); err != nil {
return err
}
has, err := isRepositoryExist(ctx.e, u, repo.Name, repo.Alias)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
@@ -1233,7 +1300,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
}
// Check if new owner has repository with same name.
has, err := IsRepositoryExist(newOwner, repo.Name)
has, err := IsRepositoryExist(newOwner, repo.Name, repo.Alias )
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
@@ -1366,7 +1433,7 @@ func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err
return err
}
has, err := IsRepositoryExist(repo.Owner, newRepoName)
has, err := IsRepositoryExist(repo.Owner, newRepoName, "" )
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
@@ -1848,6 +1915,26 @@ func getRepositoryByOwnerAndName(e Engine, ownerName, repoName string) (*Reposit
return &repo, nil
}
// GetRepositoryByOwnerAndAlias returns the repository by given ownername and reponame.
func GetRepositoryByOwnerAndAlias(ownerName, alias string) (*Repository, error) {
return getRepositoryByOwnerAndAlias(x, ownerName, alias)
}
func getRepositoryByOwnerAndAlias(e Engine, ownerName, alias string) (*Repository, error) {
var repo Repository
has, err := e.Table("repository").Select("repository.*").
Join("INNER", "`user`", "`user`.id = repository.owner_id").
Where("repository.lower_alias = ?", strings.ToLower(alias)).
And("`user`.lower_name = ?", strings.ToLower(ownerName)).
Get(&repo)
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{0, 0, ownerName, alias}
}
return &repo, nil
}
// GetRepositoryByName returns the repository by given name under user if exists.
func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
repo := &Repository{
@@ -2521,6 +2608,14 @@ func UpdateRepositoryCommitNum(repo *Repository) error {
return nil
}
func GenerateDefaultRepoName(ownerName string) string {
if len(ownerName) > 5 {
ownerName = ownerName[:5]
}
now := time.Now().Format("20060102150405")
return ownerName + now + fmt.Sprint(rand.Intn(10))
}
type RepoFile struct {
CommitId string
Content []byte