code.gitea.io/gitea@v1.19.3/modules/git/tag.go (about) 1 // Copyright 2015 The Gogs Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package git 5 6 import ( 7 "bytes" 8 "sort" 9 "strings" 10 ) 11 12 const ( 13 beginpgp = "\n-----BEGIN PGP SIGNATURE-----\n" 14 endpgp = "\n-----END PGP SIGNATURE-----" 15 ) 16 17 // Tag represents a Git tag. 18 type Tag struct { 19 Name string 20 ID SHA1 21 Object SHA1 // The id of this commit object 22 Type string 23 Tagger *Signature 24 Message string 25 Signature *CommitGPGSignature 26 } 27 28 // Commit return the commit of the tag reference 29 func (tag *Tag) Commit(gitRepo *Repository) (*Commit, error) { 30 return gitRepo.getCommit(tag.Object) 31 } 32 33 // Parse commit information from the (uncompressed) raw 34 // data from the commit object. 35 // \n\n separate headers from message 36 func parseTagData(data []byte) (*Tag, error) { 37 tag := new(Tag) 38 tag.Tagger = &Signature{} 39 // we now have the contents of the commit object. Let's investigate... 40 nextline := 0 41 l: 42 for { 43 eol := bytes.IndexByte(data[nextline:], '\n') 44 switch { 45 case eol > 0: 46 line := data[nextline : nextline+eol] 47 spacepos := bytes.IndexByte(line, ' ') 48 reftype := line[:spacepos] 49 switch string(reftype) { 50 case "object": 51 id, err := NewIDFromString(string(line[spacepos+1:])) 52 if err != nil { 53 return nil, err 54 } 55 tag.Object = id 56 case "type": 57 // A commit can have one or more parents 58 tag.Type = string(line[spacepos+1:]) 59 case "tagger": 60 sig, err := newSignatureFromCommitline(line[spacepos+1:]) 61 if err != nil { 62 return nil, err 63 } 64 tag.Tagger = sig 65 } 66 nextline += eol + 1 67 case eol == 0: 68 tag.Message = string(data[nextline+1:]) 69 break l 70 default: 71 break l 72 } 73 } 74 idx := strings.LastIndex(tag.Message, beginpgp) 75 if idx > 0 { 76 endSigIdx := strings.Index(tag.Message[idx:], endpgp) 77 if endSigIdx > 0 { 78 tag.Signature = &CommitGPGSignature{ 79 Signature: tag.Message[idx+1 : idx+endSigIdx+len(endpgp)], 80 Payload: string(data[:bytes.LastIndex(data, []byte(beginpgp))+1]), 81 } 82 tag.Message = tag.Message[:idx+1] 83 } 84 } 85 return tag, nil 86 } 87 88 type tagSorter []*Tag 89 90 func (ts tagSorter) Len() int { 91 return len([]*Tag(ts)) 92 } 93 94 func (ts tagSorter) Less(i, j int) bool { 95 return []*Tag(ts)[i].Tagger.When.After([]*Tag(ts)[j].Tagger.When) 96 } 97 98 func (ts tagSorter) Swap(i, j int) { 99 []*Tag(ts)[i], []*Tag(ts)[j] = []*Tag(ts)[j], []*Tag(ts)[i] 100 } 101 102 // sortTagsByTime 103 func sortTagsByTime(tags []*Tag) { 104 sorter := tagSorter(tags) 105 sort.Sort(sorter) 106 }