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 19 kB

11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. // Copyright 2014 The Gogs 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. "container/list"
  7. "path"
  8. "strings"
  9. "github.com/Unknwon/com"
  10. "github.com/gogits/git-module"
  11. "github.com/gogits/gogs/models"
  12. "github.com/gogits/gogs/modules/auth"
  13. "github.com/gogits/gogs/modules/base"
  14. "github.com/gogits/gogs/modules/context"
  15. "github.com/gogits/gogs/modules/log"
  16. "github.com/gogits/gogs/modules/setting"
  17. )
  18. const (
  19. FORK base.TplName = "repo/pulls/fork"
  20. COMPARE_PULL base.TplName = "repo/pulls/compare"
  21. PULL_COMMITS base.TplName = "repo/pulls/commits"
  22. PULL_FILES base.TplName = "repo/pulls/files"
  23. PULL_REQUEST_TEMPLATE_KEY = "PullRequestTemplate"
  24. )
  25. var (
  26. PullRequestTemplateCandidates = []string{
  27. "PULL_REQUEST.md",
  28. ".gogs/PULL_REQUEST.md",
  29. ".github/PULL_REQUEST.md",
  30. }
  31. )
  32. func getForkRepository(ctx *context.Context) *models.Repository {
  33. forkRepo, err := models.GetRepositoryByID(ctx.ParamsInt64(":repoid"))
  34. if err != nil {
  35. if models.IsErrRepoNotExist(err) {
  36. ctx.Handle(404, "GetRepositoryByID", nil)
  37. } else {
  38. ctx.Handle(500, "GetRepositoryByID", err)
  39. }
  40. return nil
  41. }
  42. if !forkRepo.CanBeForked() {
  43. ctx.Handle(404, "getForkRepository", nil)
  44. return nil
  45. }
  46. ctx.Data["repo_name"] = forkRepo.Name
  47. ctx.Data["description"] = forkRepo.Description
  48. ctx.Data["IsPrivate"] = forkRepo.IsPrivate
  49. if err = forkRepo.GetOwner(); err != nil {
  50. ctx.Handle(500, "GetOwner", err)
  51. return nil
  52. }
  53. ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
  54. if err := ctx.User.GetOrganizations(true); err != nil {
  55. ctx.Handle(500, "GetOrganizations", err)
  56. return nil
  57. }
  58. ctx.Data["Orgs"] = ctx.User.Orgs
  59. return forkRepo
  60. }
  61. func Fork(ctx *context.Context) {
  62. ctx.Data["Title"] = ctx.Tr("new_fork")
  63. getForkRepository(ctx)
  64. if ctx.Written() {
  65. return
  66. }
  67. ctx.Data["ContextUser"] = ctx.User
  68. ctx.HTML(200, FORK)
  69. }
  70. func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
  71. ctx.Data["Title"] = ctx.Tr("new_fork")
  72. forkRepo := getForkRepository(ctx)
  73. if ctx.Written() {
  74. return
  75. }
  76. ctxUser := checkContextUser(ctx, form.Uid)
  77. if ctx.Written() {
  78. return
  79. }
  80. ctx.Data["ContextUser"] = ctxUser
  81. if ctx.HasError() {
  82. ctx.HTML(200, FORK)
  83. return
  84. }
  85. repo, has := models.HasForkedRepo(ctxUser.Id, forkRepo.ID)
  86. if has {
  87. ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
  88. return
  89. }
  90. // Check ownership of organization.
  91. if ctxUser.IsOrganization() {
  92. if !ctxUser.IsOwnedBy(ctx.User.Id) {
  93. ctx.Error(403)
  94. return
  95. }
  96. }
  97. repo, err := models.ForkRepository(ctxUser, forkRepo, form.RepoName, form.Description)
  98. if err != nil {
  99. ctx.Data["Err_RepoName"] = true
  100. switch {
  101. case models.IsErrRepoAlreadyExist(err):
  102. ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), FORK, &form)
  103. case models.IsErrNameReserved(err):
  104. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), FORK, &form)
  105. case models.IsErrNamePatternNotAllowed(err):
  106. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), FORK, &form)
  107. default:
  108. ctx.Handle(500, "ForkPost", err)
  109. }
  110. return
  111. }
  112. log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name)
  113. ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
  114. }
  115. func checkPullInfo(ctx *context.Context) *models.Issue {
  116. issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  117. if err != nil {
  118. if models.IsErrIssueNotExist(err) {
  119. ctx.Handle(404, "GetIssueByIndex", err)
  120. } else {
  121. ctx.Handle(500, "GetIssueByIndex", err)
  122. }
  123. return nil
  124. }
  125. ctx.Data["Title"] = issue.Name
  126. ctx.Data["Issue"] = issue
  127. if !issue.IsPull {
  128. ctx.Handle(404, "ViewPullCommits", nil)
  129. return nil
  130. }
  131. if err = issue.GetPullRequest(); err != nil {
  132. ctx.Handle(500, "GetPullRequest", err)
  133. return nil
  134. } else if err = issue.GetHeadRepo(); err != nil {
  135. ctx.Handle(500, "GetHeadRepo", err)
  136. return nil
  137. }
  138. if ctx.IsSigned {
  139. // Update issue-user.
  140. if err = issue.ReadBy(ctx.User.Id); err != nil {
  141. ctx.Handle(500, "ReadBy", err)
  142. return nil
  143. }
  144. }
  145. return issue
  146. }
  147. func PrepareMergedViewPullInfo(ctx *context.Context, pull *models.Issue) {
  148. ctx.Data["HasMerged"] = true
  149. var err error
  150. if err = pull.GetMerger(); err != nil {
  151. ctx.Handle(500, "GetMerger", err)
  152. return
  153. }
  154. ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch
  155. ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch
  156. ctx.Data["NumCommits"], err = ctx.Repo.GitRepo.CommitsCountBetween(pull.MergeBase, pull.MergedCommitID)
  157. if err != nil {
  158. ctx.Handle(500, "Repo.GitRepo.CommitsCountBetween", err)
  159. return
  160. }
  161. ctx.Data["NumFiles"], err = ctx.Repo.GitRepo.FilesCountBetween(pull.MergeBase, pull.MergedCommitID)
  162. if err != nil {
  163. ctx.Handle(500, "Repo.GitRepo.FilesCountBetween", err)
  164. return
  165. }
  166. }
  167. func PrepareViewPullInfo(ctx *context.Context, pull *models.Issue) *git.PullRequestInfo {
  168. repo := ctx.Repo.Repository
  169. ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch
  170. ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch
  171. var (
  172. headGitRepo *git.Repository
  173. err error
  174. )
  175. if err = pull.GetHeadRepo(); err != nil {
  176. ctx.Handle(500, "GetHeadRepo", err)
  177. return nil
  178. }
  179. if pull.HeadRepo != nil {
  180. headGitRepo, err = git.OpenRepository(pull.HeadRepo.RepoPath())
  181. if err != nil {
  182. ctx.Handle(500, "OpenRepository", err)
  183. return nil
  184. }
  185. }
  186. if pull.HeadRepo == nil || !headGitRepo.IsBranchExist(pull.HeadBranch) {
  187. ctx.Data["IsPullReuqestBroken"] = true
  188. ctx.Data["HeadTarget"] = "deleted"
  189. ctx.Data["NumCommits"] = 0
  190. ctx.Data["NumFiles"] = 0
  191. return nil
  192. }
  193. prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(repo.Owner.Name, repo.Name),
  194. pull.BaseBranch, pull.HeadBranch)
  195. if err != nil {
  196. ctx.Handle(500, "GetPullRequestInfo", err)
  197. return nil
  198. }
  199. ctx.Data["NumCommits"] = prInfo.Commits.Len()
  200. ctx.Data["NumFiles"] = prInfo.NumFiles
  201. return prInfo
  202. }
  203. func ViewPullCommits(ctx *context.Context) {
  204. ctx.Data["PageIsPullCommits"] = true
  205. pull := checkPullInfo(ctx)
  206. if ctx.Written() {
  207. return
  208. }
  209. ctx.Data["Username"] = pull.HeadUserName
  210. ctx.Data["Reponame"] = pull.HeadRepo.Name
  211. var commits *list.List
  212. if pull.HasMerged {
  213. PrepareMergedViewPullInfo(ctx, pull)
  214. if ctx.Written() {
  215. return
  216. }
  217. startCommit, err := ctx.Repo.GitRepo.GetCommit(pull.MergeBase)
  218. if err != nil {
  219. ctx.Handle(500, "Repo.GitRepo.GetCommit", err)
  220. return
  221. }
  222. endCommit, err := ctx.Repo.GitRepo.GetCommit(pull.MergedCommitID)
  223. if err != nil {
  224. ctx.Handle(500, "Repo.GitRepo.GetCommit", err)
  225. return
  226. }
  227. commits, err = ctx.Repo.GitRepo.CommitsBetween(endCommit, startCommit)
  228. if err != nil {
  229. ctx.Handle(500, "Repo.GitRepo.CommitsBetween", err)
  230. return
  231. }
  232. } else {
  233. prInfo := PrepareViewPullInfo(ctx, pull)
  234. if ctx.Written() {
  235. return
  236. } else if prInfo == nil {
  237. ctx.Handle(404, "ViewPullCommits", nil)
  238. return
  239. }
  240. commits = prInfo.Commits
  241. }
  242. commits = models.ValidateCommitsWithEmails(commits)
  243. ctx.Data["Commits"] = commits
  244. ctx.Data["CommitCount"] = commits.Len()
  245. ctx.HTML(200, PULL_COMMITS)
  246. }
  247. func ViewPullFiles(ctx *context.Context) {
  248. ctx.Data["PageIsPullFiles"] = true
  249. pull := checkPullInfo(ctx)
  250. if ctx.Written() {
  251. return
  252. }
  253. var (
  254. diffRepoPath string
  255. startCommitID string
  256. endCommitID string
  257. gitRepo *git.Repository
  258. )
  259. if pull.HasMerged {
  260. PrepareMergedViewPullInfo(ctx, pull)
  261. if ctx.Written() {
  262. return
  263. }
  264. diffRepoPath = ctx.Repo.GitRepo.Path
  265. startCommitID = pull.MergeBase
  266. endCommitID = pull.MergedCommitID
  267. gitRepo = ctx.Repo.GitRepo
  268. } else {
  269. prInfo := PrepareViewPullInfo(ctx, pull)
  270. if ctx.Written() {
  271. return
  272. } else if prInfo == nil {
  273. ctx.Handle(404, "ViewPullFiles", nil)
  274. return
  275. }
  276. headRepoPath := models.RepoPath(pull.HeadUserName, pull.HeadRepo.Name)
  277. headGitRepo, err := git.OpenRepository(headRepoPath)
  278. if err != nil {
  279. ctx.Handle(500, "OpenRepository", err)
  280. return
  281. }
  282. headCommitID, err := headGitRepo.GetBranchCommitID(pull.HeadBranch)
  283. if err != nil {
  284. ctx.Handle(500, "GetBranchCommitID", err)
  285. return
  286. }
  287. diffRepoPath = headRepoPath
  288. startCommitID = prInfo.MergeBase
  289. endCommitID = headCommitID
  290. gitRepo = headGitRepo
  291. }
  292. diff, err := models.GetDiffRange(diffRepoPath,
  293. startCommitID, endCommitID, setting.Git.MaxGitDiffLines)
  294. if err != nil {
  295. ctx.Handle(500, "GetDiffRange", err)
  296. return
  297. }
  298. ctx.Data["Diff"] = diff
  299. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  300. commit, err := gitRepo.GetCommit(endCommitID)
  301. if err != nil {
  302. ctx.Handle(500, "GetCommit", err)
  303. return
  304. }
  305. headTarget := path.Join(pull.HeadUserName, pull.HeadRepo.Name)
  306. ctx.Data["Username"] = pull.HeadUserName
  307. ctx.Data["Reponame"] = pull.HeadRepo.Name
  308. ctx.Data["IsImageFile"] = commit.IsImageFile
  309. ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "src", endCommitID)
  310. ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "src", startCommitID)
  311. ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "raw", endCommitID)
  312. ctx.Data["RequireHighlightJS"] = true
  313. ctx.HTML(200, PULL_FILES)
  314. }
  315. func MergePullRequest(ctx *context.Context) {
  316. issue := checkPullInfo(ctx)
  317. if ctx.Written() {
  318. return
  319. }
  320. if issue.IsClosed {
  321. ctx.Handle(404, "MergePullRequest", nil)
  322. return
  323. }
  324. pr, err := models.GetPullRequestByIssueID(issue.ID)
  325. if err != nil {
  326. if models.IsErrPullRequestNotExist(err) {
  327. ctx.Handle(404, "GetPullRequestByIssueID", nil)
  328. } else {
  329. ctx.Handle(500, "GetPullRequestByIssueID", err)
  330. }
  331. return
  332. }
  333. if !pr.CanAutoMerge() || pr.HasMerged {
  334. ctx.Handle(404, "MergePullRequest", nil)
  335. return
  336. }
  337. pr.Issue = issue
  338. pr.Issue.Repo = ctx.Repo.Repository
  339. if err = pr.Merge(ctx.User, ctx.Repo.GitRepo); err != nil {
  340. ctx.Handle(500, "Merge", err)
  341. return
  342. }
  343. log.Trace("Pull request merged: %d", pr.ID)
  344. ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
  345. }
  346. func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) {
  347. baseRepo := ctx.Repo.Repository
  348. // Get compared branches information
  349. // format: <base branch>...[<head repo>:]<head branch>
  350. // base<-head: master...head:feature
  351. // same repo: master...feature
  352. infos := strings.Split(ctx.Params("*"), "...")
  353. if len(infos) != 2 {
  354. log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos)
  355. ctx.Handle(404, "CompareAndPullRequest", nil)
  356. return nil, nil, nil, nil, "", ""
  357. }
  358. baseBranch := infos[0]
  359. ctx.Data["BaseBranch"] = baseBranch
  360. var (
  361. headUser *models.User
  362. headBranch string
  363. isSameRepo bool
  364. err error
  365. )
  366. // If there is no head repository, it means pull request between same repository.
  367. headInfos := strings.Split(infos[1], ":")
  368. if len(headInfos) == 1 {
  369. isSameRepo = true
  370. headUser = ctx.Repo.Owner
  371. headBranch = headInfos[0]
  372. } else if len(headInfos) == 2 {
  373. headUser, err = models.GetUserByName(headInfos[0])
  374. if err != nil {
  375. if models.IsErrUserNotExist(err) {
  376. ctx.Handle(404, "GetUserByName", nil)
  377. } else {
  378. ctx.Handle(500, "GetUserByName", err)
  379. }
  380. return nil, nil, nil, nil, "", ""
  381. }
  382. headBranch = headInfos[1]
  383. } else {
  384. ctx.Handle(404, "CompareAndPullRequest", nil)
  385. return nil, nil, nil, nil, "", ""
  386. }
  387. ctx.Data["HeadUser"] = headUser
  388. ctx.Data["HeadBranch"] = headBranch
  389. ctx.Repo.PullRequest.SameRepo = isSameRepo
  390. // Check if base branch is valid.
  391. if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) {
  392. ctx.Handle(404, "IsBranchExist", nil)
  393. return nil, nil, nil, nil, "", ""
  394. }
  395. // Check if current user has fork of repository or in the same repository.
  396. headRepo, has := models.HasForkedRepo(headUser.Id, baseRepo.ID)
  397. if !has && !isSameRepo {
  398. log.Trace("ParseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID)
  399. ctx.Handle(404, "ParseCompareInfo", nil)
  400. return nil, nil, nil, nil, "", ""
  401. }
  402. var headGitRepo *git.Repository
  403. if isSameRepo {
  404. headRepo = ctx.Repo.Repository
  405. headGitRepo = ctx.Repo.GitRepo
  406. } else {
  407. headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name))
  408. if err != nil {
  409. ctx.Handle(500, "OpenRepository", err)
  410. return nil, nil, nil, nil, "", ""
  411. }
  412. }
  413. if !ctx.User.IsWriterOfRepo(headRepo) && !ctx.User.IsAdmin {
  414. log.Trace("ParseCompareInfo[%d]: does not have write access or site admin", baseRepo.ID)
  415. ctx.Handle(404, "ParseCompareInfo", nil)
  416. return nil, nil, nil, nil, "", ""
  417. }
  418. // Check if head branch is valid.
  419. if !headGitRepo.IsBranchExist(headBranch) {
  420. ctx.Handle(404, "IsBranchExist", nil)
  421. return nil, nil, nil, nil, "", ""
  422. }
  423. headBranches, err := headGitRepo.GetBranches()
  424. if err != nil {
  425. ctx.Handle(500, "GetBranches", err)
  426. return nil, nil, nil, nil, "", ""
  427. }
  428. ctx.Data["HeadBranches"] = headBranches
  429. prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch)
  430. if err != nil {
  431. ctx.Handle(500, "GetPullRequestInfo", err)
  432. return nil, nil, nil, nil, "", ""
  433. }
  434. ctx.Data["BeforeCommitID"] = prInfo.MergeBase
  435. return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch
  436. }
  437. func PrepareCompareDiff(
  438. ctx *context.Context,
  439. headUser *models.User,
  440. headRepo *models.Repository,
  441. headGitRepo *git.Repository,
  442. prInfo *git.PullRequestInfo,
  443. baseBranch, headBranch string) bool {
  444. var (
  445. repo = ctx.Repo.Repository
  446. err error
  447. )
  448. // Get diff information.
  449. ctx.Data["CommitRepoLink"] = headRepo.RepoLink()
  450. headCommitID, err := headGitRepo.GetBranchCommitID(headBranch)
  451. if err != nil {
  452. ctx.Handle(500, "GetBranchCommitID", err)
  453. return false
  454. }
  455. ctx.Data["AfterCommitID"] = headCommitID
  456. if headCommitID == prInfo.MergeBase {
  457. ctx.Data["IsNothingToCompare"] = true
  458. return true
  459. }
  460. diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name),
  461. prInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines)
  462. if err != nil {
  463. ctx.Handle(500, "GetDiffRange", err)
  464. return false
  465. }
  466. ctx.Data["Diff"] = diff
  467. ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
  468. headCommit, err := headGitRepo.GetCommit(headCommitID)
  469. if err != nil {
  470. ctx.Handle(500, "GetCommit", err)
  471. return false
  472. }
  473. prInfo.Commits = models.ValidateCommitsWithEmails(prInfo.Commits)
  474. ctx.Data["Commits"] = prInfo.Commits
  475. ctx.Data["CommitCount"] = prInfo.Commits.Len()
  476. ctx.Data["Username"] = headUser.Name
  477. ctx.Data["Reponame"] = headRepo.Name
  478. ctx.Data["IsImageFile"] = headCommit.IsImageFile
  479. headTarget := path.Join(headUser.Name, repo.Name)
  480. ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "src", headCommitID)
  481. ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "src", prInfo.MergeBase)
  482. ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(headTarget, "raw", headCommitID)
  483. return false
  484. }
  485. func CompareAndPullRequest(ctx *context.Context) {
  486. ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes")
  487. ctx.Data["PageIsComparePull"] = true
  488. ctx.Data["IsDiffCompare"] = true
  489. ctx.Data["RequireHighlightJS"] = true
  490. setTemplateIfExists(ctx, PULL_REQUEST_TEMPLATE_KEY, PullRequestTemplateCandidates)
  491. renderAttachmentSettings(ctx)
  492. headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(ctx)
  493. if ctx.Written() {
  494. return
  495. }
  496. pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch)
  497. if err != nil {
  498. if !models.IsErrPullRequestNotExist(err) {
  499. ctx.Handle(500, "GetUnmergedPullRequest", err)
  500. return
  501. }
  502. } else {
  503. ctx.Data["HasPullRequest"] = true
  504. ctx.Data["PullRequest"] = pr
  505. ctx.HTML(200, COMPARE_PULL)
  506. return
  507. }
  508. nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch)
  509. if ctx.Written() {
  510. return
  511. }
  512. if !nothingToCompare {
  513. // Setup information for new form.
  514. RetrieveRepoMetas(ctx, ctx.Repo.Repository)
  515. if ctx.Written() {
  516. return
  517. }
  518. }
  519. ctx.HTML(200, COMPARE_PULL)
  520. }
  521. func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) {
  522. ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes")
  523. ctx.Data["PageIsComparePull"] = true
  524. ctx.Data["IsDiffCompare"] = true
  525. renderAttachmentSettings(ctx)
  526. var (
  527. repo = ctx.Repo.Repository
  528. attachments []string
  529. )
  530. headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(ctx)
  531. if ctx.Written() {
  532. return
  533. }
  534. patch, err := headGitRepo.GetPatch(prInfo.MergeBase, headBranch)
  535. if err != nil {
  536. ctx.Handle(500, "GetPatch", err)
  537. return
  538. }
  539. labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form)
  540. if ctx.Written() {
  541. return
  542. }
  543. if setting.AttachmentEnabled {
  544. attachments = form.Attachments
  545. }
  546. if ctx.HasError() {
  547. ctx.HTML(200, COMPARE_PULL)
  548. return
  549. }
  550. pullIssue := &models.Issue{
  551. RepoID: repo.ID,
  552. Index: repo.NextIssueIndex(),
  553. Name: form.Title,
  554. PosterID: ctx.User.Id,
  555. Poster: ctx.User,
  556. MilestoneID: milestoneID,
  557. AssigneeID: assigneeID,
  558. IsPull: true,
  559. Content: form.Content,
  560. }
  561. pullRequest := &models.PullRequest{
  562. HeadRepoID: headRepo.ID,
  563. BaseRepoID: repo.ID,
  564. HeadUserName: headUser.Name,
  565. HeadBranch: headBranch,
  566. BaseBranch: baseBranch,
  567. HeadRepo: headRepo,
  568. BaseRepo: repo,
  569. MergeBase: prInfo.MergeBase,
  570. Type: models.PULL_REQUEST_GOGS,
  571. }
  572. if err := models.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil {
  573. ctx.Handle(500, "NewPullRequest", err)
  574. return
  575. } else if err := pullRequest.PushToBaseRepo(); err != nil {
  576. ctx.Handle(500, "PushToBaseRepo", err)
  577. return
  578. } else if err := MailWatchersAndMentions(ctx, pullIssue); err != nil {
  579. ctx.Handle(500, "MailWatchersAndMentions", err)
  580. return
  581. }
  582. log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID)
  583. ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index))
  584. }
  585. func TriggerTask(ctx *context.Context) {
  586. branch := ctx.Query("branch")
  587. secret := ctx.Query("secret")
  588. if len(branch) == 0 || len(secret) == 0 {
  589. ctx.Error(404)
  590. log.Trace("TriggerTask: branch or secret is empty")
  591. return
  592. }
  593. owner, repo := parseOwnerAndRepo(ctx)
  594. if ctx.Written() {
  595. return
  596. }
  597. if secret != base.EncodeMD5(owner.Salt) {
  598. ctx.Error(404)
  599. log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name)
  600. return
  601. }
  602. log.Trace("TriggerTask [%d].(new request): %s", repo.ID, branch)
  603. go models.HookQueue.Add(repo.ID)
  604. go models.AddTestPullRequestTask(repo.ID, branch)
  605. ctx.Status(202)
  606. }