2016-11-03 23:16:01 +01:00
// Copyright 2015 The Gogs Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2016-11-03 23:16:01 +01:00
package git
2017-01-06 09:51:15 +08:00
import (
"bytes"
"sort"
2024-02-09 11:02:53 +08:00
"code.gitea.io/gitea/modules/util"
2017-01-06 09:51:15 +08:00
)
2016-11-03 23:16:01 +01:00
// Tag represents a Git tag.
type Tag struct {
2020-12-17 14:00:47 +00:00
Name string
2023-12-13 21:02:00 +00:00
ID ObjectID
Object ObjectID // The id of this commit object
2020-12-17 14:00:47 +00:00
Type string
Tagger * Signature
Message string
2024-04-02 04:23:17 +08:00
Signature * CommitSignature
2016-11-03 23:16:01 +01:00
}
2016-12-22 17:30:52 +08:00
// Commit return the commit of the tag reference
2022-01-12 21:37:46 +01:00
func ( tag * Tag ) Commit ( gitRepo * Repository ) ( * Commit , error ) {
return gitRepo . getCommit ( tag . Object )
2016-11-03 23:16:01 +01:00
}
2024-04-02 04:23:17 +08:00
func parsePayloadSignature ( data [ ] byte , messageStart int ) ( payload , msg , sign string ) {
pos := messageStart
signStart , signEnd := - 1 , - 1
for {
eol := bytes . IndexByte ( data [ pos : ] , '\n' )
if eol < 0 {
break
}
line := data [ pos : pos + eol ]
signType , hasPrefix := bytes . CutPrefix ( line , [ ] byte ( "-----BEGIN " ) )
signType , hasSuffix := bytes . CutSuffix ( signType , [ ] byte ( " SIGNATURE-----" ) )
if hasPrefix && hasSuffix {
signEndBytes := append ( [ ] byte ( "\n-----END " ) , signType ... )
signEndBytes = append ( signEndBytes , [ ] byte ( " SIGNATURE-----" ) ... )
signEnd = bytes . Index ( data [ pos : ] , signEndBytes )
if signEnd != - 1 {
signStart = pos
signEnd = pos + signEnd + len ( signEndBytes )
}
}
pos += eol + 1
}
if signStart != - 1 && signEnd != - 1 {
msgEnd := max ( messageStart , signStart - 1 )
return string ( data [ : msgEnd ] ) , string ( data [ messageStart : msgEnd ] ) , string ( data [ signStart : signEnd ] )
}
return string ( data ) , string ( data [ messageStart : ] ) , ""
}
2016-11-03 23:16:01 +01:00
// Parse commit information from the (uncompressed) raw
// data from the commit object.
// \n\n separate headers from message
2023-12-13 21:02:00 +00:00
func parseTagData ( objectFormat ObjectFormat , data [ ] byte ) ( * Tag , error ) {
2016-11-03 23:16:01 +01:00
tag := new ( Tag )
2023-12-17 19:56:08 +08:00
tag . ID = objectFormat . EmptyObjectID ( )
tag . Object = objectFormat . EmptyObjectID ( )
2021-05-12 06:11:42 +01:00
tag . Tagger = & Signature { }
2024-04-02 04:23:17 +08:00
pos := 0
2016-11-03 23:16:01 +01:00
for {
2024-04-02 04:23:17 +08:00
eol := bytes . IndexByte ( data [ pos : ] , '\n' )
if eol == - 1 {
break // shouldn't happen, but could just tolerate it
2016-11-03 23:16:01 +01:00
}
2024-04-02 04:23:17 +08:00
if eol == 0 {
pos ++
break // end of headers
}
line := data [ pos : pos + eol ]
key , val , _ := bytes . Cut ( line , [ ] byte ( " " ) )
switch string ( key ) {
case "object" :
id , err := NewIDFromString ( string ( val ) )
if err != nil {
return nil , err
2020-12-17 14:00:47 +00:00
}
2024-04-02 04:23:17 +08:00
tag . Object = id
case "type" :
tag . Type = string ( val ) // A commit can have one or more parents
case "tagger" :
tag . Tagger = parseSignatureFromCommitLine ( util . UnsafeBytesToString ( val ) )
2020-12-17 14:00:47 +00:00
}
2024-04-02 04:23:17 +08:00
pos += eol + 1
}
payload , msg , sign := parsePayloadSignature ( data , pos )
tag . Message = msg
if len ( sign ) > 0 {
tag . Signature = & CommitSignature { Signature : sign , Payload : payload }
2020-12-17 14:00:47 +00:00
}
2016-11-03 23:16:01 +01:00
return tag , nil
}
2017-01-06 09:51:15 +08:00
type tagSorter [ ] * Tag
func ( ts tagSorter ) Len ( ) int {
return len ( [ ] * Tag ( ts ) )
}
func ( ts tagSorter ) Less ( i , j int ) bool {
return [ ] * Tag ( ts ) [ i ] . Tagger . When . After ( [ ] * Tag ( ts ) [ j ] . Tagger . When )
}
func ( ts tagSorter ) Swap ( i , j int ) {
[ ] * Tag ( ts ) [ i ] , [ ] * Tag ( ts ) [ j ] = [ ] * Tag ( ts ) [ j ] , [ ] * Tag ( ts ) [ i ]
}
// sortTagsByTime
func sortTagsByTime ( tags [ ] * Tag ) {
sorter := tagSorter ( tags )
sort . Sort ( sorter )
}