gitea源码

hook.go 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2021 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package git
  5. import (
  6. "errors"
  7. "os"
  8. "path/filepath"
  9. "slices"
  10. "strings"
  11. "code.gitea.io/gitea/modules/util"
  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. // ErrNotValidHook error when a git hook is not valid
  20. var ErrNotValidHook = errors.New("not a valid Git hook")
  21. // IsValidHookName returns true if given name is a valid Git hook.
  22. func IsValidHookName(name string) bool {
  23. return slices.Contains(hookNames, name)
  24. }
  25. // Hook represents a Git hook.
  26. type Hook struct {
  27. name string
  28. IsActive bool // Indicates whether repository has this hook.
  29. Content string // Content of hook if it's active.
  30. Sample string // Sample content from Git.
  31. path string // Hook file path.
  32. }
  33. // GetHook returns a Git hook by given name and repository.
  34. func GetHook(repoPath, name string) (*Hook, error) {
  35. if !IsValidHookName(name) {
  36. return nil, ErrNotValidHook
  37. }
  38. h := &Hook{
  39. name: name,
  40. path: filepath.Join(repoPath, "hooks", name+".d", name),
  41. }
  42. isFile, err := util.IsFile(h.path)
  43. if err != nil {
  44. return nil, err
  45. }
  46. if isFile {
  47. data, err := os.ReadFile(h.path)
  48. if err != nil {
  49. return nil, err
  50. }
  51. h.IsActive = true
  52. h.Content = string(data)
  53. return h, nil
  54. }
  55. samplePath := filepath.Join(repoPath, "hooks", name+".sample")
  56. isFile, err = util.IsFile(samplePath)
  57. if err != nil {
  58. return nil, err
  59. }
  60. if isFile {
  61. data, err := os.ReadFile(samplePath)
  62. if err != nil {
  63. return nil, err
  64. }
  65. h.Sample = string(data)
  66. }
  67. return h, nil
  68. }
  69. // Name return the name of the hook
  70. func (h *Hook) Name() string {
  71. return h.name
  72. }
  73. // Update updates hook settings.
  74. func (h *Hook) Update() error {
  75. if len(strings.TrimSpace(h.Content)) == 0 {
  76. exist, err := util.IsExist(h.path)
  77. if err != nil {
  78. return err
  79. }
  80. if exist {
  81. err := util.Remove(h.path)
  82. if err != nil {
  83. return err
  84. }
  85. }
  86. h.IsActive = false
  87. return nil
  88. }
  89. d := filepath.Dir(h.path)
  90. if err := os.MkdirAll(d, os.ModePerm); err != nil {
  91. return err
  92. }
  93. err := os.WriteFile(h.path, []byte(strings.ReplaceAll(h.Content, "\r", "")), os.ModePerm)
  94. if err != nil {
  95. return err
  96. }
  97. h.IsActive = true
  98. return nil
  99. }
  100. // ListHooks returns a list of Git hooks of given repository.
  101. func ListHooks(repoPath string) (_ []*Hook, err error) {
  102. exist, err := util.IsDir(filepath.Join(repoPath, "hooks"))
  103. if err != nil {
  104. return nil, err
  105. } else if !exist {
  106. return nil, errors.New("hooks path does not exist")
  107. }
  108. hooks := make([]*Hook, len(hookNames))
  109. for i, name := range hookNames {
  110. hooks[i], err = GetHook(repoPath, name)
  111. if err != nil {
  112. return nil, err
  113. }
  114. }
  115. return hooks, nil
  116. }