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.

124 lines
2.8 KiB

  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 git
  5. import (
  6. "errors"
  7. "io/ioutil"
  8. "os"
  9. "path"
  10. "strings"
  11. "github.com/Unknwon/com"
  12. )
  13. // hookNames is a list of Git server hooks' name that are supported.
  14. var hookNames = []string{
  15. "pre-receive",
  16. // "update",
  17. "post-receive",
  18. }
  19. var (
  20. // ErrNotValidHook error when a git hook is not valid
  21. ErrNotValidHook = errors.New("not a valid Git hook")
  22. )
  23. // IsValidHookName returns true if given name is a valid Git hook.
  24. func IsValidHookName(name string) bool {
  25. for _, hn := range hookNames {
  26. if hn == name {
  27. return true
  28. }
  29. }
  30. return false
  31. }
  32. // Hook represents a Git hook.
  33. type Hook struct {
  34. name string
  35. IsActive bool // Indicates whether repository has this hook.
  36. Content string // Content of hook if it's active.
  37. Sample string // Sample content from Git.
  38. path string // Hook file path.
  39. }
  40. // GetHook returns a Git hook by given name and repository.
  41. func GetHook(repoPath, name string) (*Hook, error) {
  42. if !IsValidHookName(name) {
  43. return nil, ErrNotValidHook
  44. }
  45. h := &Hook{
  46. name: name,
  47. path: path.Join(repoPath, "hooks", name),
  48. }
  49. if isFile(h.path) {
  50. data, err := ioutil.ReadFile(h.path)
  51. if err != nil {
  52. return nil, err
  53. }
  54. h.IsActive = true
  55. h.Content = string(data)
  56. } else if isFile(h.path + ".sample") {
  57. data, err := ioutil.ReadFile(h.path + ".sample")
  58. if err != nil {
  59. return nil, err
  60. }
  61. h.Sample = string(data)
  62. }
  63. return h, nil
  64. }
  65. // Name return the name of the hook
  66. func (h *Hook) Name() string {
  67. return h.name
  68. }
  69. // Update updates hook settings.
  70. func (h *Hook) Update() error {
  71. if len(strings.TrimSpace(h.Content)) == 0 {
  72. if isExist(h.path) {
  73. return os.Remove(h.path)
  74. }
  75. return nil
  76. }
  77. return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
  78. }
  79. // ListHooks returns a list of Git hooks of given repository.
  80. func ListHooks(repoPath string) (_ []*Hook, err error) {
  81. if !isDir(path.Join(repoPath, "hooks")) {
  82. return nil, errors.New("hooks path does not exist")
  83. }
  84. hooks := make([]*Hook, len(hookNames))
  85. for i, name := range hookNames {
  86. hooks[i], err = GetHook(repoPath, name)
  87. if err != nil {
  88. return nil, err
  89. }
  90. }
  91. return hooks, nil
  92. }
  93. const (
  94. // HookPathUpdate hook update path
  95. HookPathUpdate = "hooks/update"
  96. )
  97. // SetUpdateHook writes given content to update hook of the reposiotry.
  98. func SetUpdateHook(repoPath, content string) (err error) {
  99. log("Setting update hook: %s", repoPath)
  100. hookPath := path.Join(repoPath, HookPathUpdate)
  101. if com.IsExist(hookPath) {
  102. err = os.Remove(hookPath)
  103. } else {
  104. err = os.MkdirAll(path.Dir(hookPath), os.ModePerm)
  105. }
  106. if err != nil {
  107. return err
  108. }
  109. return ioutil.WriteFile(hookPath, []byte(content), 0777)
  110. }