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