@@ -26,13 +26,15 @@ import (
26
26
"code.gitea.io/gitea/modules/git"
27
27
"code.gitea.io/gitea/modules/log"
28
28
"code.gitea.io/gitea/modules/notification"
29
+ "code.gitea.io/gitea/modules/setting"
29
30
api "code.gitea.io/gitea/modules/structs"
30
31
"code.gitea.io/gitea/modules/timeutil"
31
32
"code.gitea.io/gitea/modules/web"
32
33
"code.gitea.io/gitea/routers/api/v1/utils"
33
34
asymkey_service "code.gitea.io/gitea/services/asymkey"
34
35
"code.gitea.io/gitea/services/automerge"
35
36
"code.gitea.io/gitea/services/forms"
37
+ "code.gitea.io/gitea/services/gitdiff"
36
38
issue_service "code.gitea.io/gitea/services/issue"
37
39
pull_service "code.gitea.io/gitea/services/pull"
38
40
repo_service "code.gitea.io/gitea/services/repository"
@@ -1323,3 +1325,137 @@ func GetPullRequestCommits(ctx *context.APIContext) {
1323
1325
1324
1326
ctx .JSON (http .StatusOK , & apiCommits )
1325
1327
}
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