hook.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 cmd
  5. import (
  6. "bufio"
  7. "bytes"
  8. "os"
  9. "os/exec"
  10. "path/filepath"
  11. "github.com/Unknwon/com"
  12. "github.com/urfave/cli"
  13. "github.com/gogits/gogs/models"
  14. )
  15. var (
  16. CmdHook = cli.Command{
  17. Name: "hook",
  18. Usage: "Delegate commands to corresponding Git hooks",
  19. Description: "All sub-commands should only be called by Git",
  20. Flags: []cli.Flag{
  21. stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
  22. },
  23. Subcommands: []cli.Command{
  24. subcmdHookPreReceive,
  25. subcmdHookUpadte,
  26. subcmdHookPostReceive,
  27. },
  28. }
  29. subcmdHookPreReceive = cli.Command{
  30. Name: "pre-receive",
  31. Usage: "Delegate pre-receive Git hook",
  32. Description: "This command should only be called by Git",
  33. Action: runHookPreReceive,
  34. }
  35. subcmdHookUpadte = cli.Command{
  36. Name: "update",
  37. Usage: "Delegate update Git hook",
  38. Description: "This command should only be called by Git",
  39. Action: runHookUpdate,
  40. }
  41. subcmdHookPostReceive = cli.Command{
  42. Name: "post-receive",
  43. Usage: "Delegate post-receive Git hook",
  44. Description: "This command should only be called by Git",
  45. Action: runHookPostReceive,
  46. }
  47. )
  48. func runHookPreReceive(c *cli.Context) error {
  49. if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
  50. return nil
  51. }
  52. setup(c, "hooks/pre-receive.log")
  53. buf := bytes.NewBuffer(nil)
  54. scanner := bufio.NewScanner(os.Stdin)
  55. for scanner.Scan() {
  56. buf.Write(scanner.Bytes())
  57. buf.WriteByte('\n')
  58. }
  59. customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
  60. if !com.IsFile(customHooksPath) {
  61. return nil
  62. }
  63. hookCmd := exec.Command(filepath.Join(customHooksPath, "pre-receive"))
  64. hookCmd.Stdout = os.Stdout
  65. hookCmd.Stdin = buf
  66. hookCmd.Stderr = os.Stderr
  67. if err := hookCmd.Run(); err != nil {
  68. fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
  69. }
  70. return nil
  71. }
  72. func runHookUpdate(c *cli.Context) error {
  73. if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
  74. return nil
  75. }
  76. setup(c, "hooks/update.log")
  77. args := c.Args()
  78. if len(args) != 3 {
  79. fail("Arguments received are not equal to three", "Arguments received are not equal to three")
  80. } else if len(args[0]) == 0 {
  81. fail("First argument 'refName' is empty", "First argument 'refName' is empty")
  82. }
  83. uuid := os.Getenv(_ENV_UPDATE_TASK_UUID)
  84. if err := models.AddUpdateTask(&models.UpdateTask{
  85. UUID: uuid,
  86. RefName: args[0],
  87. OldCommitID: args[1],
  88. NewCommitID: args[2],
  89. }); err != nil {
  90. fail("Internal error", "Fail to add update task '%s': %v", uuid, err)
  91. }
  92. customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
  93. if !com.IsFile(customHooksPath) {
  94. return nil
  95. }
  96. hookCmd := exec.Command(filepath.Join(customHooksPath, "update"), args...)
  97. hookCmd.Stdout = os.Stdout
  98. hookCmd.Stdin = os.Stdin
  99. hookCmd.Stderr = os.Stderr
  100. if err := hookCmd.Run(); err != nil {
  101. fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
  102. }
  103. return nil
  104. }
  105. func runHookPostReceive(c *cli.Context) error {
  106. if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
  107. return nil
  108. }
  109. setup(c, "hooks/post-receive.log")
  110. customHooksPath := os.Getenv(_ENV_REPO_CUSTOM_HOOKS_PATH)
  111. if !com.IsFile(customHooksPath) {
  112. return nil
  113. }
  114. hookCmd := exec.Command(filepath.Join(customHooksPath, "post-receive"))
  115. hookCmd.Stdout = os.Stdout
  116. hookCmd.Stdin = os.Stdin
  117. hookCmd.Stderr = os.Stderr
  118. if err := hookCmd.Run(); err != nil {
  119. fail("Internal error", "Fail to execute custom post-receive hook: %v", err)
  120. }
  121. return nil
  122. }