diff --git a/go.mod b/go.mod index 337aabc8e..d9c12ea3a 100755 --- a/go.mod +++ b/go.mod @@ -56,6 +56,7 @@ require ( github.com/gomodule/redigo v2.0.0+incompatible github.com/google/go-github/v24 v24.0.1 github.com/gorilla/context v1.1.1 + github.com/gorilla/websocket v1.4.0 github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/huandu/xstrings v1.3.0 github.com/issue9/assert v1.3.2 // indirect diff --git a/go.sum b/go.sum index 7346b9050..9bae7932d 100755 --- a/go.sum +++ b/go.sum @@ -394,6 +394,7 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index ace51002d..581b19a9c 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -31,7 +31,7 @@ type AiModelManage struct { CodeCommitID string `xorm:"NULL"` UserId int64 `xorm:"NOT NULL"` UserName string - UserRelAvatarLink string `xorm:"NULL"` + UserRelAvatarLink string TrainTaskInfo string `xorm:"text NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created"` UpdatedUnix timeutil.TimeStamp `xorm:"updated"` @@ -135,7 +135,7 @@ func QueryModelByName(name string, repoId int64) []*AiModelManage { sess := x.NewSession() defer sess.Close() sess.Select("*").Table("ai_model_manage"). - Where("name='" + name + "' and repo_id=" + fmt.Sprint(repoId)).OrderBy("version desc") + Where("name='" + name + "' and repo_id=" + fmt.Sprint(repoId)).OrderBy("created_unix desc") aiModelManageList := make([]*AiModelManage, 0) sess.Find(&aiModelManageList) return aiModelManageList diff --git a/models/cloudbrain.go b/models/cloudbrain.go index ceb552811..509f4a9ed 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -962,13 +962,23 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { cond = cond.And( builder.Eq{"Status": "COMPLETED"}, ) - sess.OrderBy("job_id DESC") + cloudbrains := make([]*CloudbrainInfo, 0) - if err := sess.Distinct("job_id,job_name").Table(&Cloudbrain{}).Where(cond). + if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). Find(&cloudbrains); err != nil { return nil, 0, fmt.Errorf("Find: %v", err) } - return cloudbrains, int(len(cloudbrains)), nil + + keys := make(map[string]string) + uniqueElements := make([]*CloudbrainInfo, 0) + for _, entry := range cloudbrains { + if _, value := keys[entry.JobID]; !value { + keys[entry.JobID] = entry.JobName + uniqueElements = append(uniqueElements, entry) + } + } + + return uniqueElements, int(len(uniqueElements)), nil } func CloudbrainsVersionList(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int, error) { @@ -1108,10 +1118,7 @@ func UpdateJob(job *Cloudbrain) error { } func updateJob(e Engine, job *Cloudbrain) error { - var sess *xorm.Session - sess = e.Where("job_id = ?", job.JobID) - //_, err := sess.Cols("status", "container_id", "container_ip").Update(job) - _, err := sess.Update(job) + _, err := e.ID(job.ID).AllCols().Update(job) return err } diff --git a/models/issue.go b/models/issue.go index 7457fcd45..19f00d5f3 100755 --- a/models/issue.go +++ b/models/issue.go @@ -1397,6 +1397,8 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, if opts.MilestoneID > 0 { sess.And("issue.milestone_id = ?", opts.MilestoneID) + } else if opts.MilestoneID == -1 { //only search for issues do not have milestone + sess.And("issue.milestone_id = ?", 0) } if opts.AssigneeID > 0 { diff --git a/models/issue_milestone.go b/models/issue_milestone.go index 464827445..a08bbf4dc 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -353,7 +353,7 @@ func GetMilestonesByRepoID(repoID int64, state api.StateType, listOptions ListOp } miles := make([]*Milestone, 0, listOptions.PageSize) - return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) + return miles, sess.Desc("id").Find(&miles) } // GetMilestones returns a list of milestones of given repository and status. diff --git a/models/repo.go b/models/repo.go index fda5460f5..8070d7442 100755 --- a/models/repo.go +++ b/models/repo.go @@ -649,49 +649,41 @@ func (repo *Repository) GetAssignees() (_ []*User, err error) { return repo.getAssignees(x) } -func (repo *Repository) getReviewersPrivate(e Engine, doerID, posterID int64) (users []*User, err error) { - users = make([]*User, 0, 20) - - if err = e. - SQL("SELECT * FROM `user` WHERE id in (SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ? AND user_id NOT IN ( ?, ?)) ORDER BY name", - repo.ID, AccessModeRead, - doerID, posterID). - Find(&users); err != nil { - return nil, err - } - - return users, nil -} - -func (repo *Repository) getReviewersPublic(e Engine, doerID, posterID int64) (_ []*User, err error) { - - users := make([]*User, 0) - - const SQLCmd = "SELECT * FROM `user` WHERE id IN ( " + - "SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ? AND user_id NOT IN ( ?, ?) ) ORDER BY name " - - if err = e. - SQL(SQLCmd, - repo.ID, AccessModeWrite, doerID, posterID). - Find(&users); err != nil { - return nil, err - } - - return users, nil -} - func (repo *Repository) getReviewers(e Engine, doerID, posterID int64) (users []*User, err error) { if err = repo.getOwner(e); err != nil { return nil, err } - if repo.IsPrivate || - (repo.Owner.IsOrganization() && repo.Owner.Visibility == api.VisibleTypePrivate) { - users, err = repo.getReviewersPrivate(x, doerID, posterID) + if repo.Owner.IsOrganization() { + const SQLCmd = "SELECT * FROM `user` WHERE id IN (" + + "SELECT DISTINCT(t3.user_id) FROM ( " + + "SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ?" + + "UNION select t2.uid as user_id from team t1 left join team_user t2 on t1.id = t2.team_id where t1.org_id = ? and t1.authorize = 4) t3)" + + " AND id NOT IN ( ?, ?) ORDER BY name " + + if err = e. + SQL(SQLCmd, + repo.ID, AccessModeWrite, repo.ID, doerID, posterID). + Find(&users); err != nil { + return nil, err + } } else { - users, err = repo.getReviewersPublic(x, doerID, posterID) + const SQLCmd = "SELECT * FROM `user` WHERE id IN ( " + + "SELECT DISTINCT(t3.user_id) FROM ( " + + "SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ? " + + " UNION" + + " SELECT owner_id as user_id FROM `repository` WHERE id = ?) t3)" + + " AND id NOT IN ( ?, ?) ORDER BY name " + + if err = e. + SQL(SQLCmd, + repo.ID, AccessModeWrite, repo.ID, doerID, posterID). + Find(&users); err != nil { + return nil, err + } } - return + + return users, nil } // GetReviewers get all users can be requested to review @@ -2478,6 +2470,12 @@ func GetBlockChainUnSuccessRepos() ([]*Repository, error) { Find(&repos) } +func (repo *Repository) UpdateBlockChain() error { + + _, err := x.Exec("UPDATE `repository` SET block_chain_status = ?, contract_address=? WHERE id = ?", repo.BlockChainStatus, repo.ContractAddress, repo.ID) + return err +} + func (repo *Repository) IncreaseCloneCnt() { sess := x.NewSession() defer sess.Close() diff --git a/models/repo_watch.go b/models/repo_watch.go index 6bdef9c7f..1d6b7a31c 100644 --- a/models/repo_watch.go +++ b/models/repo_watch.go @@ -24,6 +24,8 @@ const ( RepoWatchModeAuto // 3 ) +var ActionChan = make(chan *Action, 200) + // Watch is connection request for receiving repository notification. type Watch struct { ID int64 `xorm:"pk autoincr"` @@ -277,9 +279,17 @@ func notifyWatchers(e Engine, actions ...*Action) error { // NotifyWatchers creates batch of actions for every watcher. func NotifyWatchers(actions ...*Action) error { + + producer(actions...) return notifyWatchers(x, actions...) } +func producer(actions ...*Action) { + for _, action := range actions { + ActionChan <- action + } +} + // NotifyWatchersActions creates batch of actions for every watcher. func NotifyWatchersActions(acts []*Action) error { sess := x.NewSession() diff --git a/modules/git/commit.go b/modules/git/commit.go index 5e492e27e..8e6857f4a 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -271,6 +271,15 @@ func AllCommitsCount(repoPath string) (int64, error) { return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64) } +func HEADCommitsCount(repoPath string) (int64, error) { + stdout, err := NewCommand("rev-list", "HEAD", "--count").RunInDir(repoPath) + if err != nil { + return 0, err + } + + return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64) +} + func commitsCount(repoPath, revision, relpath string) (int64, error) { cmd := NewCommand("rev-list", "--count") cmd.AddArguments(revision) diff --git a/modules/git/repo.go b/modules/git/repo.go index a2a4d28af..f72f5df7e 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -52,6 +52,10 @@ func (repo *Repository) GetAllCommitsCount() (int64, error) { return AllCommitsCount(repo.Path) } +func (repo *Repository) GetHeadCommitsCount() (int64, error) { + return HEADCommitsCount(repo.Path) +} + func (repo *Repository) parsePrettyFormatLogToList(logs []byte) (*list.List, error) { l := list.New() if len(logs) == 0 { @@ -441,8 +445,12 @@ type Contributor struct { Email string } -func GetContributors(repoPath string) ([]Contributor, error){ - cmd := NewCommand("shortlog", "-sne", "--all") +func GetContributors(repoPath string, branchOrTag ...string) ([]Contributor, error) { + targetBranchOrTag := "HEAD" + if len(branchOrTag) > 0 && branchOrTag[0] != "" { + targetBranchOrTag = branchOrTag[0] + } + cmd := NewCommand("shortlog", "-sne", targetBranchOrTag) stdout, err := cmd.RunInDir(repoPath) if err != nil { return nil, err @@ -458,9 +466,9 @@ func GetContributors(repoPath string) ([]Contributor, error){ } number := oneCount[0:strings.Index(oneCount, "\t")] commitCnt, _ := strconv.Atoi(number) - committer := oneCount[strings.Index(oneCount, "\t")+1:strings.LastIndex(oneCount, " ")] + committer := oneCount[strings.Index(oneCount, "\t")+1 : strings.LastIndex(oneCount, " ")] committer = strings.Trim(committer, " ") - email := oneCount[strings.Index(oneCount, "<")+1:strings.Index(oneCount, ">")] + email := oneCount[strings.Index(oneCount, "<")+1 : strings.Index(oneCount, ">")] contributorsInfo[i] = Contributor{ commitCnt, committer, email, } diff --git a/modules/git/repo_stats_custom.go b/modules/git/repo_stats_custom.go index 95bad6678..d70a17052 100644 --- a/modules/git/repo_stats_custom.go +++ b/modules/git/repo_stats_custom.go @@ -126,7 +126,7 @@ func GetUserKPIStats(repoPath string) (map[string]*UserKPIStats, error) { func SetRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, newContributers map[string]struct{}) error { since := fromTime.Format(time.RFC3339) - args := []string{"log", "--numstat", "--no-merges", "--branches=*", "--pretty=format:---%n%h%n%an%n%ae%n", "--date=iso", fmt.Sprintf("--since='%s'", since)} + args := []string{"log", "--numstat", "--no-merges", "HEAD", "--pretty=format:---%n%h%n%an%n%ae%n", "--date=iso", fmt.Sprintf("--since='%s'", since)} stdout, err := NewCommand(args...).RunInDirBytes(repoPath) if err != nil { @@ -212,7 +212,7 @@ func SetRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, n func GetContributorsDetail(repoPath string, fromTime time.Time) ([]Contributor, error) { since := fromTime.Format(time.RFC3339) - cmd := NewCommand("shortlog", "-sne", "--all", fmt.Sprintf("--since='%s'", since)) + cmd := NewCommand("shortlog", "-sne", "HEAD", fmt.Sprintf("--since='%s'", since)) stdout, err := cmd.RunInDir(repoPath) if err != nil { return nil, err diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 48a010b73..b58021ea2 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -779,6 +779,8 @@ datasets.desc = Enable Dataset cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. model_manager = Model +model_noright=No right +model_rename=Duplicate model name, please modify model name. debug=Debug stop=Stop @@ -897,7 +899,7 @@ model.manage.Accuracy = Accuracy model.manage.F1 = F1 model.manage.Precision = Precision model.manage.Recall = Recall - +model.manage.sava_model = Sava Model template.items = Template Items template.git_content = Git Content (Default Branch) @@ -1129,6 +1131,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_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 1eee752a1..f5a52f2cb 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -784,6 +784,7 @@ cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 model_manager = 模型 model_noright=无权限操作 +model_rename=模型名称重复,请修改模型名称 debug=调试 stop=停止 @@ -907,6 +908,7 @@ model.manage.Accuracy = 准确率 model.manage.F1 = F1值 model.manage.Precision = 精确率 model.manage.Recall = 召回率 +model.manage.sava_model = 保存模型 template.items=模板选项 template.git_content=Git数据(默认分支) @@ -1139,6 +1141,7 @@ issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回 issues.filter_label_no_select=所有标签 issues.filter_milestone=里程碑筛选 issues.filter_milestone_no_select=所有里程碑 +issues.filter_milestone_no_add=未添加里程碑 issues.filter_assignee=指派人筛选 issues.filter_assginee_no_select=所有指派成员 issues.filter_type=类型筛选 diff --git a/routers/actionnotification.go b/routers/actionnotification.go new file mode 100644 index 000000000..b3e151c1c --- /dev/null +++ b/routers/actionnotification.go @@ -0,0 +1,53 @@ +package routers + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/socketwrap" + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, +} + +var SocketManager = socketwrap.NewClientsManager() + +func ActionNotification(ctx *context.Context) { + + conn, err := upgrader.Upgrade(ctx.Resp, ctx.Req.Request, nil) + if err != nil { + log.Warn("can not create connection.", err) + return + } + client := &socketwrap.Client{Manager: SocketManager, Conn: conn, Send: make(chan *models.Action, 256)} + + WriteLastTenActionsIfHave(conn) + + client.Manager.Register <- client + + go client.WritePump() + +} + +func WriteLastTenActionsIfHave(conn *websocket.Conn) { + socketwrap.LastTenActionsQueue.Mutex.RLock() + { + size := socketwrap.LastTenActionsQueue.Queue.Len() + if size > 0 { + tempE := socketwrap.LastTenActionsQueue.Queue.Front() + conn.WriteJSON(tempE) + for i := 1; i < size; i++ { + tempE = tempE.Next() + conn.WriteJSON(tempE) + + } + } + + } + socketwrap.LastTenActionsQueue.Mutex.RUnlock() +} + + diff --git a/routers/private/hook.go b/routers/private/hook.go index a673362fa..79c8ecfc5 100755 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -539,7 +539,7 @@ func updateRepoCommitCnt(ctx *macaron.Context, repo *models.Repository) error { } defer gitRepo.Close() - count, err := gitRepo.GetAllCommitsCount() + count, err := gitRepo.GetHeadCommitsCount() if err != nil { log.Error("GetAllCommitsCount failed:%v", err.Error(), ctx.Data["MsgID"]) return err diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 32cb5b2cf..669bdf9fa 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -71,25 +71,24 @@ func saveModelByParameters(jobId string, versionName string, name string, versio aiTaskJson, _ := json.Marshal(aiTask) model := &models.AiModelManage{ - ID: id, - Version: version, - VersionCount: len(aimodels) + 1, - Label: label, - Name: name, - Description: description, - New: MODEL_LATEST, - Type: cloudType, - Path: modelPath, - Size: modelSize, - AttachmentId: aiTask.Uuid, - RepoId: aiTask.RepoID, - UserId: ctx.User.ID, - UserRelAvatarLink: ctx.User.RelAvatarLink(), - CodeBranch: aiTask.BranchName, - CodeCommitID: aiTask.CommitID, - Engine: aiTask.EngineID, - TrainTaskInfo: string(aiTaskJson), - Accuracy: string(accuracyJson), + ID: id, + Version: version, + VersionCount: len(aimodels) + 1, + Label: label, + Name: name, + Description: description, + New: MODEL_LATEST, + Type: cloudType, + Path: modelPath, + Size: modelSize, + AttachmentId: aiTask.Uuid, + RepoId: aiTask.RepoID, + UserId: ctx.User.ID, + CodeBranch: aiTask.BranchName, + CodeCommitID: aiTask.CommitID, + Engine: aiTask.EngineID, + TrainTaskInfo: string(aiTaskJson), + Accuracy: string(accuracyJson), } err = models.SaveModelToDb(model) @@ -106,6 +105,23 @@ func saveModelByParameters(jobId string, versionName string, name string, versio return nil } +func SaveNewNameModel(ctx *context.Context) { + name := ctx.Query("Name") + if name == "" { + ctx.Error(500, fmt.Sprintf("name or version is null.")) + return + } + + aimodels := models.QueryModelByName(name, ctx.Repo.Repository.ID) + if len(aimodels) > 0 { + ctx.Error(500, ctx.Tr("repo.model_rename")) + return + } + SaveModel(ctx) + + log.Info("save model end.") +} + func SaveModel(ctx *context.Context) { log.Info("save model start.") JobId := ctx.Query("JobId") @@ -392,10 +408,24 @@ func ShowSingleModel(ctx *context.Context) { log.Info("Show single ModelInfo start.name=" + name) models := models.QueryModelByName(name, ctx.Repo.Repository.ID) + userIds := make([]int64, len(models)) + for i, model := range models { + model.IsCanOper = isOper(ctx, model.UserId) + userIds[i] = model.UserId + } + userNameMap := queryUserName(userIds) + + for _, model := range models { + value := userNameMap[model.UserId] + if value != nil { + model.UserName = value.Name + model.UserRelAvatarLink = value.RelAvatarLink() + } + } ctx.JSON(http.StatusOK, models) } -func queryUserName(intSlice []int64) map[int64]string { +func queryUserName(intSlice []int64) map[int64]*models.User { keys := make(map[int64]string) uniqueElements := []int64{} for _, entry := range intSlice { @@ -404,13 +434,15 @@ func queryUserName(intSlice []int64) map[int64]string { uniqueElements = append(uniqueElements, entry) } } - userNames, err := models.GetUserNamesByIDs(uniqueElements) + result := make(map[int64]*models.User) + userLists, err := models.GetUsersByIDs(uniqueElements) if err == nil { - for i, userName := range userNames { - keys[uniqueElements[i]] = userName + for _, user := range userLists { + result[user.ID] = user } } - return keys + + return result } func ShowOneVersionOtherModel(ctx *context.Context) { @@ -420,15 +452,17 @@ func ShowOneVersionOtherModel(ctx *context.Context) { userIds := make([]int64, len(aimodels)) for i, model := range aimodels { - log.Info("model=" + model.Name) - log.Info("model.UserId=" + fmt.Sprint(model.UserId)) model.IsCanOper = isOper(ctx, model.UserId) userIds[i] = model.UserId } userNameMap := queryUserName(userIds) for _, model := range aimodels { - model.UserName = userNameMap[model.UserId] + value := userNameMap[model.UserId] + if value != nil { + model.UserName = value.Name + model.UserRelAvatarLink = value.RelAvatarLink() + } } if len(aimodels) > 0 { @@ -496,15 +530,18 @@ func ShowModelPageInfo(ctx *context.Context) { userIds := make([]int64, len(modelResult)) for i, model := range modelResult { - log.Info("model=" + model.Name) - log.Info("model.UserId=" + fmt.Sprint(model.UserId)) model.IsCanOper = isOper(ctx, model.UserId) userIds[i] = model.UserId } userNameMap := queryUserName(userIds) + for _, model := range modelResult { - model.UserName = userNameMap[model.UserId] + value := userNameMap[model.UserId] + if value != nil { + model.UserName = value.Name + model.UserRelAvatarLink = value.RelAvatarLink() + } } mapInterface := make(map[string]interface{}) diff --git a/routers/repo/blockchain.go b/routers/repo/blockchain.go index dc3fcd848..6bd546ce6 100755 --- a/routers/repo/blockchain.go +++ b/routers/repo/blockchain.go @@ -72,7 +72,7 @@ func HandleBlockChainInitNotify(ctx *context.Context) { repo.BlockChainStatus = models.RepoBlockChainSuccess repo.ContractAddress = req.ContractAddress - if err = models.UpdateRepositoryCols(repo, "block_chain_status", "contract_address"); err != nil { + if err = repo.UpdateBlockChain(); err != nil { log.Error("UpdateRepositoryCols failed:%v", err.Error(), ctx.Data["msgID"]) ctx.JSON(200, map[string]string{ "code": "-1", diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 77ed0251d..7ab5eb283 100755 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -193,6 +193,8 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB var mileIDs []int64 if milestoneID > 0 { mileIDs = []int64{milestoneID} + } else if milestoneID == -1 { //only search no milestone + mileIDs = []int64{0} } var issues []*models.Issue @@ -355,7 +357,8 @@ func Issues(ctx *context.Context) { var err error // Get milestones. - ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state")), models.ListOptions{}) + ctx.Data["OpenMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateOpen, models.ListOptions{}) + ctx.Data["ClosedMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateClosed, models.ListOptions{}) if err != nil { ctx.ServerError("GetAllRepoMilestones", err) return diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index c19eacb7a..6dbe6740b 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -1259,7 +1259,7 @@ func TrainJobShow(ctx *context.Context) { ctx.Data["canNewJob"] = canNewJob //将运行参数转化为epoch_size = 3, device_target = Ascend的格式 - for i, _ := range VersionListTasks { + for i, task := range VersionListTasks { var parameters models.Parameters @@ -1280,6 +1280,9 @@ func TrainJobShow(ctx *context.Context) { } else { VersionListTasks[i].Parameters = "" } + + VersionListTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) + VersionListTasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) } pager := context.NewPagination(VersionListCount, setting.UI.IssuePagingNum, page, 5) diff --git a/routers/repo/view.go b/routers/repo/view.go index a5f2e1477..b08243240 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -605,7 +605,7 @@ func getContributorInfo(contributorInfos []*ContributorInfo, email string) *Cont func Home(ctx *context.Context) { if len(ctx.Repo.Units) > 0 { //get repo contributors info - contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), ctx.Repo.BranchName) if err == nil && contributors != nil { startTime := time.Now() var contributorInfos []*ContributorInfo @@ -924,7 +924,9 @@ func ContributorsAPI(ctx *context.Context) { count := 0 errorCode := 0 errorMsg := "" - contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + + branchOrTag := ctx.Query("name") + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), branchOrTag) var contributorInfos []*ContributorInfo if err == nil && contributors != nil { contributorInfoHash := make(map[string]*ContributorInfo) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 05ae5fbef..d838ebaad 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -315,6 +315,8 @@ func RegisterRoutes(m *macaron.Macaron) { }) m.Get("/", routers.Home) m.Get("/dashboard", routers.Dashboard) + go routers.SocketManager.Run() + m.Get("/action/notification", routers.ActionNotification) m.Get("/recommend/org", routers.RecommendOrgFromPromote) m.Get("/recommend/repo", routers.RecommendRepoFromPromote) m.Group("/explore", func() { @@ -975,6 +977,7 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef()) m.Group("/modelmanage", func() { m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) + m.Post("/create_new_model", reqRepoModelManageWriter, repo.SaveNewNameModel) m.Delete("/delete_model", repo.DeleteModel) m.Put("/modify_model", repo.ModifyModelInfo) m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) diff --git a/services/socketwrap/client.go b/services/socketwrap/client.go new file mode 100644 index 000000000..ce8dbb5e8 --- /dev/null +++ b/services/socketwrap/client.go @@ -0,0 +1,50 @@ +package socketwrap + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "github.com/gorilla/websocket" +) + +type Client struct { + Manager *ClientsManager + + Conn *websocket.Conn + + Send chan *models.Action +} + +func (c *Client) WritePump() { + + defer func() { + c.Manager.Unregister <- c + c.Conn.Close() + }() + for { + select { + case message, ok := <-c.Send: + + if !ok { + c.Conn.WriteMessage(websocket.CloseMessage, []byte{}) + log.Warn("send socket is closed") + return + } + log.Warn("socket:", message) + err := c.Conn.WriteJSON(message) + if err != nil { + log.Warn("can not send message", err) + return + } + + n := len(c.Send) + for i := 0; i < n; i++ { + err = c.Conn.WriteJSON(<-c.Send) + if err != nil { + log.Warn("can not send message", err) + return + } + } + + } + } +} diff --git a/services/socketwrap/clientManager.go b/services/socketwrap/clientManager.go new file mode 100644 index 000000000..ac6ca0bed --- /dev/null +++ b/services/socketwrap/clientManager.go @@ -0,0 +1,46 @@ +package socketwrap + +import ( + "code.gitea.io/gitea/models" +) + +type ClientsManager struct { + Clients map[*Client]bool + Register chan *Client + Unregister chan *Client +} + +func NewClientsManager() *ClientsManager { + return &ClientsManager{ + Register: make(chan *Client), + Unregister: make(chan *Client), + Clients: make(map[*Client]bool), + } +} + +var LastTenActionsQueue = NewSyncQueue(10) + +func (h *ClientsManager) Run() { + for { + select { + case client := <-h.Register: + h.Clients[client] = true + case client := <-h.Unregister: + if _, ok := h.Clients[client]; ok { + delete(h.Clients, client) + close(client.Send) + } + case message := <-models.ActionChan: + LastTenActionsQueue.Push(message) + for client := range h.Clients { + select { + case client.Send <- message: + default: + close(client.Send) + delete(h.Clients, client) + } + } + + } + } +} diff --git a/services/socketwrap/syncqueue.go b/services/socketwrap/syncqueue.go new file mode 100644 index 000000000..c366ac23b --- /dev/null +++ b/services/socketwrap/syncqueue.go @@ -0,0 +1,34 @@ +package socketwrap + +import ( + "container/list" + "sync" +) + +type SyncQueue struct { + Queue *list.List + Mutex *sync.RWMutex + MaxSize int +} + +func (q *SyncQueue) Push(value interface{}) { + q.Mutex.Lock() + { + if q.Queue.Len() < q.MaxSize { + q.Queue.PushBack(value) + } else { + q.Queue.PushBack(value) + q.Queue.Remove(q.Queue.Front()) + } + } + + q.Mutex.Unlock() +} + +func NewSyncQueue(maxSize int) *SyncQueue { + return &SyncQueue{ + list.New(), + &sync.RWMutex{}, + maxSize, + } +} diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl index 27c82a6bf..53d0f8839 100755 --- a/templates/base/head_navbar.tmpl +++ b/templates/base/head_navbar.tmpl @@ -19,8 +19,8 @@ {{if .IsSigned}}