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("/pulls", func() {
|
||||||
m.Group("/{index}", func() {
|
m.Group("/{index}", func() {
|
||||||
m.Combo("").Get(repo.GetPullRequest)
|
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())
|
}, mustAllowPulls, reqRepoReader(unit_model.TypeCode), context.ReferencesGitRepo())
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
|
|
|
@ -2,10 +2,21 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"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"
|
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/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"
|
"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) {
|
func GetPullRequest(ctx *context.APIContext) {
|
||||||
|
@ -34,3 +45,222 @@ func GetPullRequest(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusOK, apiResult)
|
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