forked from Gitlink/gitea_hat
新增:合并请求commit列表和变更文件列表
This commit is contained in:
parent
3019b5ca6e
commit
5be1baac4b
|
@ -0,0 +1,8 @@
|
|||
package git
|
||||
|
||||
import gitea_git "code.gitea.io/gitea/modules/git"
|
||||
|
||||
func GetDiffFileOnlyName(repo *gitea_git.Repository, base, head string) (string, error) {
|
||||
stdout, _, err := gitea_git.NewCommand(repo.Ctx, "diff", "--name-only", base, head).RunStdString(&gitea_git.RunOpts{Dir: repo.Path})
|
||||
return stdout, err
|
||||
}
|
|
@ -84,6 +84,8 @@ func Routers() *web.Route {
|
|||
m.Group("/pulls", func() {
|
||||
m.Group("/{index}", func() {
|
||||
m.Combo("").Get(repo.GetPullRequest)
|
||||
m.Get("/commits", context.RepoRef(), repo.GetPullCommits)
|
||||
m.Get("/files", context.RepoRef(), repo.GetPullFiles)
|
||||
})
|
||||
}, mustAllowPulls, reqRepoReader(unit_model.TypeCode), context.ReferencesGitRepo())
|
||||
m.Group("/releases", func() {
|
||||
|
|
|
@ -2,10 +2,21 @@ package repo
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/convert"
|
||||
hat_git "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git"
|
||||
)
|
||||
|
||||
func GetPullRequest(ctx *context.APIContext) {
|
||||
|
@ -34,3 +45,222 @@ func GetPullRequest(ctx *context.APIContext) {
|
|||
}
|
||||
ctx.JSON(http.StatusOK, apiResult)
|
||||
}
|
||||
|
||||
type PullRequestCommit struct {
|
||||
git_model.SignCommitWithStatuses
|
||||
Sha string
|
||||
}
|
||||
|
||||
func GetPullCommits(ctx *context.APIContext) {
|
||||
pull, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
issue := pull.Issue
|
||||
if issue == nil {
|
||||
ctx.NotFound("issue is not present.")
|
||||
return
|
||||
}
|
||||
gitRepo := ctx.Repo.GitRepo
|
||||
|
||||
var commits []*git.Commit
|
||||
var prInfo *git.CompareInfo
|
||||
|
||||
if pull.HasMerged {
|
||||
var baseCommit string
|
||||
if pull.MergeBase == "" {
|
||||
var commitSHA, parentCommit string
|
||||
commitSHA, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
|
||||
if err != nil {
|
||||
commitSHA, err := gitRepo.ReadPatchCommit(pull.Index)
|
||||
if err == nil {
|
||||
if err := gitRepo.SetReference(pull.GetGitRefName(), commitSHA); err != nil {
|
||||
log.Error("Could not write head file", err)
|
||||
}
|
||||
} else {
|
||||
log.Trace("No history file available for PR %d", pull.Index)
|
||||
}
|
||||
}
|
||||
if commitSHA != "" {
|
||||
parentCommit, _, err = git.NewCommand(ctx, "rev-list", "-1", "--skip=1", commitSHA).RunStdString(&git.RunOpts{Dir: gitRepo.Path})
|
||||
if err == nil {
|
||||
parentCommit = strings.TrimSpace(parentCommit)
|
||||
}
|
||||
if err != nil || parentCommit == "" {
|
||||
log.Info("No known parent commit for PR %d, error: %v", pull.Index, err)
|
||||
parentCommit = commitSHA
|
||||
}
|
||||
}
|
||||
baseCommit = parentCommit
|
||||
} else {
|
||||
baseCommit = pull.MergeBase
|
||||
}
|
||||
prInfo, err = gitRepo.GetCompareInfo(gitRepo.Path, baseCommit, pull.GetGitRefName(), false, false)
|
||||
|
||||
} else {
|
||||
prInfo, err = gitRepo.GetCompareInfo(gitRepo.Path, pull.MergeBase, pull.GetGitRefName(), false, false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||
commits = prInfo.Commits
|
||||
userCommits := user_model.ValidateCommitsWithEmails(commits)
|
||||
signCommits := asymkey_model.ParseCommitsWithSignature(userCommits, ctx.Repo.Repository.GetTrustModel(),
|
||||
func(user *user_model.User) (bool, error) {
|
||||
return repo_model.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID)
|
||||
})
|
||||
signStatusCommits := git_model.ParseCommitsWithStatus(signCommits, ctx.Repo.Repository)
|
||||
|
||||
result := make([]PullRequestCommit, 0)
|
||||
for _, commit := range signStatusCommits {
|
||||
result = append(result, PullRequestCommit{
|
||||
SignCommitWithStatuses: *commit,
|
||||
Sha: commit.ID.String(),
|
||||
})
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func GetPullFiles(ctx *context.APIContext) {
|
||||
pull, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
issue := pull.Issue
|
||||
if issue == nil {
|
||||
ctx.NotFound("issue is not present.")
|
||||
return
|
||||
}
|
||||
gitRepo := ctx.Repo.GitRepo
|
||||
|
||||
var prInfo *git.CompareInfo
|
||||
|
||||
if pull.HasMerged {
|
||||
var baseCommit string
|
||||
if pull.MergeBase == "" {
|
||||
var commitSHA, parentCommit string
|
||||
commitSHA, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
|
||||
if err != nil {
|
||||
commitSHA, err := gitRepo.ReadPatchCommit(pull.Index)
|
||||
if err == nil {
|
||||
if err := gitRepo.SetReference(pull.GetGitRefName(), commitSHA); err != nil {
|
||||
log.Error("Could not write head file", err)
|
||||
}
|
||||
} else {
|
||||
log.Trace("No history file available for PR %d", pull.Index)
|
||||
}
|
||||
}
|
||||
if commitSHA != "" {
|
||||
parentCommit, _, err = git.NewCommand(ctx, "rev-list", "-1", "--skip=1", commitSHA).RunStdString(&git.RunOpts{Dir: gitRepo.Path})
|
||||
if err == nil {
|
||||
parentCommit = strings.TrimSpace(parentCommit)
|
||||
}
|
||||
if err != nil || parentCommit == "" {
|
||||
log.Info("No known parent commit for PR %d, error: %v", pull.Index, err)
|
||||
parentCommit = commitSHA
|
||||
}
|
||||
}
|
||||
baseCommit = parentCommit
|
||||
} else {
|
||||
baseCommit = pull.MergeBase
|
||||
}
|
||||
prInfo, err = gitRepo.GetCompareInfo(gitRepo.Path, baseCommit, pull.GetGitRefName(), false, false)
|
||||
|
||||
} else {
|
||||
prInfo, err = gitRepo.GetCompareInfo(gitRepo.Path, pull.MergeBase, pull.GetGitRefName(), false, false)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err)
|
||||
return
|
||||
}
|
||||
|
||||
headCommitID, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetRefCommitID", err)
|
||||
return
|
||||
}
|
||||
|
||||
startCommitID := prInfo.MergeBase
|
||||
endCommitID := headCommitID
|
||||
|
||||
ctx.Data["WhitespaceBehavior"] = ""
|
||||
diff := &gitdiff.Diff{Files: make([]*gitdiff.DiffFile, 0)}
|
||||
if ctx.Params("not-need-files") == "true" || ctx.Params("only-file-name") == "true" {
|
||||
shortstatArgs := []string{startCommitID + "..." + endCommitID}
|
||||
if len(startCommitID) == 0 || startCommitID == git.EmptySHA {
|
||||
shortstatArgs = []string{git.EmptyTreeSHA, endCommitID}
|
||||
}
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(ctx, gitRepo.Path, shortstatArgs...)
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// git >= 2.28 now returns an error if base and head have become unrelated.
|
||||
// previously it would return the results of git diff --shortstat base head so let's try that...
|
||||
shortstatArgs = []string{startCommitID, endCommitID}
|
||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, _ = git.GetDiffShortStat(ctx, gitRepo.Path, shortstatArgs...)
|
||||
}
|
||||
if ctx.Params("only-file-name") == "true" {
|
||||
var diffString string
|
||||
var err error
|
||||
if len(startCommitID) == 0 || startCommitID == git.EmptySHA {
|
||||
diffString, err = hat_git.GetDiffFileOnlyName(ctx.Repo.GitRepo, git.EmptyTreeSHA, headCommitID)
|
||||
} else {
|
||||
diffString, err = hat_git.GetDiffFileOnlyName(ctx.Repo.GitRepo, startCommitID, headCommitID)
|
||||
}
|
||||
if err == nil {
|
||||
for _, fileName := range strings.Split(diffString, "\n") {
|
||||
if fileName != "" {
|
||||
diff.Files = append(diff.Files, &gitdiff.DiffFile{
|
||||
Name: fileName,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diff, err = gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{
|
||||
BeforeCommitID: startCommitID,
|
||||
AfterCommitID: endCommitID,
|
||||
SkipTo: ctx.FormString("skip-to"),
|
||||
MaxLines: setting.Git.MaxGitDiffLines,
|
||||
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||
MaxFiles: setting.Git.MaxGitDiffFiles,
|
||||
WhitespaceBehavior: ctx.Data["WhitespaceBehavior"].(string)})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = diff.LoadComments(ctx, issue, ctx.Doer); err != nil {
|
||||
ctx.ServerError("LoadComments", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fileDiff := struct {
|
||||
*gitdiff.Diff
|
||||
LatestSha string
|
||||
}{
|
||||
Diff: diff,
|
||||
LatestSha: endCommitID,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, fileDiff)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue