#1421 合并“项目名称支持中文”特性分支代码到里程碑分支

Merged
ychao_1983 merged 64 commits from V20220110.patch into V20220125 2 years ago
  1. +1
    -1
      integrations/pull_update_test.go
  2. +18
    -0
      models/action.go
  3. +114
    -19
      models/repo.go
  4. +1
    -0
      models/repo_generate.go
  5. +3
    -2
      models/repo_list.go
  6. +7
    -2
      models/repo_tag.go
  7. +2
    -0
      modules/auth/auth.go
  8. +3
    -0
      modules/auth/repo_form.go
  9. +16
    -0
      modules/notification/action/action.go
  10. +1
    -0
      modules/notification/base/notifier.go
  11. +4
    -0
      modules/notification/base/null.go
  12. +1
    -0
      modules/repository/create.go
  13. +2
    -1
      modules/repository/fork.go
  14. +1
    -1
      modules/repository/fork_test.go
  15. +1
    -0
      modules/repository/generate.go
  16. +1
    -1
      modules/repository/init.go
  17. +28
    -25
      modules/structs/repo.go
  18. +1
    -0
      modules/task/task.go
  19. +24
    -0
      modules/validation/binding.go
  20. +12
    -4
      options/locale/locale_en-US.ini
  21. +11
    -2
      options/locale/locale_zh-CN.ini
  22. +32
    -84
      public/home/home.js
  23. +1
    -1
      routers/api/v1/repo/fork.go
  24. +2
    -1
      routers/home.go
  25. +1
    -1
      routers/org/teams.go
  26. +2
    -1
      routers/repo/pull.go
  27. +31
    -1
      routers/repo/repo.go
  28. +36
    -4
      routers/repo/setting.go
  29. +1
    -0
      routers/routes/routes.go
  30. +2
    -2
      services/repository/repository.go
  31. +2
    -2
      services/repository/transfer.go
  32. +1
    -1
      templates/admin/repo/list.tmpl
  33. +7
    -7
      templates/explore/repo_list.tmpl
  34. +2
    -2
      templates/org/repo_list.tmpl
  35. +2
    -1
      templates/org/select_pro.tmpl
  36. +1
    -1
      templates/org/team/repositories.tmpl
  37. +4
    -32
      templates/repo/create.tmpl
  38. +5
    -5
      templates/repo/header.tmpl
  39. +2
    -11
      templates/repo/home.tmpl
  40. +3
    -31
      templates/repo/migrate.tmpl
  41. +3
    -32
      templates/repo/pulls/fork.tmpl
  42. +57
    -0
      templates/repo/repo_name.tmpl
  43. +47
    -13
      templates/repo/settings/options.tmpl
  44. +21
    -21
      templates/user/dashboard/feeds.tmpl
  45. +4
    -1
      templates/user/dashboard/issues.tmpl
  46. +4
    -1
      templates/user/dashboard/milestones.tmpl
  47. +1
    -1
      templates/user/dashboard/repolist.tmpl
  48. +1
    -1
      templates/user/settings/repos.tmpl
  49. +3
    -0
      web_src/js/components/EditAboutInfo.vue
  50. +97
    -5
      web_src/js/index.js
  51. +1
    -1
      web_src/less/_form.less

+ 1
- 1
integrations/pull_update_test.go View File

@@ -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)



+ 18
- 0
models/action.go View File

@@ -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 {


+ 114
- 19
models/repo.go View File

@@ -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


+ 1
- 0
models/repo_generate.go View File

@@ -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


+ 3
- 2
models/repo_list.go View File

@@ -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)})
}


+ 7
- 2
models/repo_tag.go View File

@@ -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,
})
}


+ 2
- 0
modules/auth/auth.go View File

@@ -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
}


+ 3
- 0
modules/auth/repo_form.go View File

@@ -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


+ 16
- 0
modules/notification/action/action.go View File

@@ -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,


+ 1
- 0
modules/notification/base/notifier.go View File

@@ -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)


+ 4
- 0
modules/notification/base/null.go View File

@@ -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) {
}


+ 1
- 0
modules/repository/create.go View File

@@ -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,


+ 2
- 1
modules/repository/fork.go View File

@@ -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,


+ 1
- 1
modules/repository/fork_test.go View File

@@ -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))


+ 1
- 0
modules/repository/generate.go View File

@@ -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,


+ 1
- 1
modules/repository/init.go View File

@@ -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,


+ 28
- 25
modules/structs/repo.go View File

@@ -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"`


+ 1
- 0
modules/task/task.go View File

@@ -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,


+ 24
- 0
modules/validation/binding.go View File

@@ -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)
}

+ 12
- 4
options/locale/locale_en-US.ini View File

@@ -346,7 +346,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
@@ -370,7 +372,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.`
@@ -384,7 +389,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.
@@ -897,7 +902,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
@@ -964,6 +969,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.
@@ -1184,7 +1192,7 @@ issues.filter_label_exclude = `Use <code>alt</code> + <code>click/enter</code> 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


+ 11
- 2
options/locale/locale_zh-CN.ini View File

@@ -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=组织名称已被使用。
@@ -976,6 +982,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=此项目已存档,您不能在此任务添加评论。


+ 32
- 84
public/home/home.js View File

@@ -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 += " <a href=\"" + getIssueLink(record) + "\" rel=\"nofollow\">" + getIssueText(record) + "</a>"
html += " <a href=\"" + getIssueLink(record) + "\" rel=\"nofollow\">" + getIssueText(record) + "</a>"
}
else if(record.OpType == "7" || record.OpType == "11" || record.OpType == "14" || record.OpType == "15" || record.OpType == "22"
|| record.OpType == "23"){
html += recordPrefix + actionName;
html += " <a href=\"" + getPRLink(record) + "\" rel=\"nofollow\">" + getPRText(record) + "</a>"
html += " <a href=\"" + getPRLink(record) + "\" rel=\"nofollow\">" + getPRText(record) + "</a>"
}
else if(record.OpType == "1"){
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>"
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>"
}
else if(record.OpType == "9" || record.OpType == "5"){
branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>"
actionName = actionName.replace("{branch}",branch);
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>"
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}else if(record.OpType == "17"){
actionName = actionName.replace("{deleteBranchName}",record.RefName);
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>"
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
actionName = actionName.replace("{repoName}",repoLink);
html += recordPrefix + actionName;
}
else if(record.OpType == "2"){
actionName = actionName.replace("{oldRepoName}",record.Content);
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>"
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}
else{
continue;
@@ -115,17 +108,8 @@ socket.onmessage = function (e) {
html += "</div>";
html += "</div>";
}
/*
<div class="swiper-slide item">
<img class="ui avatar image" src="/user/avatar/zhoupzh/-1" alt="">
<div class="middle aligned content">
<a href="/zhoupzh" title="">zhoupzh</a> 合并了合并请求 <a href="/OpenI/aiforge/pulls/1168" rel="nofollow">OpenI/aiforge#1168</a><span class="time-since">22 分钟前</span>
</div>
</div>
*/

}
console.log("html=" + html)
output.innerHTML = html;
swiperNewMessage.updateSlides();
swiperNewMessage.updateProgress();
@@ -136,15 +120,20 @@ function getMsg(record){
html += "<div class=\"swiper-slide item\">";
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + record.ActUser.Name + "/-1\" alt=\"\">"
html += " <div class=\"middle aligned content nowrap\">"
html += " <a href=\"/" + record.ActUser.Name + "\" title=\"\">" + record.ActUser.Name + "</a>"
html += " <a href=\"/" + record.ActUser.Name + "\" title=\"\">" + record.ActUser.Name + "</a>"
return html;
}

function getRepoLink(record){
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name;
function getRepotext(record){
if(record.Repo.Alias){
return record.Repo.OwnerName + "/" + record.Repo.Alias;
}else{
return record.Repo.OwnerName + "/" + record.Repo.Name;
}
}
function getRepoLink(record){
return record.Repo.OwnerName + "/" + record.Repo.Name;

}

function getTime(UpdatedUnix,currentTime){
@@ -154,8 +143,7 @@ function getTime(UpdatedUnix,currentTime){
if( timeEscSecond < 0){
timeEscSecond = 1;
}
console.log("currentTime=" + currentTime + " updateUnix=" + UpdatedUnix);

var hours= Math.floor(timeEscSecond / 3600);
//计算相差分钟数
var leave2 = Math.floor(timeEscSecond % (3600)); //计算小时数后剩余的秒数
@@ -179,11 +167,16 @@ function getPRLink(record){
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record);
}
function getPRText(record){
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record);
if(record.Repo.Alias){
return record.Repo.OwnerName + "/" + record.Repo.Alias + "#" + getIssueId(record);
}else{
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record);
}

}

function getIssueLink(record){
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record);
}

@@ -204,7 +197,12 @@ function getIssueId(record){
}

function getIssueText(record){
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record);
if(record.Repo.Alias){
return record.Repo.OwnerName + "/" + record.Repo.Alias + "#" + getIssueId(record);
}else{
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record);
}

}

/*
@@ -320,11 +318,9 @@ function queryRecommendData(){
dataType:"json",
async:false,
success:function(json){
console.log(json);
displayOrg(json);
},
error:function(response) {
console.log(response);
}
});

@@ -337,40 +333,14 @@ function queryRecommendData(){
dataType:"json",
async:false,
success:function(json){
console.log(json);
displayRepo(json);
},
error:function(response) {
console.log(response);
}
});

}

/*
<div class="swiper-slide">
<div class="ui fluid card">
<div class="content">
<span class="right floated meta">
<i class="star icon"></i>276 <i class="star icon"></i>32
</span>
<img class="left floated mini ui image" src="/repo-avatars/278-a9f45e21b92b86dbf969c9f70dff1efc">
<a class="header nowrap" href="/OpenI/aiforge">aiforge </a>
<div class="description nowrap-2">
本项目是群体化方法与技术的开源实现案例,在基于Gitea的基础上,进一步支持社交化的协同开发、协同学习、协同研究等群体创新实践服务,特别是针对新一代人工智能技术特点,重点支持项目管理、git代码管理、大数据集存储管理与智能计算平台接入。
</div>
<div class="ui tags nowrap am-mt-10">
<a class="ui small label topic" href="/explore/repos?q=ai%e5%bc%80%e5%8f%91%e5%b7%a5%e5%85%b7&amp;topic=">ai开发工具</a>
<a class="ui small label topic" href="/explore/repos?q=openi&amp;topic=">openi</a>
<a class="ui small label topic" href="/explore/repos?q=golang&amp;topic=">golang</a>
<a class="ui small label topic" href="/explore/repos?q=git&amp;topic=">git</a>
<a class="ui small label topic" href="/explore/repos?q=pcl&amp;topic=">pcl</a>
</div>
</div>
</div>
</div>
*/
function displayRepo(json){
var orgRepo = document.getElementById("recommendrepo");
var html = "";
@@ -384,7 +354,7 @@ function displayRepo(json){
html += " <i class=\"ri-star-line\"></i>" + record["NumStars"] + "<i class=\"ri-git-branch-line am-ml-10\"></i>" + record["NumForks"];
html += " </span>";
html += " <img class=\"left floated mini ui image\" src=\"" + record["Avatar"] + "\">";
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Name"] +"</a>";
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Alias"] +"</a>";
html += " <div class=\"description nowrap-2\">" + record["Description"] + " </div>";
html += " <div class=\"ui tags nowrap am-mt-10\">"
if(record["Topics"] != null){
@@ -405,27 +375,6 @@ function displayRepo(json){
swiperRepo.updateProgress();
}

/**
*
* <div class="column">
<div class="ui fluid card">
<div class="content">
<div class="ui small header">
<img class="ui image" src="/user/avatar/OpenI/-1">
<div class="content nowrap">
<a href="/OpenI">OpenI</a> 启智社区
<div class="sub header">39 项目 ・ 60 成员 ・ 23 团队</div>
</div>
</div>
</div>
</div>
</div>
*/

//var repoAndOrgZH = new Map([['1', "项目"], ['2', "成员"], ['3', "团队"]]);
//var repoAndOrgEN = new Map([['1', "Repository"], ['2', "Members"], ['3', "Teams"]]);


function getRepoOrOrg(key,isZhLang,numbers=1){
if(numbers > 1){
@@ -437,7 +386,6 @@ function getRepoOrOrg(key,isZhLang,numbers=1){
return repoAndOrgEN[key];
}
}

function displayOrg(json){
var orgDiv = document.getElementById("recommendorg");
var html = "";
@@ -460,4 +408,4 @@ function displayOrg(json){
}
}
orgDiv.innerHTML = html;
}
}

+ 1
- 1
routers/api/v1/repo/fork.go View File

@@ -118,7 +118,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) {
forker = org
}

fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description)
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description, repo.Alias)
if err != nil {
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)
return


+ 2
- 1
routers/home.go View File

@@ -625,11 +625,12 @@ func RecommendRepoFromPromote(ctx *context.Context) {
} else {
ownerName := strings.Trim(repoName[0:tmpIndex], " ")
repoName := strings.Trim(repoName[tmpIndex+1:], " ")
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
repo, err := models.GetRepositoryByOwnerAndAlias(ownerName, repoName)
if err == nil {
repoMap := make(map[string]interface{})
repoMap["ID"] = fmt.Sprint(repo.ID)
repoMap["Name"] = repo.Name
repoMap["Alias"] = repo.Alias
repoMap["OwnerName"] = repo.OwnerName
repoMap["NumStars"] = repo.NumStars
repoMap["NumForks"] = repo.NumForks


+ 1
- 1
routers/org/teams.go View File

@@ -143,7 +143,7 @@ func TeamsRepoAction(ctx *context.Context) {
case "add":
repoName := path.Base(ctx.Query("repo_name"))
var repo *models.Repository
repo, err = models.GetRepositoryByName(ctx.Org.Organization.ID, repoName)
repo, err = models.GetRepositoryByOwnerAndAlias(ctx.Org.Organization.Name, repoName)
if err != nil {
if models.IsErrRepoNotExist(err) {
ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo"))


+ 2
- 1
routers/repo/pull.go View File

@@ -105,6 +105,7 @@ func getForkRepository(ctx *context.Context) *models.Repository {
return nil
}
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
ctx.Data["ForkDisplayName"] = forkRepo.FullDisplayName()
ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID

if err := ctx.User.GetOwnedOrganizations(); err != nil {
@@ -221,7 +222,7 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
}
}

repo, err := repo_service.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description)
repo, err := repo_service.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description, form.Alias)
if err != nil {
ctx.Data["Err_RepoName"] = true
switch {


+ 31
- 1
routers/repo/repo.go View File

@@ -6,11 +6,14 @@
package repo

import (
"code.gitea.io/gitea/modules/validation"
"fmt"
"net/url"
"os"
"path"
"regexp"
"strings"
"unicode/utf8"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
@@ -201,6 +204,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
if form.RepoTemplate > 0 {
opts := models.GenerateRepoOptions{
Name: form.RepoName,
Alias: form.Alias,
Description: form.Description,
Private: form.Private,
GitContent: form.GitContent,
@@ -235,6 +239,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
} else {
repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
Name: form.RepoName,
Alias: form.Alias,
Description: form.Description,
Gitignores: form.Gitignores,
IssueLabels: form.IssueLabels,
@@ -358,6 +363,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
GitServiceType: gitServiceType,
CloneAddr: remoteAddr,
RepoName: form.RepoName,
Alias: form.Alias,
Description: form.Description,
Private: form.Private || setting.Repository.ForcePrivate,
Mirror: form.Mirror,
@@ -380,7 +386,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
opts.Releases = false
}

err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName)
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, opts.Alias)
if err != nil {
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
return
@@ -552,3 +558,27 @@ func Status(ctx *context.Context) {
"err": task.Errors,
})
}

var repoNamePattern = regexp.MustCompile("^[0-9a-zA-Z\\.\\-_]{1,100}$")
var repoAliasPattern = regexp.MustCompile("^[\u4e00-\u9fa5\\.\\-_A-Za-z0-9]{1,100}$")

// CheckName returns repository's default name(by given alias)
func CheckName(ctx *context.Context) {
var r = make(map[string]string, 1)
q := ctx.Query("q")
owner := ctx.Query("owner")
if q == "" || owner == "" || utf8.RuneCountInString(q) > 100 || !validation.ValidAlphaDashDotChinese(q) {
r["name"] = ""
ctx.JSON(200, r)
return
}
if repoNamePattern.MatchString(q) {
r["name"] = q
ctx.JSON(200, r)
return
}
n := models.GenerateDefaultRepoName(owner)
r["name"] = n
ctx.JSON(200, r)
return
}

+ 36
- 4
routers/repo/setting.go View File

@@ -6,6 +6,7 @@
package repo

import (
"code.gitea.io/gitea/modules/notification"
"errors"
"fmt"
"io/ioutil"
@@ -70,6 +71,30 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
return
}

newAlias := form.Alias
var aliasChanged = false
// Check if repository alias has been changed.
if strings.ToLower(repo.Alias) != strings.ToLower(newAlias) {
aliasChanged = true
//check new alias is available or not
if err := models.IsRepositoryAliasAvailable(ctx.Repo.Owner, newAlias); err != nil {
ctx.Data["Err_Alias"] = true
switch {
case models.IsErrRepoAlreadyExist(err):
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tplSettingsOptions, &form)
case models.IsErrNameReserved(err):
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tplSettingsOptions, &form)
case models.IsErrNamePatternNotAllowed(err):
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form)
default:
ctx.ServerError("ChangeRepositoryName", err)
}
return
}

log.Trace("Repository alias changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Alias, newAlias)
}

newRepoName := form.RepoName
// Check if repository name has been changed.
if repo.LowerName != strings.ToLower(newRepoName) {
@@ -95,12 +120,19 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {

log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName)
}
//notify
if aliasChanged {
notification.NotifyRenameRepository(ctx.Repo.Owner, repo, repo.Alias)
}

// In case it's just a case change.
repo.Name = newRepoName
repo.LowerName = strings.ToLower(newRepoName)
repo.Description = form.Description
repo.Website = form.Website
repo.IsTemplate = form.Template
repo.Alias = newAlias
repo.LowerAlias = strings.ToLower(newAlias)

// Visibility of forked repository is forced sync with base repository.
if repo.IsFork {
@@ -380,7 +412,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Error(404)
return
}
if repo.Name != form.RepoName {
if repo.Alias != form.RepoName {
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
return
}
@@ -407,7 +439,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Error(404)
return
}
if repo.Name != form.RepoName {
if repo.Alias != form.RepoName {
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
return
}
@@ -445,7 +477,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Error(404)
return
}
if repo.Name != form.RepoName {
if repo.Alias != form.RepoName {
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
return
}
@@ -465,7 +497,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Error(404)
return
}
if repo.Name != form.RepoName {
if repo.Alias != form.RepoName {
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
return
}


+ 1
- 0
routers/routes/routes.go View File

@@ -718,6 +718,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/:repoid").Get(repo.Fork).
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
}, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader)
m.Get("/check_name", repo.CheckName)
}, reqSignIn)

// ***** Release Attachment Download without Signin


+ 2
- 2
services/repository/repository.go View File

@@ -31,8 +31,8 @@ func CreateRepository(doer, owner *models.User, opts models.CreateRepoOptions) (
}

// ForkRepository forks a repository
func ForkRepository(doer, u *models.User, oldRepo *models.Repository, name, desc string) (*models.Repository, error) {
repo, err := repo_module.ForkRepository(doer, u, oldRepo, name, desc)
func ForkRepository(doer, u *models.User, oldRepo *models.Repository, name, desc, alias string) (*models.Repository, error) {
repo, err := repo_module.ForkRepository(doer, u, oldRepo, name, desc, alias)
if err != nil {
if repo != nil {
if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != nil {


+ 2
- 2
services/repository/transfer.go View File

@@ -55,7 +55,7 @@ func TransferOwnership(doer, newOwner *models.User, repo *models.Repository, tea

// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoName string) error {
oldRepoName := repo.Name
//oldRepoName := repo.Name

// Change repository directory name. We must lock the local copy of the
// repo so that we can atomically rename the repo path and updates the
@@ -68,7 +68,7 @@ func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoNam
}
repoWorkingPool.CheckOut(com.ToStr(repo.ID))

notification.NotifyRenameRepository(doer, repo, oldRepoName)
//notification.NotifyRenameRepository(doer, repo, oldRepoName)

return nil
}

+ 1
- 1
templates/admin/repo/list.tmpl View File

@@ -36,7 +36,7 @@
<span class="text gold">{{svg "octicon-lock" 16}}</span>
{{end}}
</td>
<td><a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Name}}</a></td>
<td><a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Alias}}</a></td>
<td><i class="fa fa{{if .IsPrivate}}-check{{end}}-square-o"></i></td>
<td>{{.NumWatches}}</td>
<td>{{.NumStars}}</td>


+ 7
- 7
templates/explore/repo_list.tmpl View File

@@ -5,7 +5,7 @@
border-radius: 0.8rem;
margin-bottom: 1.0rem;
padding: 1.0rem !important;
}
}
.ui.repository.list>.item .header {
font-size: 1.4rem !important;
font-weight: 200;
@@ -24,7 +24,7 @@
content: "";
height: 1px;
background-color: #E1E3E6;
bottom: 2.8rem;
bottom: 2.8rem;
}
.repository .ui.mini.menu{
font-size: .6rem;
@@ -43,13 +43,13 @@
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot&tab={{$.TabName}}">
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-repo" />
</svg>
</svg>
热门{{.i18n.Tr "explore.repos"}}
</a>
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}">
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-inbox" />
</svg>
</svg>
活跃{{.i18n.Tr "explore.repos"}}
</a>
{{end}}
@@ -93,7 +93,7 @@
<div class="ui grid">
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column">
<a class="name" href="{{.Link}}">
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.Name}}</strong>
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.DisplayName}}</strong>
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
</a>
{{if .IsPrivate}}
@@ -114,7 +114,7 @@
<a class="item">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z" />
</svg>
</svg>
{{.Hot}}
</a>
{{else if eq $.SortType "active"}}
@@ -130,7 +130,7 @@
<a class="item">
{{svg "octicon-git-branch" 16}} {{.NumForks}}
</a>
{{end}}
{{end}}
<a class="item">
{{svg "octicon-star" 16}} {{.NumStars}}
</a>


+ 2
- 2
templates/org/repo_list.tmpl View File

@@ -33,7 +33,7 @@
<img class="ui avatar image" src="{{.RelAvatarLink}}">
{{end}}
<a class="name" href="{{.Link}}">
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{.Name}}
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
</a>
{{if .IsPrivate}}
@@ -70,4 +70,4 @@
{{$.i18n.Tr "explore.repo_no_results"}}
</div>
{{end}}
</div>
</div>

+ 2
- 1
templates/org/select_pro.tmpl View File

@@ -89,7 +89,7 @@
<div class="extra full_height cor" >
<div class=" header header_card omit" >
<a class="header_card image poping up " href="{{.Link}}" data-content="{{.Name}}" data-position="top left" data-variation="tiny inverted"> {{.Name}}</a>
<a class="header_card image poping up " href="{{.Link}}" data-content="{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}" data-position="top left" data-variation="tiny inverted">{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}</a>
</div>
<div class='content descript_height nowrap-2'>
@@ -167,6 +167,7 @@
</div>

<script>
console.log({{.tags}})
var data;
var filterData=[];
var num=0;


+ 1
- 1
templates/org/team/repositories.tmpl View File

@@ -50,7 +50,7 @@
{{else}}
{{svg "octicon-repo" 16}}
{{end}}
<strong>{{$.Org.Name}}/{{.Name}}</strong>
<strong>{{$.Org.Name}}/{{.Alias}}</strong>
</a>
</div>
{{else}}


+ 4
- 32
templates/repo/create.tmpl View File

@@ -2,43 +2,15 @@
<div class="repository new repo" style="margin-top: 40px;">
<div class="ui middle very relaxed page grid">
<div class="column">
<form class="ui form" action="{{.Link}}" method="post">
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form">
{{.CsrfTokenHtml}}
<h3 class="ui top attached header">
{{.i18n.Tr "new_repo"}}
</h3>
<div class="ui attached segment">
{{template "base/alert" .}}
<div class="inline required field {{if .Err_Owner}}error{{end}}">
<label>{{.i18n.Tr "repo.owner"}}</label>
<div class="ui selection owner dropdown">
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
<span class="text" title="{{.ContextUser.Name}}">
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
{{.ContextUser.ShortName 20}}
</span>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}">
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
{{.SignedUser.ShortName 20}}
</div>
{{range .Orgs}}
<div class="item" data-value="{{.ID}}" title="{{.Name}}">
<img class="ui mini image" src="{{.RelAvatarLink}}">
{{.ShortName 20}}
</div>
{{end}}
</div>
</div>
<span class="help">{{.i18n.Tr "repo.repo_owner_helper"}}</span>
</div>

<div class="inline required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" value="{{.repo_name}}" autofocus required>
<span class="help"></span>
</div>
{{template "repo/repo_name" .}}
<!-- <div class="js-project-full-path" id="repoAdress" ></div> -->
<div class="inline field">
<label>{{.i18n.Tr "repo.visibility"}}</label>
<div class="ui checkbox">
@@ -172,7 +144,7 @@
<br/>
<div class="inline field">
<label></label>
<button class="ui green button">
<button class="ui green button" id="submit_reponame">
{{.i18n.Tr "repo.create_repo"}}
</button>
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a>


+ 5
- 5
templates/repo/header.tmpl View File

@@ -24,7 +24,7 @@
{{end}}
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
<div class="divider"> / </div>
<a href="{{$.RepoLink}}">{{.Name}}</a>
<a href="{{$.RepoLink}}">{{.DisplayName}}</a>
{{if .RelAvatarLink}}
{{if .IsTemplate}}
{{if .IsPrivate}}
@@ -46,7 +46,7 @@
{{end}}
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
{{if .IsMirror}}<div class="fork-flag">{{$.i18n.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}">{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}</a></div>{{end}}
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}}
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullDisplayName}}</a></div>{{end}}
{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}}
</div>
{{if not .IsBeingCreated}}
@@ -114,9 +114,9 @@
{{end}}
</div>
</div>
{{end}}


{{if .Permission.CanRead $.UnitTypeIssues}}
@@ -152,7 +152,7 @@
{{if .Permission.CanRead $.UnitTypeCloudBrain}}
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all">
<span>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 3h16a1 1 0 0 1 1 1v7H3V4a1 1 0 0 1 1-1zM3 13h18v7a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-7zm4 3v2h3v-2H7zM7 6v2h3V6H7z"/></svg>
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 3h16a1 1 0 0 1 1 1v7H3V4a1 1 0 0 1 1-1zM3 13h18v7a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-7zm4 3v2h3v-2H7zM7 6v2h3V6H7z"/></svg>
{{.i18n.Tr "repo.cloudbrain"}}
<i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i>
</span>


+ 2
- 11
templates/repo/home.tmpl View File

@@ -256,11 +256,8 @@
</div>
<div class="ui six wide tablet four wide computer column">
<div id="repo-desc">
<h4 id="about-desc" class="ui header">简介
<!-- <a class="edit-icon" href="javascript:void(0)">
<i class="gray edit outline icon"></i>
</a> -->
</h4>
<h4 id="about-desc" class="ui header">简介</h4>
<input type="hidden" id="edit-alias" value="{{.Repository.Alias}}">
<p>
{{if .Repository.DescriptionHTML}}
<span class="description" style="word-break:break-all">{{.Repository.DescriptionHTML}}</span>
@@ -286,14 +283,8 @@
<i class="grey bookmark icon"></i>

<div id="repo-topics1" style="flex: 1;">
<!-- {{if not .Topics}}
<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>
{{end}} -->
{{range .Topics}}

<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a>


{{end}}
</div>
<div>


+ 3
- 31
templates/repo/migrate.tmpl View File

@@ -2,7 +2,7 @@
<div class="repository new migrate" style="margin-top: 40px;">
<div class="ui middle very relaxed page grid">
<div class="column">
<form class="ui form" action="{{.Link}}" method="post">
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form">
{{.CsrfTokenHtml}}
<h3 class="ui top attached header">
{{.i18n.Tr "new_migrate"}}
@@ -37,35 +37,7 @@
</div>

<div class="ui divider"></div>

<div class="inline required field {{if .Err_Owner}}error{{end}}">
<label>{{.i18n.Tr "repo.owner"}}</label>
<div class="ui selection owner dropdown">
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
<span class="text" title="{{.ContextUser.Name}}">
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
{{.ContextUser.ShortName 20}}
</span>
<i class="dropdown icon"></i>
<div class="menu" title="{{.SignedUser.Name}}">
<div class="item" data-value="{{.SignedUser.ID}}">
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
{{.SignedUser.ShortName 20}}
</div>
{{range .Orgs}}
<div class="item" data-value="{{.ID}}" title="{{.Name}}">
<img class="ui mini image" src="{{.RelAvatarLink}}">
{{.ShortName 20}}
</div>
{{end}}
</div>
</div>
</div>

<div class="inline required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" value="{{.repo_name}}" required>
</div>
{{template "repo/repo_name" .}}
<div class="inline field">
<label>{{.i18n.Tr "repo.visibility"}}</label>
<div class="ui checkbox">
@@ -127,7 +99,7 @@

<div class="inline field">
<label></label>
<button class="ui green button">
<button class="ui green button" id="submit_reponame">
{{.i18n.Tr "repo.migrate_repo"}}
</button>
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a>


+ 3
- 32
templates/repo/pulls/fork.tmpl View File

@@ -2,47 +2,18 @@
<div class="repository new fork">
<div class="ui middle very relaxed page grid">
<div class="column">
<form class="ui form" action="{{.Link}}" method="post">
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form">
{{.CsrfTokenHtml}}
<h3 class="ui top attached header">
{{.i18n.Tr "new_fork"}}
</h3>
<div class="ui attached segment">
{{template "base/alert" .}}
<div class="inline required field {{if .Err_Owner}}error{{end}}">
<label>{{.i18n.Tr "repo.owner"}}</label>
<div class="ui selection owner dropdown">
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
<span class="text" title="{{.ContextUser.Name}}">
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
{{.ContextUser.ShortName 20}}
</span>
<i class="dropdown icon"></i>
<div class="menu">
{{if .CanForkToUser}}
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}">
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
{{.SignedUser.ShortName 20}}
</div>
{{end}}
{{range .Orgs}}
<div class="item" data-value="{{.ID}}" title="{{.Name}}">
<img class="ui mini image" src="{{.RelAvatarLink}}">
{{.ShortName 20}}
</div>
{{end}}
</div>
</div>
</div>

<div class="inline field">
<label>{{.i18n.Tr "repo.fork_from"}}</label>
<a href="{{AppSubUrl}}/{{.ForkFrom}}">{{.ForkFrom}}</a>
</div>
<div class="inline required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" value="{{.repo_name}}" required>
<a href="{{AppSubUrl}}/{{.ForkFrom}}">{{.ForkDisplayName}}</a>
</div>
{{template "repo/repo_name" .}}
<div class="inline field">
<label>{{.i18n.Tr "repo.visibility"}}</label>
<div class="ui read-only checkbox">


+ 57
- 0
templates/repo/repo_name.tmpl View File

@@ -0,0 +1,57 @@
<div class="inline required field {{if .Err_RepoName}}error{{end}}" >
<label for="Alias">{{.i18n.Tr "form.Alias"}}</label>
<input id="alias" name="alias" value="{{.alias}}" autofocus required maxlength="100">
<span class="help">{{.i18n.Tr "form.reponame_dash_dot_error"}}</span>
</div>

<div class="inline required fields" style="margin-bottom: 0;">
<label style="text-align: right;width: 250px!important;word-wrap: break-word;">{{.i18n.Tr "form.RepoPath"}}</label>
<div class="required field {{if .Err_Owner}}error{{end}}" style="padding: 0;">
<!-- <label>{{.i18n.Tr "repo.owner"}}</label> -->
<div class="ui selection owner dropdown" id="ownerDropdown">
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
<div class="text" title="{{.ContextUser.Name}}">
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
{{.ContextUser.ShortName 20}}
</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}">
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}">
{{.SignedUser.ShortName 20}}
</div>
{{range .Orgs}}
<div class="item" data-value="{{.ID}}" title="{{.Name}}">
<img class="ui mini image" src="{{.RelAvatarLink}}">
{{.ShortName 20}}
</div>
{{end}}
</div>
</div>
<!-- <span class="help">{{.i18n.Tr "repo.repo_owner_helper"}}</span> -->
</div>
<!-- <div class="required field {{if .Err_RepoName}}error{{end}}">
<input id="repo_name" name="repo_name" value="{{.repo_name}}" autofocus required>
</div> -->
<div class="ui interval" style="width: 0.6em;font-size: 2rem;line-height: 0px;text-align: center;">/</div>
<div class="required field {{if .Err_RepoName}}error{{end}}">
<!-- <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> -->
<input style="width: 100% !important;" id="repo_name" name="repo_name" value="{{.repo_name}}" maxlength="100" autofocus required>
</div>
</div>
<span style="display: block;margin-bottom: 1em;" class="help">{{.i18n.Tr "form.repoadd_dash_dot_error"}}</span>
<div class="inline field" id="repoAdress" style="display: none;word-break: break-all;">
<label for="">{{.i18n.Tr "form.RepoAdress"}}:</label>
<span style="flex: 1;"></span>
</div>

<script>
console.log({{$.Err_Alias}})
</script>

+ 47
- 13
templates/repo/settings/options.tmpl View File

@@ -8,12 +8,46 @@
{{.i18n.Tr "repo.settings.basic_settings"}}
</h4>
<div class="ui attached segment">
<form class="ui form" action="{{.Link}}" method="post">
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
<div class="required field {{if .Err_RepoName}}error{{end}}">
<!-- <div class="required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required>
<input id="repo_name" name="alias" value="{{.Repository.Alias}}" data-repo-name="{{.Repository.Alias}}" autofocus required>
<input type="hidden" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required>
</div> -->
<div class="required field {{if .Err_Alias}}error{{end}}">
<label for="Alias">{{.i18n.Tr "form.Alias"}}</label>
<input name="alias" value="{{.Repository.Alias}}" data-repo-name="{{.Repository.Alias}}" autofocus required>
<span class="help">{{.i18n.Tr "form.reponame_dash_dot_error"}}</span>
</div>

<div class="required field">
<label>{{.i18n.Tr "form.RepoPath"}}</label>
<div class="fields">
<div class="eight wide required field {{if .Err_Owner}}error{{end}}">
<div class="ui selection owner dropdown" id="ownerDropdown">
<input type="hidden" id="uid" name="uid" value="{{.Owner.Name}}" required>
<div class="text" title="{{.Owner.Name}}">
<img class="ui mini image" src="{{.Owner.RelAvatarLink}}">
{{.Owner.ShortName 40}}
</div>
</div>
</div>
<div class="ui interval" style="width: 0.6em;font-size: 2rem;line-height: 38px;text-align: center;">/</div>
<div class="eight wide required field {{if .Err_Alias}}error{{end}}">
<!-- <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> -->
<input style="width: 100% !important;" id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required>
<span class="help">{{.i18n.Tr "form.repoadd_dash_dot_error"}}</span>
</div>
</div>
</div>
<div class="inline field" id="repoAdress" style="display: none;">
<label for="">{{.i18n.Tr "form.RepoAdress"}}:</label>
<span></span>
</div>
<div class="inline field">
<label>{{.i18n.Tr "repo.repo_size"}}</label>
@@ -41,7 +75,7 @@
{{end}}
<div class="field {{if .Err_Description}}error{{end}}">
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label>
<textarea id="description" name="description" rows="2" maxlength="255">{{.Repository.Description}}</textarea>
<textarea id="description" name="description" rows="2" maxlength="254">{{.Repository.Description}}</textarea>
</div>
<div class="field {{if .Err_Website}}error{{end}}">
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label>
@@ -152,7 +186,7 @@
{{$isModelMangeEnabled := .Repository.UnitEnabled $.UnitTypeModelManage }}
<div class="inline field">
<label>{{.i18n.Tr "repo.model_manager"}}</label>
<div class="ui checkbox {{if ne $.MODEL_COUNT 0}}disabled{{end}}">
<div class="ui checkbox">
<input class="enable-system" name="enable_model_manager" type="checkbox" {{if $isModelMangeEnabled}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.model_desc"}}</label>
</div>
@@ -160,7 +194,7 @@
{{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }}
<div class="inline field">
<label>{{.i18n.Tr "repo.cloudbrain"}}</label>
<div class="ui checkbox {{if ne $.jobCount 0}}disabled{{end}}">
<div class="ui checkbox">
<input class="enable-system" name="enable_cloud_brain" type="checkbox" {{if $isCloudBrainEnabled}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label>
</div>
@@ -475,7 +509,7 @@
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
<span class="text red">{{.Repository.Alias}}</span>
</label>
</div>
<div class="required field">
@@ -507,7 +541,7 @@
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
<span class="text red">{{.Repository.Alias}}</span>
</label>
</div>
<div class="required field">
@@ -534,7 +568,7 @@
<div class="content">
<div class="ui warning message text left">
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br>
{{.i18n.Tr "repo.settings.delete_notices_2" .Repository.FullName | Safe}}
{{.i18n.Tr "repo.settings.delete_notices_2" .Repository.Alias | Safe}}
{{if .Repository.NumForks}}<br>
{{.i18n.Tr "repo.settings.delete_notices_fork_1"}}
{{end}}
@@ -545,7 +579,7 @@
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
<span class="text red">{{.Repository.Alias}}</span>
</label>
</div>
<div class="required field">
@@ -569,7 +603,7 @@
<div class="content">
<div class="ui warning message text left">
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br>
{{.i18n.Tr "repo.settings.wiki_delete_notices_1" .Repository.Name | Safe}}
{{.i18n.Tr "repo.settings.wiki_delete_notices_1" .Repository.Alias | Safe}}
</div>
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
@@ -577,7 +611,7 @@
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
<span class="text red">{{.Repository.Alias}}</span>
</label>
</div>
<div class="required field">
@@ -625,4 +659,4 @@
{{end}}
{{end}}

{{template "base/footer" .}}
{{template "base/footer" .}}

+ 21
- 21
templates/user/dashboard/feeds.tmpl View File

@@ -13,63 +13,63 @@
{{.ShortActUserName}}
{{end}}
{{if eq .GetOpType 1}}
{{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 2}}
{{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 5}}
{{ $branchLink := .GetBranch | EscapePound | Escape}}
{{$.i18n.Tr "action.commit_repo" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.commit_repo" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 6}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.create_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.create_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 7}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.create_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.create_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 8}}
{{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 9}}
{{ $branchLink := .GetBranch | EscapePound | Escape}}
{{$.i18n.Tr "action.push_tag" .GetRepoLink $branchLink .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.push_tag" .GetRepoLink $branchLink .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 10}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 11}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.merge_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.merge_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 12}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.close_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.close_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 13}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.reopen_issue" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.reopen_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 14}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.close_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.close_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 15}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 16}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 17}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 18}}
{{ $branchLink := .GetBranch | EscapePound}}
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink .GetBranch .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink .GetBranch .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 19}}
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 20}}
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 21}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 22}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{else if eq .GetOpType 23}}
{{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoPath | Str2html}}
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}}
{{end}}
</p>
{{if or (eq .GetOpType 5) (eq .GetOpType 18)}}


+ 4
- 1
templates/user/dashboard/issues.tmpl View File

@@ -107,7 +107,7 @@
{{ $timeStr:= TimeSinceUnix .CreatedUnix $.Lang }}
{{if .Repo}}
<li class="item">
<div class="ui label">{{.Repo.FullName}}#{{.Index}}</div>
<div class="ui label">{{.Repo.OwnerName}}/{{.Repo.Alias}}#{{.Index}}</div>
<a class="title" href="{{.HTMLURL}}">{{RenderEmoji .Title}}</a>

{{if .IsPull}}
@@ -208,3 +208,6 @@
</div>
</div>
{{template "base/footer" .}}
<script>
console.log({{.Issues}})
</script>

+ 4
- 1
templates/user/dashboard/milestones.tmpl View File

@@ -65,7 +65,7 @@
<div class="milestone list">
{{range .Milestones}}
<li class="item">
<div class="ui label">{{.Repo.FullName}}</div>
<div class="ui label">{{.Repo.OwnerName}}/{{.Repo.Alias}}</div>
{{svg "octicon-milestone" 16}} <a href="{{.Repo.Link }}/milestone/{{.ID}}">{{.Name}}</a>
<div class="ui right green progress" data-percent="{{.Completeness}}">
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
@@ -117,3 +117,6 @@
</div>
</div>
{{template "base/footer" .}}
<script>
console.log({{.Milestones}})
</script>

+ 1
- 1
templates/user/dashboard/repolist.tmpl View File

@@ -104,7 +104,7 @@
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)">
<a :href="suburl + '/' + repo.full_name">
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg>
<strong class="text truncate item-name">${repo.full_name}</strong>
<strong class="text truncate item-name">${repo.full_display_name}</strong>
<i v-if="repo.archived" class="archive icon archived-icon"></i>
<span class="ui right text light grey">
${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span>


+ 1
- 1
templates/user/settings/repos.tmpl View File

@@ -21,7 +21,7 @@
{{else}}
<span class="iconFloat">{{svg "octicon-repo" 16}}</span>
{{end}}
<a class="name" href="{{AppSubUrl}}/{{$.Owner.Name}}/{{.Name}}">{{$.Owner.Name}}/{{.Name}}</a>
<a class="name" href="{{AppSubUrl}}/{{$.Owner.Name}}/{{.Name}}">{{$.Owner.Name}}/{{.DisplayName}}</a>
<span>{{SizeFmt .Size}}</span>
{{if .IsFork}}
{{$.i18n.Tr "repo.forked_from"}}


+ 3
- 0
web_src/js/components/EditAboutInfo.vue View File

@@ -52,6 +52,7 @@ export default {
desc: '',
index_web: '',
repo_name_name: '',
alias:''
},
// rule1:[{min:3,max:5,message:'1',trigger:"blur"}],
rule: {
@@ -76,6 +77,7 @@ export default {
getRepoName() {
const el = this.url.split('/')[2];
this.info.repo_name = el;
this.info.alias = $('input#edit-alias').val()
},
initForm(diaolog) {
if (diaolog === false) {
@@ -95,6 +97,7 @@ export default {
data: this.qs.stringify({
_csrf: csrf,
action: 'update',
alias:this.info.alias,
repo_name: this.info.repo_name,
description: this.info.desc,
website: this.info.index_web


+ 97
- 5
web_src/js/index.js View File

@@ -2411,8 +2411,8 @@ function searchRepositories() {
const items = [];
$.each(response.data, (_i, item) => {
items.push({
title: item.full_name.split('/')[1],
description: item.full_name
title: item.full_display_name.split('/')[1],
description: item.full_display_name
});
});

@@ -2677,7 +2677,7 @@ function initTemplateSearch() {
// Parse the response from the api to work with our dropdown
$.each(response.data, (_r, repo) => {
filteredResponse.results.push({
name: htmlEncode(repo.full_name),
name: htmlEncode(repo.full_display_name),
value: repo.id
});
});
@@ -2966,10 +2966,21 @@ $(document).ready(async () => {

const $cloneAddr = $('#clone_addr');
$cloneAddr.on('change', () => {
const $repoName = $('#repo_name');
const $repoName = $('#alias');
const $owner = $('#ownerDropdown div.text').attr("title")
const $urlAdd = location.href.split('/')[0] + '//' + location.href.split('/')[2]
if ($cloneAddr.val().length > 0 && $repoName.val().length === 0) {
// Only modify if repo_name input is blank
const repoValue = $cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]
$repoName.val($cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]);
$.get(`${window.config.AppSubUrl}/repo/check_name?q=${repoValue}&owner=${$owner}`,(data)=>{
const repo_name = data.name
$('#repo_name').val(repo_name)
repo_name && $('#repo_name').parent().removeClass('error')
$('#repoAdress').css("display","flex")
$('#repoAdress span').text($urlAdd+'/'+$owner+'/'+$('#repo_name').val()+'.git')
$('#repo_name').attr("placeholder","")
})
}
});

@@ -4136,4 +4147,85 @@ $('.question.circle.icon.cloudbrain-question').hover(function(){
//云脑详情页面跳转回上一个页面
$(".section.backTodeBug").attr("href",localStorage.getItem('all'))
//新建调试取消跳转
$(".ui.button.cancel").attr("href",localStorage.getItem('all'))
$(".ui.button.cancel").attr("href",localStorage.getItem('all'))

function initcreateRepo(){
let timeout;
let keydown_flag = false
const urlAdd = location.href.split('/')[0] + '//' + location.href.split('/')[2]
let owner = $('#ownerDropdown div.text').attr("title")
$(document).ready(function(){
$('#ownerDropdown').dropdown({
onChange:function(value,text,$choice){
owner = $choice[0].getAttribute("title")
$('#repoAdress').css("display","flex")
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git')
}
});
})
$('#repo_name').keyup(function(){
keydown_flag = $('#repo_name').val() ? true : false
if(keydown_flag){
$('#repoAdress').css("display","flex")
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git')
}
else{
$('#repoAdress').css("display","none")
$('#repo_name').attr("placeholder","")
}
})
$("#create_repo_form")
.form({
on: 'blur',
// inline:true,
fields: {
alias: {
identifier : 'alias',
rules: [
{
type: 'regExp[/^[\u4E00-\u9FA5A-Za-z0-9_.-]{1,100}$/]',
}
]
},
repo_name:{
identifier : 'repo_name',
rules: [
{
type: 'regExp[/^[A-Za-z0-9_.-]{1,100}$/]',
}
]
},
},
onFailure: function(e){
return false;
}
})
$('#alias').bind('input propertychange', function (event) {
clearTimeout(timeout)
timeout = setTimeout(() => {
//在此处写调用的方法,可以实现仅最后一次操作生效
const aliasValue = $('#alias').val()
if(keydown_flag){
$('#repo_name').attr("placeholder","")
}
else if(aliasValue){
$('#repo_name').attr("placeholder","正在获取路径...")
$.get(`${window.config.AppSubUrl}/repo/check_name?q=${aliasValue}&owner=${owner}`,(data)=>{
const repo_name = data.name
$('#repo_name').val(repo_name)
repo_name && $('#repo_name').parent().removeClass('error')
$('#repoAdress').css("display","flex")
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git')
$('#repo_name').attr("placeholder","")
})
}else{
$('#repo_name').val('')
$('#repo_name').attr("placeholder","")
$('#repoAdress').css("display","none")
}
}, 500)
});
}

initcreateRepo()

+ 1
- 1
web_src/less/_form.less View File

@@ -2,7 +2,7 @@
.help {
color: #999999;
padding-top: .6em;
padding-bottom: .6em;
display: inline-block;
}
}


Loading…
Cancel
Save