You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

pull.go 20 kB

Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Issue due date (#3794) * Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
7 years ago
Issue due date (#3794) * Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
7 years ago
Issue due date (#3794) * Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
7 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Issue due date (#3794) * Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
7 years ago
Issue due date (#3794) * Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
7 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show pull request form after click on button Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Updates css file Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath <art27@cantab.net> * Update from master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjusts comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use compareInfo instead of prInfo
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. // Copyright 2016 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "fmt"
  7. "net/http"
  8. "strings"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/auth"
  11. "code.gitea.io/gitea/modules/context"
  12. "code.gitea.io/gitea/modules/git"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/notification"
  15. "code.gitea.io/gitea/modules/pull"
  16. api "code.gitea.io/gitea/modules/structs"
  17. "code.gitea.io/gitea/modules/timeutil"
  18. milestone_service "code.gitea.io/gitea/services/milestone"
  19. )
  20. // ListPullRequests returns a list of all PRs
  21. func ListPullRequests(ctx *context.APIContext, form api.ListPullRequestsOptions) {
  22. // swagger:operation GET /repos/{owner}/{repo}/pulls repository repoListPullRequests
  23. // ---
  24. // summary: List a repo's pull requests
  25. // produces:
  26. // - application/json
  27. // parameters:
  28. // - name: owner
  29. // in: path
  30. // description: owner of the repo
  31. // type: string
  32. // required: true
  33. // - name: repo
  34. // in: path
  35. // description: name of the repo
  36. // type: string
  37. // required: true
  38. // - name: page
  39. // in: query
  40. // description: Page number
  41. // type: integer
  42. // - name: state
  43. // in: query
  44. // description: "State of pull request: open or closed (optional)"
  45. // type: string
  46. // enum: [closed, open, all]
  47. // - name: sort
  48. // in: query
  49. // description: "Type of sort"
  50. // type: string
  51. // enum: [oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority]
  52. // - name: milestone
  53. // in: query
  54. // description: "ID of the milestone"
  55. // type: integer
  56. // format: int64
  57. // - name: labels
  58. // in: query
  59. // description: "Label IDs"
  60. // type: array
  61. // collectionFormat: multi
  62. // items:
  63. // type: integer
  64. // format: int64
  65. // responses:
  66. // "200":
  67. // "$ref": "#/responses/PullRequestList"
  68. prs, maxResults, err := models.PullRequests(ctx.Repo.Repository.ID, &models.PullRequestsOptions{
  69. Page: ctx.QueryInt("page"),
  70. State: ctx.QueryTrim("state"),
  71. SortType: ctx.QueryTrim("sort"),
  72. Labels: ctx.QueryStrings("labels"),
  73. MilestoneID: ctx.QueryInt64("milestone"),
  74. })
  75. if err != nil {
  76. ctx.Error(500, "PullRequests", err)
  77. return
  78. }
  79. apiPrs := make([]*api.PullRequest, len(prs))
  80. for i := range prs {
  81. if err = prs[i].LoadIssue(); err != nil {
  82. ctx.Error(500, "LoadIssue", err)
  83. return
  84. }
  85. if err = prs[i].LoadAttributes(); err != nil {
  86. ctx.Error(500, "LoadAttributes", err)
  87. return
  88. }
  89. if err = prs[i].GetBaseRepo(); err != nil {
  90. ctx.Error(500, "GetBaseRepo", err)
  91. return
  92. }
  93. if err = prs[i].GetHeadRepo(); err != nil {
  94. ctx.Error(500, "GetHeadRepo", err)
  95. return
  96. }
  97. apiPrs[i] = prs[i].APIFormat()
  98. }
  99. ctx.SetLinkHeader(int(maxResults), models.ItemsPerPage)
  100. ctx.JSON(200, &apiPrs)
  101. }
  102. // GetPullRequest returns a single PR based on index
  103. func GetPullRequest(ctx *context.APIContext) {
  104. // swagger:operation GET /repos/{owner}/{repo}/pulls/{index} repository repoGetPullRequest
  105. // ---
  106. // summary: Get a pull request
  107. // produces:
  108. // - application/json
  109. // parameters:
  110. // - name: owner
  111. // in: path
  112. // description: owner of the repo
  113. // type: string
  114. // required: true
  115. // - name: repo
  116. // in: path
  117. // description: name of the repo
  118. // type: string
  119. // required: true
  120. // - name: index
  121. // in: path
  122. // description: index of the pull request to get
  123. // type: integer
  124. // format: int64
  125. // required: true
  126. // responses:
  127. // "200":
  128. // "$ref": "#/responses/PullRequest"
  129. pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  130. if err != nil {
  131. if models.IsErrPullRequestNotExist(err) {
  132. ctx.NotFound()
  133. } else {
  134. ctx.Error(500, "GetPullRequestByIndex", err)
  135. }
  136. return
  137. }
  138. if err = pr.GetBaseRepo(); err != nil {
  139. ctx.Error(500, "GetBaseRepo", err)
  140. return
  141. }
  142. if err = pr.GetHeadRepo(); err != nil {
  143. ctx.Error(500, "GetHeadRepo", err)
  144. return
  145. }
  146. ctx.JSON(200, pr.APIFormat())
  147. }
  148. // CreatePullRequest does what it says
  149. func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption) {
  150. // swagger:operation POST /repos/{owner}/{repo}/pulls repository repoCreatePullRequest
  151. // ---
  152. // summary: Create a pull request
  153. // consumes:
  154. // - application/json
  155. // produces:
  156. // - application/json
  157. // parameters:
  158. // - name: owner
  159. // in: path
  160. // description: owner of the repo
  161. // type: string
  162. // required: true
  163. // - name: repo
  164. // in: path
  165. // description: name of the repo
  166. // type: string
  167. // required: true
  168. // - name: body
  169. // in: body
  170. // schema:
  171. // "$ref": "#/definitions/CreatePullRequestOption"
  172. // responses:
  173. // "201":
  174. // "$ref": "#/responses/PullRequest"
  175. var (
  176. repo = ctx.Repo.Repository
  177. labelIDs []int64
  178. assigneeID int64
  179. milestoneID int64
  180. )
  181. // Get repo/branch information
  182. headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := parseCompareInfo(ctx, form)
  183. if ctx.Written() {
  184. return
  185. }
  186. // Check if another PR exists with the same targets
  187. existingPr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch)
  188. if err != nil {
  189. if !models.IsErrPullRequestNotExist(err) {
  190. ctx.Error(500, "GetUnmergedPullRequest", err)
  191. return
  192. }
  193. } else {
  194. err = models.ErrPullRequestAlreadyExists{
  195. ID: existingPr.ID,
  196. IssueID: existingPr.Index,
  197. HeadRepoID: existingPr.HeadRepoID,
  198. BaseRepoID: existingPr.BaseRepoID,
  199. HeadBranch: existingPr.HeadBranch,
  200. BaseBranch: existingPr.BaseBranch,
  201. }
  202. ctx.Error(409, "GetUnmergedPullRequest", err)
  203. return
  204. }
  205. if len(form.Labels) > 0 {
  206. labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels)
  207. if err != nil {
  208. ctx.Error(500, "GetLabelsInRepoByIDs", err)
  209. return
  210. }
  211. labelIDs = make([]int64, len(labels))
  212. for i := range labels {
  213. labelIDs[i] = labels[i].ID
  214. }
  215. }
  216. if form.Milestone > 0 {
  217. milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, milestoneID)
  218. if err != nil {
  219. if models.IsErrMilestoneNotExist(err) {
  220. ctx.NotFound()
  221. } else {
  222. ctx.Error(500, "GetMilestoneByRepoID", err)
  223. }
  224. return
  225. }
  226. milestoneID = milestone.ID
  227. }
  228. patch, err := headGitRepo.GetPatch(compareInfo.MergeBase, headBranch)
  229. if err != nil {
  230. ctx.Error(500, "GetPatch", err)
  231. return
  232. }
  233. var deadlineUnix timeutil.TimeStamp
  234. if form.Deadline != nil {
  235. deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
  236. }
  237. prIssue := &models.Issue{
  238. RepoID: repo.ID,
  239. Title: form.Title,
  240. PosterID: ctx.User.ID,
  241. Poster: ctx.User,
  242. MilestoneID: milestoneID,
  243. AssigneeID: assigneeID,
  244. IsPull: true,
  245. Content: form.Body,
  246. DeadlineUnix: deadlineUnix,
  247. }
  248. pr := &models.PullRequest{
  249. HeadRepoID: headRepo.ID,
  250. BaseRepoID: repo.ID,
  251. HeadUserName: headUser.Name,
  252. HeadBranch: headBranch,
  253. BaseBranch: baseBranch,
  254. HeadRepo: headRepo,
  255. BaseRepo: repo,
  256. MergeBase: compareInfo.MergeBase,
  257. Type: models.PullRequestGitea,
  258. }
  259. // Get all assignee IDs
  260. assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees)
  261. if err != nil {
  262. if models.IsErrUserNotExist(err) {
  263. ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
  264. } else {
  265. ctx.Error(500, "AddAssigneeByName", err)
  266. }
  267. return
  268. }
  269. if err := models.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, patch, assigneeIDs); err != nil {
  270. if models.IsErrUserDoesNotHaveAccessToRepo(err) {
  271. ctx.Error(400, "UserDoesNotHaveAccessToRepo", err)
  272. return
  273. }
  274. ctx.Error(500, "NewPullRequest", err)
  275. return
  276. } else if err := pr.PushToBaseRepo(); err != nil {
  277. ctx.Error(500, "PushToBaseRepo", err)
  278. return
  279. }
  280. notification.NotifyNewPullRequest(pr)
  281. log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID)
  282. ctx.JSON(201, pr.APIFormat())
  283. }
  284. // EditPullRequest does what it says
  285. func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
  286. // swagger:operation PATCH /repos/{owner}/{repo}/pulls/{index} repository repoEditPullRequest
  287. // ---
  288. // summary: Update a pull request
  289. // consumes:
  290. // - application/json
  291. // produces:
  292. // - application/json
  293. // parameters:
  294. // - name: owner
  295. // in: path
  296. // description: owner of the repo
  297. // type: string
  298. // required: true
  299. // - name: repo
  300. // in: path
  301. // description: name of the repo
  302. // type: string
  303. // required: true
  304. // - name: index
  305. // in: path
  306. // description: index of the pull request to edit
  307. // type: integer
  308. // format: int64
  309. // required: true
  310. // - name: body
  311. // in: body
  312. // schema:
  313. // "$ref": "#/definitions/EditPullRequestOption"
  314. // responses:
  315. // "201":
  316. // "$ref": "#/responses/PullRequest"
  317. pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  318. if err != nil {
  319. if models.IsErrPullRequestNotExist(err) {
  320. ctx.NotFound()
  321. } else {
  322. ctx.Error(500, "GetPullRequestByIndex", err)
  323. }
  324. return
  325. }
  326. err = pr.LoadIssue()
  327. if err != nil {
  328. ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
  329. return
  330. }
  331. issue := pr.Issue
  332. issue.Repo = ctx.Repo.Repository
  333. if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypePullRequests) {
  334. ctx.Status(403)
  335. return
  336. }
  337. if len(form.Title) > 0 {
  338. issue.Title = form.Title
  339. }
  340. if len(form.Body) > 0 {
  341. issue.Content = form.Body
  342. }
  343. // Update Deadline
  344. var deadlineUnix timeutil.TimeStamp
  345. if form.Deadline != nil && !form.Deadline.IsZero() {
  346. deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
  347. }
  348. if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
  349. ctx.Error(500, "UpdateIssueDeadline", err)
  350. return
  351. }
  352. // Add/delete assignees
  353. // Deleting is done the GitHub way (quote from their api documentation):
  354. // https://developer.github.com/v3/issues/#edit-an-issue
  355. // "assignees" (array): Logins for Users to assign to this issue.
  356. // Pass one or more user logins to replace the set of assignees on this Issue.
  357. // Send an empty array ([]) to clear all assignees from the Issue.
  358. if ctx.Repo.CanWrite(models.UnitTypePullRequests) && (form.Assignees != nil || len(form.Assignee) > 0) {
  359. err = models.UpdateAPIAssignee(issue, form.Assignee, form.Assignees, ctx.User)
  360. if err != nil {
  361. if models.IsErrUserNotExist(err) {
  362. ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
  363. } else {
  364. ctx.Error(500, "UpdateAPIAssignee", err)
  365. }
  366. return
  367. }
  368. }
  369. if ctx.Repo.CanWrite(models.UnitTypePullRequests) && form.Milestone != 0 &&
  370. issue.MilestoneID != form.Milestone {
  371. oldMilestoneID := issue.MilestoneID
  372. issue.MilestoneID = form.Milestone
  373. if err = milestone_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
  374. ctx.Error(500, "ChangeMilestoneAssign", err)
  375. return
  376. }
  377. }
  378. if ctx.Repo.CanWrite(models.UnitTypePullRequests) && form.Labels != nil {
  379. labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels)
  380. if err != nil {
  381. ctx.Error(500, "GetLabelsInRepoByIDsError", err)
  382. return
  383. }
  384. if err = issue.ReplaceLabels(labels, ctx.User); err != nil {
  385. ctx.Error(500, "ReplaceLabelsError", err)
  386. return
  387. }
  388. }
  389. if err = models.UpdateIssue(issue); err != nil {
  390. ctx.Error(500, "UpdateIssue", err)
  391. return
  392. }
  393. if form.State != nil {
  394. if err = issue.ChangeStatus(ctx.User, api.StateClosed == api.StateType(*form.State)); err != nil {
  395. if models.IsErrDependenciesLeft(err) {
  396. ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
  397. return
  398. }
  399. ctx.Error(500, "ChangeStatus", err)
  400. return
  401. }
  402. notification.NotifyIssueChangeStatus(ctx.User, issue, api.StateClosed == api.StateType(*form.State))
  403. }
  404. // Refetch from database
  405. pr, err = models.GetPullRequestByIndex(ctx.Repo.Repository.ID, pr.Index)
  406. if err != nil {
  407. if models.IsErrPullRequestNotExist(err) {
  408. ctx.NotFound()
  409. } else {
  410. ctx.Error(500, "GetPullRequestByIndex", err)
  411. }
  412. return
  413. }
  414. // TODO this should be 200, not 201
  415. ctx.JSON(201, pr.APIFormat())
  416. }
  417. // IsPullRequestMerged checks if a PR exists given an index
  418. func IsPullRequestMerged(ctx *context.APIContext) {
  419. // swagger:operation GET /repos/{owner}/{repo}/pulls/{index}/merge repository repoPullRequestIsMerged
  420. // ---
  421. // summary: Check if a pull request has been merged
  422. // produces:
  423. // - application/json
  424. // parameters:
  425. // - name: owner
  426. // in: path
  427. // description: owner of the repo
  428. // type: string
  429. // required: true
  430. // - name: repo
  431. // in: path
  432. // description: name of the repo
  433. // type: string
  434. // required: true
  435. // - name: index
  436. // in: path
  437. // description: index of the pull request
  438. // type: integer
  439. // format: int64
  440. // required: true
  441. // responses:
  442. // "204":
  443. // description: pull request has been merged
  444. // "404":
  445. // description: pull request has not been merged
  446. pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  447. if err != nil {
  448. if models.IsErrPullRequestNotExist(err) {
  449. ctx.NotFound()
  450. } else {
  451. ctx.Error(500, "GetPullRequestByIndex", err)
  452. }
  453. return
  454. }
  455. if pr.HasMerged {
  456. ctx.Status(204)
  457. }
  458. ctx.NotFound()
  459. }
  460. // MergePullRequest merges a PR given an index
  461. func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) {
  462. // swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/merge repository repoMergePullRequest
  463. // ---
  464. // summary: Merge a pull request
  465. // produces:
  466. // - application/json
  467. // parameters:
  468. // - name: owner
  469. // in: path
  470. // description: owner of the repo
  471. // type: string
  472. // required: true
  473. // - name: repo
  474. // in: path
  475. // description: name of the repo
  476. // type: string
  477. // required: true
  478. // - name: index
  479. // in: path
  480. // description: index of the pull request to merge
  481. // type: integer
  482. // format: int64
  483. // required: true
  484. // - name: body
  485. // in: body
  486. // schema:
  487. // $ref: "#/definitions/MergePullRequestOption"
  488. // responses:
  489. // "200":
  490. // "$ref": "#/responses/empty"
  491. // "405":
  492. // "$ref": "#/responses/empty"
  493. pr, err := models.GetPullRequestByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  494. if err != nil {
  495. if models.IsErrPullRequestNotExist(err) {
  496. ctx.NotFound("GetPullRequestByIndex", err)
  497. } else {
  498. ctx.Error(500, "GetPullRequestByIndex", err)
  499. }
  500. return
  501. }
  502. if err = pr.GetHeadRepo(); err != nil {
  503. ctx.ServerError("GetHeadRepo", err)
  504. return
  505. }
  506. err = pr.LoadIssue()
  507. if err != nil {
  508. ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
  509. return
  510. }
  511. pr.Issue.Repo = ctx.Repo.Repository
  512. if ctx.IsSigned {
  513. // Update issue-user.
  514. if err = pr.Issue.ReadBy(ctx.User.ID); err != nil {
  515. ctx.Error(500, "ReadBy", err)
  516. return
  517. }
  518. }
  519. if pr.Issue.IsClosed {
  520. ctx.NotFound()
  521. return
  522. }
  523. if !pr.CanAutoMerge() || pr.HasMerged || pr.IsWorkInProgress() {
  524. ctx.Status(405)
  525. return
  526. }
  527. if len(form.Do) == 0 {
  528. form.Do = string(models.MergeStyleMerge)
  529. }
  530. message := strings.TrimSpace(form.MergeTitleField)
  531. if len(message) == 0 {
  532. if models.MergeStyle(form.Do) == models.MergeStyleMerge {
  533. message = pr.GetDefaultMergeMessage()
  534. }
  535. if models.MergeStyle(form.Do) == models.MergeStyleSquash {
  536. message = pr.GetDefaultSquashMessage()
  537. }
  538. }
  539. form.MergeMessageField = strings.TrimSpace(form.MergeMessageField)
  540. if len(form.MergeMessageField) > 0 {
  541. message += "\n\n" + form.MergeMessageField
  542. }
  543. if err := pull.Merge(pr, ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil {
  544. if models.IsErrInvalidMergeStyle(err) {
  545. ctx.Status(405)
  546. return
  547. }
  548. ctx.Error(500, "Merge", err)
  549. return
  550. }
  551. log.Trace("Pull request merged: %d", pr.ID)
  552. ctx.Status(200)
  553. }
  554. func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) {
  555. baseRepo := ctx.Repo.Repository
  556. // Get compared branches information
  557. // format: <base branch>...[<head repo>:]<head branch>
  558. // base<-head: master...head:feature
  559. // same repo: master...feature
  560. // TODO: Validate form first?
  561. baseBranch := form.Base
  562. var (
  563. headUser *models.User
  564. headBranch string
  565. isSameRepo bool
  566. err error
  567. )
  568. // If there is no head repository, it means pull request between same repository.
  569. headInfos := strings.Split(form.Head, ":")
  570. if len(headInfos) == 1 {
  571. isSameRepo = true
  572. headUser = ctx.Repo.Owner
  573. headBranch = headInfos[0]
  574. } else if len(headInfos) == 2 {
  575. headUser, err = models.GetUserByName(headInfos[0])
  576. if err != nil {
  577. if models.IsErrUserNotExist(err) {
  578. ctx.NotFound("GetUserByName")
  579. } else {
  580. ctx.ServerError("GetUserByName", err)
  581. }
  582. return nil, nil, nil, nil, "", ""
  583. }
  584. headBranch = headInfos[1]
  585. } else {
  586. ctx.NotFound()
  587. return nil, nil, nil, nil, "", ""
  588. }
  589. ctx.Repo.PullRequest.SameRepo = isSameRepo
  590. log.Info("Base branch: %s", baseBranch)
  591. log.Info("Repo path: %s", ctx.Repo.GitRepo.Path)
  592. // Check if base branch is valid.
  593. if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) {
  594. ctx.NotFound("IsBranchExist")
  595. return nil, nil, nil, nil, "", ""
  596. }
  597. // Check if current user has fork of repository or in the same repository.
  598. headRepo, has := models.HasForkedRepo(headUser.ID, baseRepo.ID)
  599. if !has && !isSameRepo {
  600. log.Trace("parseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID)
  601. ctx.NotFound("HasForkedRepo")
  602. return nil, nil, nil, nil, "", ""
  603. }
  604. var headGitRepo *git.Repository
  605. if isSameRepo {
  606. headRepo = ctx.Repo.Repository
  607. headGitRepo = ctx.Repo.GitRepo
  608. } else {
  609. headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name))
  610. if err != nil {
  611. ctx.Error(500, "OpenRepository", err)
  612. return nil, nil, nil, nil, "", ""
  613. }
  614. }
  615. // user should have permission to read baseRepo's codes and pulls, NOT headRepo's
  616. permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
  617. if err != nil {
  618. ctx.ServerError("GetUserRepoPermission", err)
  619. return nil, nil, nil, nil, "", ""
  620. }
  621. if !permBase.CanReadIssuesOrPulls(true) || !permBase.CanRead(models.UnitTypeCode) {
  622. if log.IsTrace() {
  623. log.Trace("Permission Denied: User %-v cannot create/read pull requests or cannot read code in Repo %-v\nUser in baseRepo has Permissions: %-+v",
  624. ctx.User,
  625. baseRepo,
  626. permBase)
  627. }
  628. ctx.NotFound("Can't read pulls or can't read UnitTypeCode")
  629. return nil, nil, nil, nil, "", ""
  630. }
  631. // user should have permission to read headrepo's codes
  632. permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
  633. if err != nil {
  634. ctx.ServerError("GetUserRepoPermission", err)
  635. return nil, nil, nil, nil, "", ""
  636. }
  637. if !permHead.CanRead(models.UnitTypeCode) {
  638. if log.IsTrace() {
  639. log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
  640. ctx.User,
  641. headRepo,
  642. permHead)
  643. }
  644. ctx.NotFound("Can't read headRepo UnitTypeCode")
  645. return nil, nil, nil, nil, "", ""
  646. }
  647. // Check if head branch is valid.
  648. if !headGitRepo.IsBranchExist(headBranch) {
  649. ctx.NotFound()
  650. return nil, nil, nil, nil, "", ""
  651. }
  652. compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch)
  653. if err != nil {
  654. ctx.Error(500, "GetCompareInfo", err)
  655. return nil, nil, nil, nil, "", ""
  656. }
  657. return headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch
  658. }