aboutsummaryrefslogtreecommitdiffstats
path: root/routers/api
diff options
context:
space:
mode:
authorqwerty287 <80460567+qwerty287@users.noreply.github.com>2022-09-29 04:27:20 +0200
committerGitHub <noreply@github.com>2022-09-29 04:27:20 +0200
commit1dfa28ffa557720d164a351783be64c9a47a0adb (patch)
tree93c7cae9241eb71f8d377c8f089417ac7dcf448b /routers/api
parent78c15dabf33f32050757ab410266ddb348c1a863 (diff)
downloadgitea-1dfa28ffa557720d164a351783be64c9a47a0adb.tar.gz
gitea-1dfa28ffa557720d164a351783be64c9a47a0adb.zip
Add API endpoint to get changed files of a PR (#21177)
This adds an api endpoint `/files` to PRs that allows to get a list of changed files. built upon #18228, reviews there are included closes https://github.com/go-gitea/gitea/issues/654 Co-authored-by: Anton Bracke <anton@ju60.de> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'routers/api')
-rw-r--r--routers/api/v1/api.go1
-rw-r--r--routers/api/v1/repo/pull.go136
-rw-r--r--routers/api/v1/swagger/repo.go22
3 files changed, 159 insertions, 0 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 6a98121b73..0d11674aa9 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -1002,6 +1002,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch)
m.Post("/update", reqToken(), repo.UpdatePullRequest)
m.Get("/commits", repo.GetPullRequestCommits)
+ m.Get("/files", repo.GetPullRequestFiles)
m.Combo("/merge").Get(repo.IsPullRequestMerged).
Post(reqToken(), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
Delete(reqToken(), mustNotBeArchived, repo.CancelScheduledAutoMerge)
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index dda05203df..2cf30e7c47 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
+ "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
@@ -33,6 +34,7 @@ import (
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/automerge"
"code.gitea.io/gitea/services/forms"
+ "code.gitea.io/gitea/services/gitdiff"
issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
@@ -1323,3 +1325,137 @@ func GetPullRequestCommits(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, &apiCommits)
}
+
+// GetPullRequestFiles gets all changed files associated with a given PR
+func GetPullRequestFiles(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/pulls/{index}/files repository repoGetPullRequestFiles
+ // ---
+ // summary: Get changed files for a pull request
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the repo
+ // type: string
+ // required: true
+ // - name: repo
+ // in: path
+ // description: name of the repo
+ // type: string
+ // required: true
+ // - name: index
+ // in: path
+ // description: index of the pull request to get
+ // type: integer
+ // format: int64
+ // required: true
+ // - name: skip-to
+ // in: query
+ // description: skip to given file
+ // type: string
+ // - name: whitespace
+ // in: query
+ // description: whitespace behavior
+ // type: string
+ // enum: [ignore-all, ignore-change, ignore-eol, show-all]
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/ChangedFileList"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ pr, 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
+ }
+
+ if err := pr.LoadBaseRepo(); err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
+ if err := pr.LoadHeadRepo(); err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
+ baseGitRepo := ctx.Repo.GitRepo
+
+ var prInfo *git.CompareInfo
+ if pr.HasMerged {
+ prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.MergeBase, pr.GetGitRefName(), true, false)
+ } else {
+ prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName(), true, false)
+ }
+ if err != nil {
+ ctx.ServerError("GetCompareInfo", err)
+ return
+ }
+
+ headCommitID, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
+ if err != nil {
+ ctx.ServerError("GetRefCommitID", err)
+ return
+ }
+
+ startCommitID := prInfo.MergeBase
+ endCommitID := headCommitID
+
+ maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
+
+ diff, err := gitdiff.GetDiff(baseGitRepo,
+ &gitdiff.DiffOptions{
+ BeforeCommitID: startCommitID,
+ AfterCommitID: endCommitID,
+ SkipTo: ctx.FormString("skip-to"),
+ MaxLines: maxLines,
+ MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
+ MaxFiles: maxFiles,
+ WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.FormString("whitespace")),
+ })
+ if err != nil {
+ ctx.ServerError("GetDiff", err)
+ return
+ }
+
+ listOptions := utils.GetListOptions(ctx)
+
+ totalNumberOfFiles := diff.NumFiles
+ totalNumberOfPages := int(math.Ceil(float64(totalNumberOfFiles) / float64(listOptions.PageSize)))
+
+ start, end := listOptions.GetStartEnd()
+
+ if end > totalNumberOfFiles {
+ end = totalNumberOfFiles
+ }
+
+ apiFiles := make([]*api.ChangedFile, 0, end-start)
+ for i := start; i < end; i++ {
+ apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], pr.HeadRepo, endCommitID))
+ }
+
+ ctx.SetLinkHeader(totalNumberOfFiles, listOptions.PageSize)
+ ctx.SetTotalCountHeader(int64(totalNumberOfFiles))
+
+ ctx.RespHeader().Set("X-Page", strconv.Itoa(listOptions.Page))
+ ctx.RespHeader().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
+ ctx.RespHeader().Set("X-PageCount", strconv.Itoa(totalNumberOfPages))
+ ctx.RespHeader().Set("X-HasMore", strconv.FormatBool(listOptions.Page < totalNumberOfPages))
+ ctx.AppendAccessControlExposeHeaders("X-Page", "X-PerPage", "X-PageCount", "X-HasMore")
+
+ ctx.JSON(http.StatusOK, &apiFiles)
+}
diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go
index 3522e24276..642b1b7b91 100644
--- a/routers/api/v1/swagger/repo.go
+++ b/routers/api/v1/swagger/repo.go
@@ -254,6 +254,28 @@ type swaggerCommitList struct {
Body []api.Commit `json:"body"`
}
+// ChangedFileList
+// swagger:response ChangedFileList
+type swaggerChangedFileList struct {
+ // The current page
+ Page int `json:"X-Page"`
+
+ // Commits per page
+ PerPage int `json:"X-PerPage"`
+
+ // Total commit count
+ Total int `json:"X-Total"`
+
+ // Total number of pages
+ PageCount int `json:"X-PageCount"`
+
+ // True if there is another page
+ HasMore bool `json:"X-HasMore"`
+
+ // in: body
+ Body []api.ChangedFile `json:"body"`
+}
+
// Note
// swagger:response Note
type swaggerNote struct {