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

tool.go 7.7 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 base
  5. import (
  6. "bytes"
  7. "crypto/md5"
  8. "encoding/hex"
  9. "encoding/json"
  10. "fmt"
  11. "math"
  12. "strings"
  13. "time"
  14. )
  15. // Encode string to md5 hex value
  16. func EncodeMd5(str string) string {
  17. m := md5.New()
  18. m.Write([]byte(str))
  19. return hex.EncodeToString(m.Sum(nil))
  20. }
  21. // AvatarLink returns avatar link by given e-mail.
  22. func AvatarLink(email string) string {
  23. return "http://1.gravatar.com/avatar/" + EncodeMd5(email)
  24. }
  25. // Seconds-based time units
  26. const (
  27. Minute = 60
  28. Hour = 60 * Minute
  29. Day = 24 * Hour
  30. Week = 7 * Day
  31. Month = 30 * Day
  32. Year = 12 * Month
  33. )
  34. // TimeSince calculates the time interval and generate user-friendly string.
  35. func TimeSince(then time.Time) string {
  36. now := time.Now()
  37. lbl := "ago"
  38. diff := now.Unix() - then.Unix()
  39. if then.After(now) {
  40. lbl = "from now"
  41. diff = then.Unix() - now.Unix()
  42. }
  43. switch {
  44. case diff <= 0:
  45. return "now"
  46. case diff <= 2:
  47. return fmt.Sprintf("1 second %s", lbl)
  48. case diff < 1*Minute:
  49. return fmt.Sprintf("%d seconds %s", diff, lbl)
  50. case diff < 2*Minute:
  51. return fmt.Sprintf("1 minute %s", lbl)
  52. case diff < 1*Hour:
  53. return fmt.Sprintf("%d minutes %s", diff/Minute, lbl)
  54. case diff < 2*Hour:
  55. return fmt.Sprintf("1 hour %s", lbl)
  56. case diff < 1*Day:
  57. return fmt.Sprintf("%d hours %s", diff/Hour, lbl)
  58. case diff < 2*Day:
  59. return fmt.Sprintf("1 day %s", lbl)
  60. case diff < 1*Week:
  61. return fmt.Sprintf("%d days %s", diff/Day, lbl)
  62. case diff < 2*Week:
  63. return fmt.Sprintf("1 week %s", lbl)
  64. case diff < 1*Month:
  65. return fmt.Sprintf("%d weeks %s", diff/Week, lbl)
  66. case diff < 2*Month:
  67. return fmt.Sprintf("1 month %s", lbl)
  68. case diff < 1*Year:
  69. return fmt.Sprintf("%d months %s", diff/Month, lbl)
  70. case diff < 18*Month:
  71. return fmt.Sprintf("1 year %s", lbl)
  72. }
  73. return then.String()
  74. }
  75. const (
  76. Byte = 1
  77. KByte = Byte * 1024
  78. MByte = KByte * 1024
  79. GByte = MByte * 1024
  80. TByte = GByte * 1024
  81. PByte = TByte * 1024
  82. EByte = PByte * 1024
  83. )
  84. var bytesSizeTable = map[string]uint64{
  85. "b": Byte,
  86. "kb": KByte,
  87. "mb": MByte,
  88. "gb": GByte,
  89. "tb": TByte,
  90. "pb": PByte,
  91. "eb": EByte,
  92. }
  93. func logn(n, b float64) float64 {
  94. return math.Log(n) / math.Log(b)
  95. }
  96. func humanateBytes(s uint64, base float64, sizes []string) string {
  97. if s < 10 {
  98. return fmt.Sprintf("%dB", s)
  99. }
  100. e := math.Floor(logn(float64(s), base))
  101. suffix := sizes[int(e)]
  102. val := float64(s) / math.Pow(base, math.Floor(e))
  103. f := "%.0f"
  104. if val < 10 {
  105. f = "%.1f"
  106. }
  107. return fmt.Sprintf(f+"%s", val, suffix)
  108. }
  109. // FileSize calculates the file size and generate user-friendly string.
  110. func FileSize(s int64) string {
  111. sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
  112. return humanateBytes(uint64(s), 1024, sizes)
  113. }
  114. // Subtract deals with subtraction of all types of number.
  115. func Subtract(left interface{}, right interface{}) interface{} {
  116. var rleft, rright int64
  117. var fleft, fright float64
  118. var isInt bool = true
  119. switch left.(type) {
  120. case int:
  121. rleft = int64(left.(int))
  122. case int8:
  123. rleft = int64(left.(int8))
  124. case int16:
  125. rleft = int64(left.(int16))
  126. case int32:
  127. rleft = int64(left.(int32))
  128. case int64:
  129. rleft = left.(int64)
  130. case float32:
  131. fleft = float64(left.(float32))
  132. isInt = false
  133. case float64:
  134. fleft = left.(float64)
  135. isInt = false
  136. }
  137. switch right.(type) {
  138. case int:
  139. rright = int64(right.(int))
  140. case int8:
  141. rright = int64(right.(int8))
  142. case int16:
  143. rright = int64(right.(int16))
  144. case int32:
  145. rright = int64(right.(int32))
  146. case int64:
  147. rright = right.(int64)
  148. case float32:
  149. fright = float64(left.(float32))
  150. isInt = false
  151. case float64:
  152. fleft = left.(float64)
  153. isInt = false
  154. }
  155. if isInt {
  156. return rleft - rright
  157. } else {
  158. return fleft + float64(rleft) - (fright + float64(rright))
  159. }
  160. }
  161. // DateFormat pattern rules.
  162. var datePatterns = []string{
  163. // year
  164. "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
  165. "y", "06", //A two digit representation of a year Examples: 99 or 03
  166. // month
  167. "m", "01", // Numeric representation of a month, with leading zeros 01 through 12
  168. "n", "1", // Numeric representation of a month, without leading zeros 1 through 12
  169. "M", "Jan", // A short textual representation of a month, three letters Jan through Dec
  170. "F", "January", // A full textual representation of a month, such as January or March January through December
  171. // day
  172. "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
  173. "j", "2", // Day of the month without leading zeros 1 to 31
  174. // week
  175. "D", "Mon", // A textual representation of a day, three letters Mon through Sun
  176. "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
  177. // time
  178. "g", "3", // 12-hour format of an hour without leading zeros 1 through 12
  179. "G", "15", // 24-hour format of an hour without leading zeros 0 through 23
  180. "h", "03", // 12-hour format of an hour with leading zeros 01 through 12
  181. "H", "15", // 24-hour format of an hour with leading zeros 00 through 23
  182. "a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
  183. "A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
  184. "i", "04", // Minutes with leading zeros 00 to 59
  185. "s", "05", // Seconds, with leading zeros 00 through 59
  186. // time zone
  187. "T", "MST",
  188. "P", "-07:00",
  189. "O", "-0700",
  190. // RFC 2822
  191. "r", time.RFC1123Z,
  192. }
  193. // Parse Date use PHP time format.
  194. func DateParse(dateString, format string) (time.Time, error) {
  195. replacer := strings.NewReplacer(datePatterns...)
  196. format = replacer.Replace(format)
  197. return time.ParseInLocation(format, dateString, time.Local)
  198. }
  199. // Date takes a PHP like date func to Go's time format.
  200. func DateFormat(t time.Time, format string) string {
  201. replacer := strings.NewReplacer(datePatterns...)
  202. format = replacer.Replace(format)
  203. return t.Format(format)
  204. }
  205. type Actioner interface {
  206. GetOpType() int
  207. GetActUserName() string
  208. GetRepoName() string
  209. GetContent() string
  210. }
  211. // ActionIcon accepts a int that represents action operation type
  212. // and returns a icon class name.
  213. func ActionIcon(opType int) string {
  214. switch opType {
  215. case 1: // Create repository.
  216. return "plus-circle"
  217. case 5: // Commit repository.
  218. return "arrow-circle-o-right"
  219. default:
  220. return "invalid type"
  221. }
  222. }
  223. const (
  224. TPL_CREATE_REPO = `<a href="/user/%s">%s</a> created repository <a href="/%s/%s">%s</a>`
  225. TPL_COMMIT_REPO = `<a href="/user/%s">%s</a> pushed to <a href="/%s/%s/tree/%s">%s</a> at <a href="/%s/%s">%s/%s</a>%s`
  226. TPL_COMMIT_REPO_LI = `<div><img id="gogs-user-avatar-commit" src="%s?s=16" alt="user-avatar" title="username"/> <a href="/%s/%s/commit/%s">%s</a> %s</div>`
  227. )
  228. // ActionDesc accepts int that represents action operation type
  229. // and returns the description.
  230. func ActionDesc(act Actioner, avatarLink string) string {
  231. actUserName := act.GetActUserName()
  232. repoName := act.GetRepoName()
  233. content := act.GetContent()
  234. switch act.GetOpType() {
  235. case 1: // Create repository.
  236. return fmt.Sprintf(TPL_CREATE_REPO, actUserName, actUserName, actUserName, repoName, repoName)
  237. case 5: // Commit repository.
  238. var commits [][]string
  239. if err := json.Unmarshal([]byte(content), &commits); err != nil {
  240. return err.Error()
  241. }
  242. buf := bytes.NewBuffer([]byte("\n"))
  243. for _, commit := range commits {
  244. buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, avatarLink, actUserName, repoName, commit[0], commit[0][:7], commit[1]) + "\n")
  245. }
  246. return fmt.Sprintf(TPL_COMMIT_REPO, actUserName, actUserName, actUserName, repoName, "master", "master", actUserName, repoName, actUserName, repoName,
  247. buf.String())
  248. default:
  249. return "invalid type"
  250. }
  251. }