gitea源码

utils.go 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package git
  4. import (
  5. "crypto/sha1"
  6. "encoding/hex"
  7. "io"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "code.gitea.io/gitea/modules/util"
  12. )
  13. // ObjectCache provides thread-safe cache operations.
  14. type ObjectCache[T any] struct {
  15. lock sync.RWMutex
  16. cache map[string]T
  17. }
  18. func newObjectCache[T any]() *ObjectCache[T] {
  19. return &ObjectCache[T]{cache: make(map[string]T, 10)}
  20. }
  21. // Set adds obj to cache
  22. func (oc *ObjectCache[T]) Set(id string, obj T) {
  23. oc.lock.Lock()
  24. defer oc.lock.Unlock()
  25. oc.cache[id] = obj
  26. }
  27. // Get gets cached obj by id
  28. func (oc *ObjectCache[T]) Get(id string) (T, bool) {
  29. oc.lock.RLock()
  30. defer oc.lock.RUnlock()
  31. obj, has := oc.cache[id]
  32. return obj, has
  33. }
  34. // ParseBool returns the boolean value represented by the string as per git's git_config_bool
  35. // true will be returned for the result if the string is empty, but valid will be false.
  36. // "true", "yes", "on" are all true, true
  37. // "false", "no", "off" are all false, true
  38. // 0 is false, true
  39. // Any other integer is true, true
  40. // Anything else will return false, false
  41. func ParseBool(value string) (result, valid bool) {
  42. // Empty strings are true but invalid
  43. if len(value) == 0 {
  44. return true, false
  45. }
  46. // These are the git expected true and false values
  47. if strings.EqualFold(value, "true") || strings.EqualFold(value, "yes") || strings.EqualFold(value, "on") {
  48. return true, true
  49. }
  50. if strings.EqualFold(value, "false") || strings.EqualFold(value, "no") || strings.EqualFold(value, "off") {
  51. return false, true
  52. }
  53. // Try a number
  54. intValue, err := strconv.ParseInt(value, 10, 32)
  55. if err != nil {
  56. return false, false
  57. }
  58. return intValue != 0, true
  59. }
  60. // LimitedReaderCloser is a limited reader closer
  61. type LimitedReaderCloser struct {
  62. R io.Reader
  63. C io.Closer
  64. N int64
  65. }
  66. // Read implements io.Reader
  67. func (l *LimitedReaderCloser) Read(p []byte) (n int, err error) {
  68. if l.N <= 0 {
  69. _ = l.C.Close()
  70. return 0, io.EOF
  71. }
  72. if int64(len(p)) > l.N {
  73. p = p[0:l.N]
  74. }
  75. n, err = l.R.Read(p)
  76. l.N -= int64(n)
  77. return n, err
  78. }
  79. // Close implements io.Closer
  80. func (l *LimitedReaderCloser) Close() error {
  81. return l.C.Close()
  82. }
  83. func HashFilePathForWebUI(s string) string {
  84. h := sha1.New()
  85. _, _ = h.Write([]byte(s))
  86. return hex.EncodeToString(h.Sum(nil))
  87. }
  88. func SplitCommitTitleBody(commitMessage string, titleRuneLimit int) (title, body string) {
  89. title, body, _ = strings.Cut(commitMessage, "\n")
  90. title, title2 := util.EllipsisTruncateRunes(title, titleRuneLimit)
  91. if title2 != "" {
  92. if body == "" {
  93. body = title2
  94. } else {
  95. body = title2 + "\n" + body
  96. }
  97. }
  98. return title, body
  99. }