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

pull.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright 2015 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 cmd
  5. import (
  6. "bufio"
  7. "log"
  8. "os"
  9. "strconv"
  10. "strings"
  11. "github.com/codegangsta/cli"
  12. "github.com/gogits/git-module"
  13. "github.com/gogits/gogs/models"
  14. )
  15. var CmdPull = cli.Command{
  16. Name: "pull",
  17. Usage: "Filter commits for Pull Request actions",
  18. Description: `Checks commits for potential pull request updates and takes appropriate actions.`,
  19. Action: runPull,
  20. Flags: []cli.Flag{
  21. stringFlag("path, p", "", "repository path"),
  22. },
  23. }
  24. func runPull(ctx *cli.Context) {
  25. setup("pull.log")
  26. if !ctx.IsSet("path") {
  27. log.Fatal("Missing argument --path")
  28. }
  29. workingDirectory := ctx.String("path")
  30. // Scan standard input (stdin) for updated refs
  31. stdin := bufio.NewScanner(os.Stdin)
  32. for stdin.Scan() {
  33. // Format from post-receive is: <old-commit> <new-commit> <ref-name>
  34. args := strings.Split(stdin.Text(), " ")
  35. if len(args) < 3 {
  36. continue
  37. }
  38. refName := args[2]
  39. refSplits := strings.Split(refName, "/")
  40. if len(refSplits) < 3 {
  41. log.Fatal("Not enough elements in refs element.")
  42. }
  43. // if refSplits[1] == "pull" {
  44. // log.Fatal("Not allowed to push to \"pull\" refs. Reserved for Pull Requests.")
  45. // } else
  46. if refSplits[1] != "heads" {
  47. // Only push branches of ref "heads"
  48. continue
  49. }
  50. branch := strings.Join(refSplits[2:], "/")
  51. repoPathSplits := strings.Split(workingDirectory, string(os.PathSeparator))
  52. userName := repoPathSplits[len(repoPathSplits)-2]
  53. repoName := repoPathSplits[len(repoPathSplits)-1]
  54. repoName = repoName[0 : len(repoName)-4]
  55. pr, err := models.GetUnmergedPullRequestByRepoPathAndHeadBranch(userName, repoName, branch)
  56. if _, ok := err.(models.ErrPullRequestNotExist); ok {
  57. // Nothing to do here if the branch has no Pull Request open
  58. log.Printf("Skipping for %s/%s.git branch '%s'", userName, repoName, branch)
  59. continue
  60. } else if err != nil {
  61. log.Fatal("Database operation failed: " + err.Error())
  62. }
  63. err = pr.BaseRepo.GetOwner()
  64. if err != nil {
  65. log.Fatal("Could not get owner data: " + err.Error())
  66. }
  67. prIdStr := strconv.FormatInt(pr.ID, 10)
  68. tmpRemoteName := "tmp-pull-" + branch + "-" + prIdStr
  69. remoteUrl := "../../" + pr.BaseRepo.Owner.LowerName + "/" + pr.BaseRepo.LowerName + ".git"
  70. repo, err := git.OpenRepository(workingDirectory)
  71. repo.AddRemote(tmpRemoteName, remoteUrl, false)
  72. err = git.Push(workingDirectory, tmpRemoteName, branch+":"+"refs/pull/"+prIdStr+"/head")
  73. if err != nil {
  74. log.Fatal("Error pushing: " + err.Error())
  75. }
  76. err = repo.RemoveRemote(tmpRemoteName)
  77. if err != nil {
  78. log.Fatal("Error deleting temporary remote: " + err.Error())
  79. }
  80. }
  81. }