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 <info@mrsdizzie.com>

* Apply suggestions from code review

* fix ui view

Co-authored-by: silverwind <me@silverwind.io>

* 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 <info@mrsdizzie.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
赵智超 2020-05-20 20:47:24 +08:00 committed by GitHub
parent 9e0e2a9fcf
commit 0903b1ac8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 478 additions and 6 deletions

View file

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

View file

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