1// Copyright 2022 The Gitea Authors. All rights reserved.
2// SPDX-License-Identifier: MIT
3
4package pull
5
6import (
7 "context"
8
9 issues_model "forgejo.org/models/issues"
10 repo_model "forgejo.org/models/repo"
11 user_model "forgejo.org/models/user"
12 "forgejo.org/modules/gitrepo"
13 "forgejo.org/modules/json"
14)
15
16// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
17// isForcePush will be true if oldCommit isn't on the branch
18// Commit on baseBranch will skip
19func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) {
20 gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
21 if err != nil {
22 return nil, false, err
23 }
24 defer closer.Close()
25
26 oldCommit, err := gitRepo.GetCommit(oldCommitID)
27 if err != nil {
28 return nil, false, err
29 }
30
31 newCommit, err := gitRepo.GetCommit(newCommitID)
32 if err != nil {
33 return nil, false, err
34 }
35
36 isForcePush, err = newCommit.IsForcePush(oldCommitID)
37 if err != nil {
38 return nil, false, err
39 }
40
41 if isForcePush {
42 commitIDs = make([]string, 2)
43 commitIDs[0] = oldCommitID
44 commitIDs[1] = newCommitID
45
46 return commitIDs, isForcePush, err
47 }
48
49 // Find commits between new and old commit excluding base branch commits
50 commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
51 if err != nil {
52 return nil, false, err
53 }
54
55 commitIDs = make([]string, 0, len(commits))
56 for i := len(commits) - 1; i >= 0; i-- {
57 commitIDs = append(commitIDs, commits[i].ID.String())
58 }
59
60 return commitIDs, isForcePush, err
61}
62
63// CreatePushPullComment create push code to pull base comment
64func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (comment *issues_model.Comment, err error) {
65 if pr.HasMerged || oldCommitID == "" || newCommitID == "" {
66 return nil, nil
67 }
68
69 ops := &issues_model.CreateCommentOptions{
70 Type: issues_model.CommentTypePullRequestPush,
71 Doer: pusher,
72 Repo: pr.BaseRepo,
73 }
74
75 var data issues_model.PushActionContent
76
77 data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
78 if err != nil {
79 return nil, err
80 }
81
82 ops.Issue = pr.Issue
83
84 dataJSON, err := json.Marshal(data)
85 if err != nil {
86 return nil, err
87 }
88
89 ops.Content = string(dataJSON)
90
91 comment, err = issues_model.CreateComment(ctx, ops)
92
93 return comment, err
94}