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.

signature_nogogit.go 2.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. //go:build !gogit
  6. package git
  7. import (
  8. "bytes"
  9. "fmt"
  10. "strconv"
  11. "time"
  12. )
  13. // Signature represents the Author or Committer information.
  14. type Signature struct {
  15. // Name represents a person name. It is an arbitrary string.
  16. Name string
  17. // Email is an email, but it cannot be assumed to be well-formed.
  18. Email string
  19. // When is the timestamp of the signature.
  20. When time.Time
  21. }
  22. func (s *Signature) String() string {
  23. return fmt.Sprintf("%s <%s>", s.Name, s.Email)
  24. }
  25. // Decode decodes a byte array representing a signature to signature
  26. func (s *Signature) Decode(b []byte) {
  27. sig, _ := newSignatureFromCommitline(b)
  28. s.Email = sig.Email
  29. s.Name = sig.Name
  30. s.When = sig.When
  31. }
  32. // Helper to get a signature from the commit line, which looks like these:
  33. // author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
  34. // author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
  35. // but without the "author " at the beginning (this method should)
  36. // be used for author and committer.
  37. func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
  38. sig = new(Signature)
  39. emailStart := bytes.LastIndexByte(line, '<')
  40. emailEnd := bytes.LastIndexByte(line, '>')
  41. if emailStart == -1 || emailEnd == -1 || emailEnd < emailStart {
  42. return
  43. }
  44. sig.Name = string(line[:emailStart-1])
  45. sig.Email = string(line[emailStart+1 : emailEnd])
  46. hasTime := emailEnd+2 < len(line)
  47. if !hasTime {
  48. return
  49. }
  50. // Check date format.
  51. firstChar := line[emailEnd+2]
  52. if firstChar >= 48 && firstChar <= 57 {
  53. idx := bytes.IndexByte(line[emailEnd+2:], ' ')
  54. if idx < 0 {
  55. return
  56. }
  57. timestring := string(line[emailEnd+2 : emailEnd+2+idx])
  58. seconds, _ := strconv.ParseInt(timestring, 10, 64)
  59. sig.When = time.Unix(seconds, 0)
  60. idx += emailEnd + 3
  61. if idx >= len(line) || idx+5 > len(line) {
  62. return
  63. }
  64. timezone := string(line[idx : idx+5])
  65. tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64)
  66. tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64)
  67. if err1 != nil || err2 != nil {
  68. return
  69. }
  70. if tzhours < 0 {
  71. tzmins *= -1
  72. }
  73. tz := time.FixedZone("", int(tzhours*60*60+tzmins*60))
  74. sig.When = sig.When.In(tz)
  75. } else {
  76. sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
  77. if err != nil {
  78. return
  79. }
  80. }
  81. return
  82. }