diff --git a/integrations/pull_update_test.go b/integrations/pull_update_test.go
index 484390001..251051582 100644
--- a/integrations/pull_update_test.go
+++ b/integrations/pull_update_test.go
@@ -58,7 +58,7 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *models.User) *models.PullReq
assert.NoError(t, err)
assert.NotEmpty(t, baseRepo)
- headRepo, err := repo_module.ForkRepository(actor, forkOrg, baseRepo, "repo-pr-update", "desc")
+ headRepo, err := repo_module.ForkRepository(actor, forkOrg, baseRepo, "repo-pr-update", "desc", "")
assert.NoError(t, err)
assert.NotEmpty(t, headRepo)
diff --git a/models/action.go b/models/action.go
index 003dc1b20..4821910db 100755
--- a/models/action.go
+++ b/models/action.go
@@ -164,12 +164,24 @@ func (a *Action) GetRepoName() string {
return a.Repo.Name
}
+// GetRepoName returns the name of the action repository.
+func (a *Action) GetRepoDisplayName() string {
+ a.loadRepo()
+ return a.Repo.DisplayName()
+}
+
// ShortRepoName returns the name of the action repository
// trimmed to max 33 chars.
func (a *Action) ShortRepoName() string {
return base.EllipsisString(a.GetRepoName(), 33)
}
+// ShortRepoName returns the name of the action repository
+// trimmed to max 33 chars.
+func (a *Action) ShortRepoDisplayName() string {
+ return base.EllipsisString(a.GetRepoDisplayName(), 33)
+}
+
// GetRepoPath returns the virtual path to the action repository.
func (a *Action) GetRepoPath() string {
return path.Join(a.GetRepoUserName(), a.GetRepoName())
@@ -181,6 +193,12 @@ func (a *Action) ShortRepoPath() string {
return path.Join(a.ShortRepoUserName(), a.ShortRepoName())
}
+// ShortRepoPath returns the virtual path to the action repository
+// trimmed to max 20 + 1 + 33 chars.
+func (a *Action) ShortRepoFullDisplayName() string {
+ return path.Join(a.ShortRepoUserName(), a.ShortRepoDisplayName())
+}
+
// GetRepoLink returns relative link to action repository.
func (a *Action) GetRepoLink() string {
if len(setting.AppSubURL) > 0 {
diff --git a/models/repo.go b/models/repo.go
index f393b51b2..027ced6ff 100755
--- a/models/repo.go
+++ b/models/repo.go
@@ -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(name); err != nil {
+ if err := IsUsableRepoName(repoName); 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, repoName}
}
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
diff --git a/models/repo_generate.go b/models/repo_generate.go
index 480683cd4..08bb1463d 100644
--- a/models/repo_generate.go
+++ b/models/repo_generate.go
@@ -19,6 +19,7 @@ import (
// GenerateRepoOptions contains the template units to generate
type GenerateRepoOptions struct {
Name string
+ Alias string
Description string
Private bool
GitContent bool
diff --git a/models/repo_list.go b/models/repo_list.go
index c4d8ee823..e41b0f49d 100755
--- a/models/repo_list.go
+++ b/models/repo_list.go
@@ -200,8 +200,8 @@ const (
SearchOrderByForks SearchOrderBy = "num_forks ASC"
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC"
SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC"
- SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC"
- SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC"
+ SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC"
+ SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC"
)
// SearchRepositoryCondition creates a query condition according search repository options
@@ -321,6 +321,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
var likes = builder.NewCond()
for _, v := range strings.Split(opts.Keyword, ",") {
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
+ likes = likes.Or(builder.Like{"alias", v})
if opts.IncludeDescription {
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)})
}
diff --git a/models/repo_tag.go b/models/repo_tag.go
index 76740bd76..984f9e2db 100644
--- a/models/repo_tag.go
+++ b/models/repo_tag.go
@@ -28,6 +28,7 @@ type OfficialTagRepos struct {
type TagReposBrief struct {
RepoID int64
RepoName string
+ Alias string
TagID int64
}
@@ -97,7 +98,7 @@ func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error {
func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) {
t := make([]TagReposBrief, 0)
- const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc"
+ const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t1.alias,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc"
if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil {
return nil, err
@@ -108,9 +109,13 @@ func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) {
if v.TagID > 0 {
selected = true
}
+ repoName := v.Alias
+ if v.Alias == "" {
+ repoName = v.RepoName
+ }
r = append(r, TagReposSelected{
RepoID: v.RepoID,
- RepoName: v.RepoName,
+ RepoName: repoName,
Selected: selected,
})
}
diff --git a/modules/auth/auth.go b/modules/auth/auth.go
index 352e50ca0..6a156491d 100644
--- a/modules/auth/auth.go
+++ b/modules/auth/auth.go
@@ -186,6 +186,8 @@ func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaro
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
case validation.ErrGlobPattern:
data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message)
+ case validation.ErrAlphaDashDotChinese:
+ data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_chinese_error")
default:
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
}
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 8061c6469..32890a5c1 100755
--- a/modules/auth/repo_form.go
+++ b/modules/auth/repo_form.go
@@ -29,6 +29,7 @@ import (
type CreateRepoForm struct {
UID int64 `binding:"Required"`
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
+ Alias string `binding:"Required;MaxSize(100);AlphaDashDotChinese"`
Private bool
Description string `binding:"MaxSize(1024)"`
DefaultBranch string `binding:"GitRefName;MaxSize(100)"`
@@ -62,6 +63,7 @@ type MigrateRepoForm struct {
UID int64 `json:"uid" binding:"Required"`
// required: true
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
+ Alias string `json:"alias" binding:"Required;AlphaDashDotChinese;MaxSize(100)"`
Mirror bool `json:"mirror"`
Private bool `json:"private"`
Description string `json:"description" binding:"MaxSize(255)"`
@@ -109,6 +111,7 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
// RepoSettingForm form for changing repository settings
type RepoSettingForm struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
+ Alias string `binding:"Required;AlphaDashDotChinese;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Interval string
diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go
index 9956940f3..4bc296657 100644
--- a/modules/notification/action/action.go
+++ b/modules/notification/action/action.go
@@ -154,6 +154,22 @@ func (a *actionNotifier) NotifyRenameRepository(doer *models.User, repo *models.
}
}
+func (a *actionNotifier) NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string) {
+ log.Trace("action.ChangeRepositoryAlias: %s/%s", doer.Name, repo.Alias)
+
+ if err := models.NotifyWatchers(&models.Action{
+ ActUserID: doer.ID,
+ ActUser: doer,
+ OpType: models.ActionRenameRepo,
+ RepoID: repo.ID,
+ Repo: repo,
+ IsPrivate: repo.IsPrivate,
+ Content: oldAlias,
+ }); err != nil {
+ log.Error("NotifyWatchers: %v", err)
+ }
+}
+
func (a *actionNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) {
if err := models.NotifyWatchers(&models.Action{
ActUserID: doer.ID,
diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go
index 0b3e1173b..8325f710c 100644
--- a/modules/notification/base/notifier.go
+++ b/modules/notification/base/notifier.go
@@ -18,6 +18,7 @@ type Notifier interface {
NotifyDeleteRepository(doer *models.User, repo *models.Repository)
NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository)
NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string)
+ NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string)
NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string)
NotifyNewIssue(*models.Issue)
diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go
index d2fd51d71..a74c47980 100644
--- a/modules/notification/base/null.go
+++ b/modules/notification/base/null.go
@@ -135,6 +135,10 @@ func (*NullNotifier) NotifyDeleteRef(doer *models.User, repo *models.Repository,
func (*NullNotifier) NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string) {
}
+func (a *NullNotifier) NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string) {
+
+}
+
// NotifyTransferRepository places a place holder function
func (*NullNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) {
}
diff --git a/modules/repository/create.go b/modules/repository/create.go
index d740c58b1..f5dfa63d6 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -28,6 +28,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m
Owner: u,
OwnerName: u.Name,
Name: opts.Name,
+ Alias: opts.Alias,
LowerName: strings.ToLower(opts.Name),
Description: opts.Description,
OriginalURL: opts.OriginalURL,
diff --git a/modules/repository/fork.go b/modules/repository/fork.go
index 2ed2a0eb7..da9039d00 100644
--- a/modules/repository/fork.go
+++ b/modules/repository/fork.go
@@ -15,7 +15,7 @@ import (
)
// ForkRepository forks a repository
-func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, desc string) (_ *models.Repository, err error) {
+func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, desc, alias string) (_ *models.Repository, err error) {
forkedRepo, err := oldRepo.GetUserFork(owner.ID)
if err != nil {
return nil, err
@@ -33,6 +33,7 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name,
Owner: owner,
OwnerName: owner.Name,
Name: name,
+ Alias: alias,
LowerName: strings.ToLower(name),
Description: desc,
DefaultBranch: oldRepo.DefaultBranch,
diff --git a/modules/repository/fork_test.go b/modules/repository/fork_test.go
index cb3526bcc..f599ead68 100644
--- a/modules/repository/fork_test.go
+++ b/modules/repository/fork_test.go
@@ -18,7 +18,7 @@ func TestForkRepository(t *testing.T) {
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 13}).(*models.User)
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
- fork, err := ForkRepository(user, user, repo, "test", "test")
+ fork, err := ForkRepository(user, user, repo, "test", "test", "test")
assert.Nil(t, fork)
assert.Error(t, err)
assert.True(t, models.IsErrForkAlreadyExist(err))
diff --git a/modules/repository/generate.go b/modules/repository/generate.go
index 6d80488de..86c9a5c28 100644
--- a/modules/repository/generate.go
+++ b/modules/repository/generate.go
@@ -236,6 +236,7 @@ func GenerateRepository(ctx models.DBContext, doer, owner *models.User, template
Owner: owner,
OwnerName: owner.Name,
Name: opts.Name,
+ Alias: opts.Alias,
LowerName: strings.ToLower(opts.Name),
Description: opts.Description,
IsPrivate: opts.Private,
diff --git a/modules/repository/init.go b/modules/repository/init.go
index 3d1c663c8..5dc352d65 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -51,7 +51,7 @@ func prepareRepoCommit(ctx models.DBContext, repo *models.Repository, tmpDir, re
cloneLink := repo.CloneLink()
match := map[string]string{
- "Name": repo.Name,
+ "Name": repo.DisplayName(),
"Description": repo.Description,
"CloneURL.SSH": cloneLink.SSH,
"CloneURL.HTTPS": cloneLink.HTTPS,
diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index 70de9b746..e290488a4 100755
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -46,31 +46,33 @@ type ExternalWiki struct {
// Repository represents a repository
type Repository struct {
- ID int64 `json:"id"`
- Owner *User `json:"owner"`
- Name string `json:"name"`
- FullName string `json:"full_name"`
- Description string `json:"description"`
- Empty bool `json:"empty"`
- Private bool `json:"private"`
- Fork bool `json:"fork"`
- Template bool `json:"template"`
- Parent *Repository `json:"parent"`
- Mirror bool `json:"mirror"`
- Size int `json:"size"`
- HTMLURL string `json:"html_url"`
- SSHURL string `json:"ssh_url"`
- CloneURL string `json:"clone_url"`
- OriginalURL string `json:"original_url"`
- Website string `json:"website"`
- Stars int `json:"stars_count"`
- Forks int `json:"forks_count"`
- Watchers int `json:"watchers_count"`
- OpenIssues int `json:"open_issues_count"`
- OpenPulls int `json:"open_pr_counter"`
- Releases int `json:"release_counter"`
- DefaultBranch string `json:"default_branch"`
- Archived bool `json:"archived"`
+ ID int64 `json:"id"`
+ Owner *User `json:"owner"`
+ Name string `json:"name"`
+ Alias string `json:"alias"`
+ FullName string `json:"full_name"`
+ FullDisplayName string `json:"full_display_name"`
+ Description string `json:"description"`
+ Empty bool `json:"empty"`
+ Private bool `json:"private"`
+ Fork bool `json:"fork"`
+ Template bool `json:"template"`
+ Parent *Repository `json:"parent"`
+ Mirror bool `json:"mirror"`
+ Size int `json:"size"`
+ HTMLURL string `json:"html_url"`
+ SSHURL string `json:"ssh_url"`
+ CloneURL string `json:"clone_url"`
+ OriginalURL string `json:"original_url"`
+ Website string `json:"website"`
+ Stars int `json:"stars_count"`
+ Forks int `json:"forks_count"`
+ Watchers int `json:"watchers_count"`
+ OpenIssues int `json:"open_issues_count"`
+ OpenPulls int `json:"open_pr_counter"`
+ Releases int `json:"release_counter"`
+ DefaultBranch string `json:"default_branch"`
+ Archived bool `json:"archived"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
@@ -217,6 +219,7 @@ type MigrateRepoOption struct {
UID int `json:"uid" binding:"Required"`
// required: true
RepoName string `json:"repo_name" binding:"Required"`
+ Alias string `json:"alias" binding:"Required"`
Mirror bool `json:"mirror"`
Private bool `json:"private"`
Description string `json:"description"`
diff --git a/modules/task/task.go b/modules/task/task.go
index 72f111ecc..722e39bec 100644
--- a/modules/task/task.go
+++ b/modules/task/task.go
@@ -84,6 +84,7 @@ func CreateMigrateTask(doer, u *models.User, opts base.MigrateOptions) (*models.
repo, err := repo_module.CreateRepository(doer, u, models.CreateRepoOptions{
Name: opts.RepoName,
+ Alias: opts.Alias,
Description: opts.Description,
OriginalURL: opts.OriginalURL,
GitServiceType: opts.GitServiceType,
diff --git a/modules/validation/binding.go b/modules/validation/binding.go
index 1c67878ea..b608cdea2 100644
--- a/modules/validation/binding.go
+++ b/modules/validation/binding.go
@@ -19,6 +19,8 @@ const (
// ErrGlobPattern is returned when glob pattern is invalid
ErrGlobPattern = "GlobPattern"
+
+ ErrAlphaDashDotChinese = "AlphaDashDotChineseError"
)
var (
@@ -26,6 +28,8 @@ var (
// They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.
// They cannot have question-mark ?, asterisk *, or open bracket [ anywhere
GitRefNamePatternInvalid = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`)
+
+ AlphaDashDotChinese = regexp.MustCompile("^[\u4e00-\u9fa5\\.\\-_A-Za-z0-9]+$")
)
// CheckGitRefAdditionalRulesValid check name is valid on additional rules
@@ -53,6 +57,7 @@ func AddBindingRules() {
addGitRefNameBindingRule()
addValidURLBindingRule()
addGlobPatternRule()
+ addAlphaDashDotChineseRule()
}
func addGitRefNameBindingRule() {
@@ -117,6 +122,21 @@ func addGlobPatternRule() {
})
}
+func addAlphaDashDotChineseRule() {
+ binding.AddRule(&binding.Rule{
+ IsMatch: func(rule string) bool {
+ return strings.HasPrefix(rule, "AlphaDashDotChinese")
+ },
+ IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
+ if !ValidAlphaDashDotChinese(fmt.Sprintf("%v", val)) {
+ errs.Add([]string{name}, ErrAlphaDashDotChinese, "ErrAlphaDashDotChinese")
+ return false, errs
+ }
+ return true, errs
+ },
+ })
+}
+
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
@@ -139,3 +159,7 @@ func validPort(p string) bool {
}
return true
}
+
+func ValidAlphaDashDotChinese(value string) bool {
+ return AlphaDashDotChinese.MatchString(value)
+}
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 739d515bc..68cf292e2 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -348,7 +348,9 @@ modify = Update
[form]
UserName = Username
-RepoName = Repository name
+Alias = Repository name
+RepoPath = Repository path
+RepoAdress = Repository Adress
Email = Email address
Password = Password
Retype = Re-Type Password
@@ -372,7 +374,10 @@ SSPIDefaultLanguage = Default Language
require_error = ` cannot be empty.`
alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.`
alpha_dash_dot_error = ` should contain only alphanumeric, dash ('-'), underscore ('_') and dot ('.') characters.`
+reponame_dash_dot_error=` Please enter Chinese, alphanumeric, dash ('-') ,underscore ('_') and dot ('.')characters, up to 100 characters. `
+repoadd_dash_dot_error=` Path only allows input alphanumeric, dash ('-') ,underscore ('_') and dot ('.')characters, up to 100 characters. `
git_ref_name_error = ` must be a well-formed Git reference name.`
+alpha_dash_dot_chinese_error= ` should contain only alphanumeric, chinese, dash ('-') and underscore ('_') characters.`
size_error = ` must be size %s.`
min_size_error = ` must contain at least %s characters.`
max_size_error = ` must contain at most %s characters.`
@@ -386,7 +391,7 @@ password_not_match = The passwords do not match.
lang_select_error = Select a language from the list.
username_been_taken = The username is already taken.
-repo_name_been_taken = The repository name is already used.
+repo_name_been_taken = The repository name or path is already used.
visit_rate_limit = Remote visit addressed rate limitation.
2fa_auth_required = Remote visit required two factors authentication.
org_name_been_taken = The organization name is already taken.
@@ -899,7 +904,7 @@ modelarts.train_job.description=Description
modelarts.train_job.parameter_setting=Parameter setting
modelarts.train_job.parameter_setting_info=Parameter Info
modelarts.train_job.fast_parameter_setting=fast_parameter_setting
-modelarts.train_job.fast_parameter_setting_config=fast_parameter_setting_config
+modelarts.train_job.fast_parameter_setting_config=fast_parameter_setting_config
modelarts.train_job.fast_parameter_setting_config_link=fast_parameter_setting_config_link
modelarts.train_job.frames=frames
modelarts.train_job.algorithm_origin=Algorithm Origin
@@ -974,6 +979,9 @@ template.avatar = Avatar
template.issue_labels = Issue Labels
template.one_item = Must select at least one template item
template.invalid = Must select a template repository
+template.repo_adress=Adress
+template.repo_path=path
+template.repo_name=Name
archive.title = This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
archive.issue.nocomment = This repo is archived. You cannot comment on issues.
@@ -1194,7 +1202,7 @@ issues.filter_label_exclude = `Use alt
+ click/enter
t
issues.filter_label_no_select = All labels
issues.filter_milestone = Milestone
issues.filter_milestone_no_select = All milestones
-issues.filter_milestone_no_add = Not add milestones
+issues.filter_milestone_no_add = Not add milestones
issues.filter_assignee = Assignee
issues.filter_assginee_no_select = All assignees
issues.filter_type = Type
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 935b6112b..7f8bab699 100755
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -350,7 +350,10 @@ modify=更新
[form]
UserName=用户名
-RepoName=项目名称
+RepoName=项目路径
+Alias=项目名称
+RepoPath=项目路径
+RepoAdress=项目地址
Email=邮箱地址
Password=密码
Retype=重新输入密码
@@ -374,7 +377,10 @@ SSPIDefaultLanguage=默认语言
require_error=不能为空。
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。
alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。
+reponame_dash_dot_error=请输入中文、字母、数字和-_ .,最多100个字符。
+repoadd_dash_dot_error=路径只允许字母、数字和-_ .,最多100个字符。
git_ref_name_error=` 必须是格式良好的 git 引用名称。`
+alpha_dash_dot_chinese_error=应该只包含字母数字中文, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。
size_error=长度必须为 %s。
min_size_error=长度最小为 %s 个字符。
max_size_error=长度最大为 %s 个字符。
@@ -388,7 +394,7 @@ password_not_match=密码不匹配。
lang_select_error=从列表中选出语言
username_been_taken=用户名已被使用。
-repo_name_been_taken=项目名称已被使用。
+repo_name_been_taken=项目名称或项目路径已被使用。
visit_rate_limit=远程访问达到速度限制。
2fa_auth_required=远程访问需要双重验证。
org_name_been_taken=组织名称已被使用。
@@ -984,6 +990,9 @@ template.avatar=头像
template.issue_labels=任务标签
template.one_item=必须至少选择一个模板项
template.invalid=必须选择一个模板项目
+template.repo_adress=项目地址
+template.repo_path=项目地址
+template.repo_name=项目名称
archive.title=此项目已存档。您可以查看文件和克隆,但不能推送或创建任务/合并请求。
archive.issue.nocomment=此项目已存档,您不能在此任务添加评论。
diff --git a/public/home/home.js b/public/home/home.js
index d7eb5ab04..f49c8248b 100644
--- a/public/home/home.js
+++ b/public/home/home.js
@@ -4,7 +4,6 @@ if(isEmpty(token)){
var meta = $("meta[name=_uid]");
if(!isEmpty(meta)){
token = meta.attr("content");
- console.log("token is uid:" + token);
}
}
@@ -33,8 +32,6 @@ var swiperRepo = new Swiper(".homepro-list", {
});
var output = document.getElementById("newmessage");
-console.log("document.location.host="+document.location.host);
-console.log("document.URL="+document.URL);
var url = "ws://" + document.location.host + "/action/notification";
if(document.location.host == "git.openi.org.cn" || document.URL.startsWith("https")){
url = "wss://" + document.location.host + "/action/notification"
@@ -51,18 +48,14 @@ var html =document.documentElement;
var lang = html.attributes["lang"]
var isZh = true;
if(lang != null && lang.nodeValue =="en-US" ){
- console.log("the language is " + lang.nodeValue);
isZh=false;
}else{
- console.log("default lang=zh");
}
socket.onmessage = function (e) {
var data =JSON.parse(e.data)
- console.log("recevie data=" + e.data)
var html = "";
if (data != null){
- console.log("queue length=" + messageQueue.length);
if(messageQueue.length > maxSize){
delete messageQueue[0];
}else{
@@ -71,38 +64,38 @@ socket.onmessage = function (e) {
var currentTime = new Date().getTime();
for(var i = 0; i < messageQueue.length; i++){
var record = messageQueue[i];
-
+
var recordPrefix = getMsg(record);
var actionName = getAction(record.OpType,isZh);
-
+
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){
html += recordPrefix + actionName;
- html += " " + getIssueText(record) + ""
+ html += " " + getIssueText(record) + ""
}
else if(record.OpType == "7" || record.OpType == "11" || record.OpType == "14" || record.OpType == "15" || record.OpType == "22"
|| record.OpType == "23"){
html += recordPrefix + actionName;
- html += " " + getPRText(record) + ""
+ html += " " + getPRText(record) + ""
}
else if(record.OpType == "1"){
html += recordPrefix + actionName;
- html += " " + getRepoLink(record) + ""
+ html += " " +getRepotext(record) + ""
}
else if(record.OpType == "9" || record.OpType == "5"){
branch = "" + record.RefName + ""
actionName = actionName.replace("{branch}",branch);
html += recordPrefix + actionName;
- html += " " + getRepoLink(record) + ""
+ html += " " + getRepotext(record) + ""
}else if(record.OpType == "17"){
actionName = actionName.replace("{deleteBranchName}",record.RefName);
- var repoLink = "" + getRepoLink(record) + ""
+ var repoLink = "" + getRepotext(record) + ""
actionName = actionName.replace("{repoName}",repoLink);
html += recordPrefix + actionName;
}
else if(record.OpType == "2"){
actionName = actionName.replace("{oldRepoName}",record.Content);
html += recordPrefix + actionName;
- html += " " + getRepoLink(record) + ""
+ html += " " + getRepotext(record) + ""
}
else{
continue;
@@ -115,17 +108,8 @@ socket.onmessage = function (e) {
html += "";
html += "";
}
- /*
-