From 0903b1ac8c7b64bb571d02cdd69fa671cc1c18c1 Mon Sep 17 00:00:00 2001 From: 赵智超 <1012112796@qq.com> Date: Wed, 20 May 2020 20:47:24 +0800 Subject: Add push commits history comment on PR time-line (#11167) * Add push commits history comment on PR time-line * Add notify by email and ui of this comment type also Signed-off-by: a1012112796 <1012112796@qq.com> * Add migrations for IsForcePush * fix wrong force-push judgement * Apply suggestions from code review * Remove commit number check * add own notify fun * fix some typo Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> * fix lint * fix style again, I forgot something before * Change email notify way * fix api * add number check if It's force-push * Add repo commit link fuction remove unnecessary check skip show push commits comment which not have commits alive * Update issue_comment.go * Apply suggestions from code review Co-authored-by: mrsdizzie * Apply suggestions from code review * fix ui view Co-authored-by: silverwind * fix height * remove unnecessary style define * simplify GetBranchName * Apply suggestions from code review * save commit ids and isForce push by json * simplify GetBranchName * fix bug Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: mrsdizzie Co-authored-by: Lauris BH Co-authored-by: silverwind --- models/issue_comment.go | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ models/repo.go | 11 ++++ 2 files changed, 159 insertions(+) (limited to 'models') diff --git a/models/issue_comment.go b/models/issue_comment.go index f7017435d7..e23fae6715 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -7,6 +7,8 @@ package models import ( + "container/list" + "encoding/json" "fmt" "strings" @@ -90,6 +92,8 @@ const ( CommentTypeReviewRequest // merge pull request CommentTypeMergePull + // push to PR head branch + CommentTypePullPush ) // CommentTag defines comment tag type @@ -167,6 +171,18 @@ type Comment struct { RefRepo *Repository `xorm:"-"` RefIssue *Issue `xorm:"-"` RefComment *Comment `xorm:"-"` + + Commits *list.List `xorm:"-"` + OldCommit string `xorm:"-"` + NewCommit string `xorm:"-"` + CommitsNum int64 `xorm:"-"` + IsForcePush bool `xorm:"-"` +} + +// PushActionContent is content of push pull comment +type PushActionContent struct { + IsForcePush bool `json:"is_force_push"` + CommitIDs []string `json:"commit_ids"` } // LoadIssue loads issue from database @@ -543,6 +559,47 @@ func (c *Comment) CodeCommentURL() string { return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) } +// LoadPushCommits Load push commits +func (c *Comment) LoadPushCommits() (err error) { + if c.Content == "" || c.Commits != nil || c.Type != CommentTypePullPush { + return nil + } + + var data PushActionContent + + err = json.Unmarshal([]byte(c.Content), &data) + if err != nil { + return + } + + c.IsForcePush = data.IsForcePush + + if c.IsForcePush { + if len(data.CommitIDs) != 2 { + return nil + } + c.OldCommit = data.CommitIDs[0] + c.NewCommit = data.CommitIDs[1] + } else { + repoPath := c.Issue.Repo.RepoPath() + gitRepo, err := git.OpenRepository(repoPath) + if err != nil { + return err + } + defer gitRepo.Close() + + c.Commits = gitRepo.GetCommitsFromIDs(data.CommitIDs) + c.CommitsNum = int64(c.Commits.Len()) + if c.CommitsNum > 0 { + c.Commits = ValidateCommitsWithEmails(c.Commits) + c.Commits = ParseCommitsWithSignature(c.Commits, c.Issue.Repo) + c.Commits = ParseCommitsWithStatus(c.Commits, c.Issue.Repo) + } + } + + return err +} + func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err error) { var LabelID int64 if opts.Label != nil { @@ -576,6 +633,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err RefCommentID: opts.RefCommentID, RefAction: opts.RefAction, RefIsPull: opts.RefIsPull, + IsForcePush: opts.IsForcePush, } if _, err = e.Insert(comment); err != nil { return nil, err @@ -738,6 +796,7 @@ type CreateCommentOptions struct { RefCommentID int64 RefAction references.XRefAction RefIsPull bool + IsForcePush bool } // CreateComment creates comment of issue or commit. @@ -1016,3 +1075,92 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID }) return err } + +// CreatePushPullComment create push code to pull base commend +func CreatePushPullComment(pusher *User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) { + if pr.HasMerged || oldCommitID == "" || newCommitID == "" { + return nil, nil + } + + ops := &CreateCommentOptions{ + Type: CommentTypePullPush, + Doer: pusher, + Repo: pr.BaseRepo, + } + + var data PushActionContent + + data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) + if err != nil { + return nil, err + } + + ops.Issue = pr.Issue + dataJSON, err := json.Marshal(data) + if err != nil { + return nil, err + } + + ops.Content = string(dataJSON) + + comment, err = CreateComment(ops) + + return +} + +// getCommitsFromRepo get commit IDs from repo in betwern oldCommitID and newCommitID +// isForcePush will be true if oldCommit isn't on the branch +// Commit on baseBranch will skip +func getCommitIDsFromRepo(repo *Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { + repoPath := repo.RepoPath() + gitRepo, err := git.OpenRepository(repoPath) + if err != nil { + return nil, false, err + } + defer gitRepo.Close() + + oldCommit, err := gitRepo.GetCommit(oldCommitID) + if err != nil { + return nil, false, err + } + + oldCommitBranch, err := oldCommit.GetBranchName() + if err != nil { + return nil, false, err + } + + if oldCommitBranch == "undefined" { + commitIDs = make([]string, 2) + commitIDs[0] = oldCommitID + commitIDs[1] = newCommitID + + return commitIDs, true, err + } + + newCommit, err := gitRepo.GetCommit(newCommitID) + if err != nil { + return nil, false, err + } + + var commits *list.List + commits, err = newCommit.CommitsBeforeUntil(oldCommitID) + if err != nil { + return nil, false, err + } + + commitIDs = make([]string, 0, commits.Len()) + + for e := commits.Back(); e != nil; e = e.Prev() { + commit := e.Value.(*git.Commit) + commitBranch, err := commit.GetBranchName() + if err != nil { + return nil, false, err + } + + if commitBranch != baseBranch { + commitIDs = append(commitIDs, commit.ID.String()) + } + } + + return +} diff --git a/models/repo.go b/models/repo.go index f79740e747..c45abdf63d 100644 --- a/models/repo.go +++ b/models/repo.go @@ -264,6 +264,17 @@ func (repo *Repository) HTMLURL() string { return setting.AppURL + repo.FullName() } +// CommitLink make link to by commit full ID +// note: won't check whether it's an right id +func (repo *Repository) CommitLink(commitID string) (result string) { + if commitID == "" || commitID == "0000000000000000000000000000000000000000" { + result = "" + } else { + result = repo.HTMLURL() + "/commit/" + commitID + } + return +} + // APIURL returns the repository API URL func (repo *Repository) APIURL() string { return setting.AppURL + path.Join("api/v1/repos", repo.FullName()) -- cgit v1.2.3