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