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

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