|
7 | 7 | package models |
8 | 8 |
|
9 | 9 | import ( |
| 10 | + "container/list" |
| 11 | + "encoding/json" |
10 | 12 | "fmt" |
11 | 13 | "strings" |
12 | 14 |
|
@@ -90,6 +92,8 @@ const ( |
90 | 92 | CommentTypeReviewRequest |
91 | 93 | // merge pull request |
92 | 94 | CommentTypeMergePull |
| 95 | + // push to PR head branch |
| 96 | + CommentTypePullPush |
93 | 97 | ) |
94 | 98 |
|
95 | 99 | // CommentTag defines comment tag type |
@@ -167,6 +171,18 @@ type Comment struct { |
167 | 171 | RefRepo *Repository `xorm:"-"` |
168 | 172 | RefIssue *Issue `xorm:"-"` |
169 | 173 | RefComment *Comment `xorm:"-"` |
| 174 | + |
| 175 | + Commits *list.List `xorm:"-"` |
| 176 | + OldCommit string `xorm:"-"` |
| 177 | + NewCommit string `xorm:"-"` |
| 178 | + CommitsNum int64 `xorm:"-"` |
| 179 | + IsForcePush bool `xorm:"-"` |
| 180 | +} |
| 181 | + |
| 182 | +// PushActionContent is content of push pull comment |
| 183 | +type PushActionContent struct { |
| 184 | + IsForcePush bool `json:"is_force_push"` |
| 185 | + CommitIDs []string `json:"commit_ids"` |
170 | 186 | } |
171 | 187 |
|
172 | 188 | // LoadIssue loads issue from database |
@@ -543,6 +559,47 @@ func (c *Comment) CodeCommentURL() string { |
543 | 559 | return fmt.Sprintf("%s/files#%s", c.Issue.HTMLURL(), c.HashTag()) |
544 | 560 | } |
545 | 561 |
|
| 562 | +// LoadPushCommits Load push commits |
| 563 | +func (c *Comment) LoadPushCommits() (err error) { |
| 564 | + if c.Content == "" || c.Commits != nil || c.Type != CommentTypePullPush { |
| 565 | + return nil |
| 566 | + } |
| 567 | + |
| 568 | + var data PushActionContent |
| 569 | + |
| 570 | + err = json.Unmarshal([]byte(c.Content), &data) |
| 571 | + if err != nil { |
| 572 | + return |
| 573 | + } |
| 574 | + |
| 575 | + c.IsForcePush = data.IsForcePush |
| 576 | + |
| 577 | + if c.IsForcePush { |
| 578 | + if len(data.CommitIDs) != 2 { |
| 579 | + return nil |
| 580 | + } |
| 581 | + c.OldCommit = data.CommitIDs[0] |
| 582 | + c.NewCommit = data.CommitIDs[1] |
| 583 | + } else { |
| 584 | + repoPath := c.Issue.Repo.RepoPath() |
| 585 | + gitRepo, err := git.OpenRepository(repoPath) |
| 586 | + if err != nil { |
| 587 | + return err |
| 588 | + } |
| 589 | + defer gitRepo.Close() |
| 590 | + |
| 591 | + c.Commits = gitRepo.GetCommitsFromIDs(data.CommitIDs) |
| 592 | + c.CommitsNum = int64(c.Commits.Len()) |
| 593 | + if c.CommitsNum > 0 { |
| 594 | + c.Commits = ValidateCommitsWithEmails(c.Commits) |
| 595 | + c.Commits = ParseCommitsWithSignature(c.Commits, c.Issue.Repo) |
| 596 | + c.Commits = ParseCommitsWithStatus(c.Commits, c.Issue.Repo) |
| 597 | + } |
| 598 | + } |
| 599 | + |
| 600 | + return err |
| 601 | +} |
| 602 | + |
546 | 603 | func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err error) { |
547 | 604 | var LabelID int64 |
548 | 605 | if opts.Label != nil { |
@@ -576,6 +633,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err |
576 | 633 | RefCommentID: opts.RefCommentID, |
577 | 634 | RefAction: opts.RefAction, |
578 | 635 | RefIsPull: opts.RefIsPull, |
| 636 | + IsForcePush: opts.IsForcePush, |
579 | 637 | } |
580 | 638 | if _, err = e.Insert(comment); err != nil { |
581 | 639 | return nil, err |
@@ -738,6 +796,7 @@ type CreateCommentOptions struct { |
738 | 796 | RefCommentID int64 |
739 | 797 | RefAction references.XRefAction |
740 | 798 | RefIsPull bool |
| 799 | + IsForcePush bool |
741 | 800 | } |
742 | 801 |
|
743 | 802 | // CreateComment creates comment of issue or commit. |
@@ -1016,3 +1075,92 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID |
1016 | 1075 | }) |
1017 | 1076 | return err |
1018 | 1077 | } |
| 1078 | + |
| 1079 | +// CreatePushPullComment create push code to pull base commend |
| 1080 | +func CreatePushPullComment(pusher *User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) { |
| 1081 | + if pr.HasMerged || oldCommitID == "" || newCommitID == "" { |
| 1082 | + return nil, nil |
| 1083 | + } |
| 1084 | + |
| 1085 | + ops := &CreateCommentOptions{ |
| 1086 | + Type: CommentTypePullPush, |
| 1087 | + Doer: pusher, |
| 1088 | + Repo: pr.BaseRepo, |
| 1089 | + } |
| 1090 | + |
| 1091 | + var data PushActionContent |
| 1092 | + |
| 1093 | + data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) |
| 1094 | + if err != nil { |
| 1095 | + return nil, err |
| 1096 | + } |
| 1097 | + |
| 1098 | + ops.Issue = pr.Issue |
| 1099 | + dataJSON, err := json.Marshal(data) |
| 1100 | + if err != nil { |
| 1101 | + return nil, err |
| 1102 | + } |
| 1103 | + |
| 1104 | + ops.Content = string(dataJSON) |
| 1105 | + |
| 1106 | + comment, err = CreateComment(ops) |
| 1107 | + |
| 1108 | + return |
| 1109 | +} |
| 1110 | + |
| 1111 | +// getCommitsFromRepo get commit IDs from repo in betwern oldCommitID and newCommitID |
| 1112 | +// isForcePush will be true if oldCommit isn't on the branch |
| 1113 | +// Commit on baseBranch will skip |
| 1114 | +func getCommitIDsFromRepo(repo *Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { |
| 1115 | + repoPath := repo.RepoPath() |
| 1116 | + gitRepo, err := git.OpenRepository(repoPath) |
| 1117 | + if err != nil { |
| 1118 | + return nil, false, err |
| 1119 | + } |
| 1120 | + defer gitRepo.Close() |
| 1121 | + |
| 1122 | + oldCommit, err := gitRepo.GetCommit(oldCommitID) |
| 1123 | + if err != nil { |
| 1124 | + return nil, false, err |
| 1125 | + } |
| 1126 | + |
| 1127 | + oldCommitBranch, err := oldCommit.GetBranchName() |
| 1128 | + if err != nil { |
| 1129 | + return nil, false, err |
| 1130 | + } |
| 1131 | + |
| 1132 | + if oldCommitBranch == "undefined" { |
| 1133 | + commitIDs = make([]string, 2) |
| 1134 | + commitIDs[0] = oldCommitID |
| 1135 | + commitIDs[1] = newCommitID |
| 1136 | + |
| 1137 | + return commitIDs, true, err |
| 1138 | + } |
| 1139 | + |
| 1140 | + newCommit, err := gitRepo.GetCommit(newCommitID) |
| 1141 | + if err != nil { |
| 1142 | + return nil, false, err |
| 1143 | + } |
| 1144 | + |
| 1145 | + var commits *list.List |
| 1146 | + commits, err = newCommit.CommitsBeforeUntil(oldCommitID) |
| 1147 | + if err != nil { |
| 1148 | + return nil, false, err |
| 1149 | + } |
| 1150 | + |
| 1151 | + commitIDs = make([]string, 0, commits.Len()) |
| 1152 | + |
| 1153 | + for e := commits.Back(); e != nil; e = e.Prev() { |
| 1154 | + commit := e.Value.(*git.Commit) |
| 1155 | + commitBranch, err := commit.GetBranchName() |
| 1156 | + if err != nil { |
| 1157 | + return nil, false, err |
| 1158 | + } |
| 1159 | + |
| 1160 | + if commitBranch != baseBranch { |
| 1161 | + commitIDs = append(commitIDs, commit.ID.String()) |
| 1162 | + } |
| 1163 | + } |
| 1164 | + |
| 1165 | + return |
| 1166 | +} |
0 commit comments