2023-12-13 21:02:00 +00:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"bytes"
"encoding/hex"
"fmt"
)
type ObjectID interface {
String ( ) string
IsZero ( ) bool
RawValue ( ) [ ] byte
Type ( ) ObjectFormat
}
2024-01-19 16:05:02 +00:00
/* SHA1 */
2023-12-13 21:02:00 +00:00
type Sha1Hash [ 20 ] byte
func ( h * Sha1Hash ) String ( ) string {
return hex . EncodeToString ( h [ : ] )
}
func ( h * Sha1Hash ) IsZero ( ) bool {
empty := Sha1Hash { }
return bytes . Equal ( empty [ : ] , h [ : ] )
}
func ( h * Sha1Hash ) RawValue ( ) [ ] byte { return h [ : ] }
2023-12-17 19:56:08 +08:00
func ( * Sha1Hash ) Type ( ) ObjectFormat { return Sha1ObjectFormat }
2023-12-13 21:02:00 +00:00
2023-12-17 19:56:08 +08:00
var _ ObjectID = & Sha1Hash { }
2023-12-13 21:02:00 +00:00
2023-12-19 15:20:47 +08:00
func MustIDFromString ( hexHash string ) ObjectID {
id , err := NewIDFromString ( hexHash )
if err != nil {
panic ( err )
2023-12-13 21:02:00 +00:00
}
2023-12-19 15:20:47 +08:00
return id
2023-12-13 21:02:00 +00:00
}
2024-01-19 16:05:02 +00:00
/* SHA256 */
type Sha256Hash [ 32 ] byte
func ( h * Sha256Hash ) String ( ) string {
return hex . EncodeToString ( h [ : ] )
}
func ( h * Sha256Hash ) IsZero ( ) bool {
empty := Sha256Hash { }
return bytes . Equal ( empty [ : ] , h [ : ] )
}
func ( h * Sha256Hash ) RawValue ( ) [ ] byte { return h [ : ] }
func ( * Sha256Hash ) Type ( ) ObjectFormat { return Sha256ObjectFormat }
/* utility */
2023-12-19 15:20:47 +08:00
func NewIDFromString ( hexHash string ) ( ObjectID , error ) {
var theObjectFormat ObjectFormat
for _ , objectFormat := range SupportedObjectFormats {
if len ( hexHash ) == objectFormat . FullLength ( ) {
theObjectFormat = objectFormat
break
}
2023-12-13 21:02:00 +00:00
}
2023-12-19 15:20:47 +08:00
if theObjectFormat == nil {
return nil , fmt . Errorf ( "length %d has no matched object format: %s" , len ( hexHash ) , hexHash )
2023-12-13 21:02:00 +00:00
}
2023-12-19 15:20:47 +08:00
b , err := hex . DecodeString ( hexHash )
2023-12-13 21:02:00 +00:00
if err != nil {
2023-12-19 15:20:47 +08:00
return nil , err
2023-12-13 21:02:00 +00:00
}
2023-12-19 15:20:47 +08:00
if len ( b ) != theObjectFormat . FullLength ( ) / 2 {
return theObjectFormat . EmptyObjectID ( ) , fmt . Errorf ( "length must be %d: %v" , theObjectFormat . FullLength ( ) , b )
2023-12-13 21:02:00 +00:00
}
2023-12-19 15:20:47 +08:00
return theObjectFormat . MustID ( b ) , nil
2023-12-13 21:02:00 +00:00
}
2024-05-15 15:42:29 +02:00
// IsEmptyCommitID checks if an hexadecimal string represents an empty commit according to git (only '0').
2024-05-25 09:43:50 +02:00
// If objectFormat is not nil, the length will be checked as well (otherwise the length must match the sha1 or sha256 length).
2024-05-15 15:42:29 +02:00
func IsEmptyCommitID ( commitID string , objectFormat ObjectFormat ) bool {
2023-12-13 21:02:00 +00:00
if commitID == "" {
return true
}
2024-05-15 15:42:29 +02:00
if objectFormat == nil {
if Sha1ObjectFormat . FullLength ( ) != len ( commitID ) && Sha256ObjectFormat . FullLength ( ) != len ( commitID ) {
return false
}
} else if objectFormat . FullLength ( ) != len ( commitID ) {
2023-12-13 21:02:00 +00:00
return false
}
2024-05-15 15:42:29 +02:00
for _ , c := range commitID {
if c != '0' {
return false
}
}
return true
2023-12-13 21:02:00 +00:00
}
// ComputeBlobHash compute the hash for a given blob content
func ComputeBlobHash ( hashType ObjectFormat , content [ ] byte ) ObjectID {
2023-12-19 15:20:47 +08:00
return hashType . ComputeHash ( ObjectBlob , content )
2023-12-13 21:02:00 +00:00
}
type ErrInvalidSHA struct {
SHA string
}
func ( err ErrInvalidSHA ) Error ( ) string {
return fmt . Sprintf ( "invalid sha: %s" , err . SHA )
}