@@ -26,13 +26,15 @@ import (
2626 "code.gitea.io/gitea/modules/git"
2727 "code.gitea.io/gitea/modules/log"
2828 "code.gitea.io/gitea/modules/notification"
29+ "code.gitea.io/gitea/modules/setting"
2930 api "code.gitea.io/gitea/modules/structs"
3031 "code.gitea.io/gitea/modules/timeutil"
3132 "code.gitea.io/gitea/modules/web"
3233 "code.gitea.io/gitea/routers/api/v1/utils"
3334 asymkey_service "code.gitea.io/gitea/services/asymkey"
3435 "code.gitea.io/gitea/services/automerge"
3536 "code.gitea.io/gitea/services/forms"
37+ "code.gitea.io/gitea/services/gitdiff"
3638 issue_service "code.gitea.io/gitea/services/issue"
3739 pull_service "code.gitea.io/gitea/services/pull"
3840 repo_service "code.gitea.io/gitea/services/repository"
@@ -1323,3 +1325,137 @@ func GetPullRequestCommits(ctx *context.APIContext) {
13231325
13241326 ctx .JSON (http .StatusOK , & apiCommits )
13251327}
1328+
1329+ // GetPullRequestFiles gets all changed files associated with a given PR
1330+ func GetPullRequestFiles (ctx * context.APIContext ) {
1331+ // swagger:operation GET /repos/{owner}/{repo}/pulls/{index}/files repository repoGetPullRequestFiles
1332+ // ---
1333+ // summary: Get changed files for a pull request
1334+ // produces:
1335+ // - application/json
1336+ // parameters:
1337+ // - name: owner
1338+ // in: path
1339+ // description: owner of the repo
1340+ // type: string
1341+ // required: true
1342+ // - name: repo
1343+ // in: path
1344+ // description: name of the repo
1345+ // type: string
1346+ // required: true
1347+ // - name: index
1348+ // in: path
1349+ // description: index of the pull request to get
1350+ // type: integer
1351+ // format: int64
1352+ // required: true
1353+ // - name: skip-to
1354+ // in: query
1355+ // description: skip to given file
1356+ // type: string
1357+ // - name: whitespace
1358+ // in: query
1359+ // description: whitespace behavior
1360+ // type: string
1361+ // enum: [ignore-all, ignore-change, ignore-eol, show-all]
1362+ // - name: page
1363+ // in: query
1364+ // description: page number of results to return (1-based)
1365+ // type: integer
1366+ // - name: limit
1367+ // in: query
1368+ // description: page size of results
1369+ // type: integer
1370+ // responses:
1371+ // "200":
1372+ // "$ref": "#/responses/ChangedFileList"
1373+ // "404":
1374+ // "$ref": "#/responses/notFound"
1375+
1376+ pr , err := issues_model .GetPullRequestByIndex (ctx , ctx .Repo .Repository .ID , ctx .ParamsInt64 (":index" ))
1377+ if err != nil {
1378+ if issues_model .IsErrPullRequestNotExist (err ) {
1379+ ctx .NotFound ()
1380+ } else {
1381+ ctx .Error (http .StatusInternalServerError , "GetPullRequestByIndex" , err )
1382+ }
1383+ return
1384+ }
1385+
1386+ if err := pr .LoadBaseRepo (); err != nil {
1387+ ctx .InternalServerError (err )
1388+ return
1389+ }
1390+
1391+ if err := pr .LoadHeadRepo (); err != nil {
1392+ ctx .InternalServerError (err )
1393+ return
1394+ }
1395+
1396+ baseGitRepo := ctx .Repo .GitRepo
1397+
1398+ var prInfo * git.CompareInfo
1399+ if pr .HasMerged {
1400+ prInfo , err = baseGitRepo .GetCompareInfo (pr .BaseRepo .RepoPath (), pr .MergeBase , pr .GetGitRefName (), true , false )
1401+ } else {
1402+ prInfo , err = baseGitRepo .GetCompareInfo (pr .BaseRepo .RepoPath (), pr .BaseBranch , pr .GetGitRefName (), true , false )
1403+ }
1404+ if err != nil {
1405+ ctx .ServerError ("GetCompareInfo" , err )
1406+ return
1407+ }
1408+
1409+ headCommitID , err := baseGitRepo .GetRefCommitID (pr .GetGitRefName ())
1410+ if err != nil {
1411+ ctx .ServerError ("GetRefCommitID" , err )
1412+ return
1413+ }
1414+
1415+ startCommitID := prInfo .MergeBase
1416+ endCommitID := headCommitID
1417+
1418+ maxLines , maxFiles := setting .Git .MaxGitDiffLines , setting .Git .MaxGitDiffFiles
1419+
1420+ diff , err := gitdiff .GetDiff (baseGitRepo ,
1421+ & gitdiff.DiffOptions {
1422+ BeforeCommitID : startCommitID ,
1423+ AfterCommitID : endCommitID ,
1424+ SkipTo : ctx .FormString ("skip-to" ),
1425+ MaxLines : maxLines ,
1426+ MaxLineCharacters : setting .Git .MaxGitDiffLineCharacters ,
1427+ MaxFiles : maxFiles ,
1428+ WhitespaceBehavior : gitdiff .GetWhitespaceFlag (ctx .FormString ("whitespace" )),
1429+ })
1430+ if err != nil {
1431+ ctx .ServerError ("GetDiff" , err )
1432+ return
1433+ }
1434+
1435+ listOptions := utils .GetListOptions (ctx )
1436+
1437+ totalNumberOfFiles := diff .NumFiles
1438+ totalNumberOfPages := int (math .Ceil (float64 (totalNumberOfFiles ) / float64 (listOptions .PageSize )))
1439+
1440+ start , end := listOptions .GetStartEnd ()
1441+
1442+ if end > totalNumberOfFiles {
1443+ end = totalNumberOfFiles
1444+ }
1445+
1446+ apiFiles := make ([]* api.ChangedFile , 0 , end - start )
1447+ for i := start ; i < end ; i ++ {
1448+ apiFiles = append (apiFiles , convert .ToChangedFile (diff .Files [i ], pr .HeadRepo , endCommitID ))
1449+ }
1450+
1451+ ctx .SetLinkHeader (totalNumberOfFiles , listOptions .PageSize )
1452+ ctx .SetTotalCountHeader (int64 (totalNumberOfFiles ))
1453+
1454+ ctx .RespHeader ().Set ("X-Page" , strconv .Itoa (listOptions .Page ))
1455+ ctx .RespHeader ().Set ("X-PerPage" , strconv .Itoa (listOptions .PageSize ))
1456+ ctx .RespHeader ().Set ("X-PageCount" , strconv .Itoa (totalNumberOfPages ))
1457+ ctx .RespHeader ().Set ("X-HasMore" , strconv .FormatBool (listOptions .Page < totalNumberOfPages ))
1458+ ctx .AppendAccessControlExposeHeaders ("X-Page" , "X-PerPage" , "X-PageCount" , "X-HasMore" )
1459+
1460+ ctx .JSON (http .StatusOK , & apiFiles )
1461+ }
0 commit comments