2023-12-14 00:02:00 +03:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"crypto/sha1"
2024-01-19 19:05:02 +03:00
"crypto/sha256"
2023-12-14 00:02:00 +03:00
"regexp"
2023-12-19 10:20:47 +03:00
"strconv"
2023-12-14 00:02:00 +03:00
)
// sha1Pattern can be used to determine if a string is an valid sha
var sha1Pattern = regexp . MustCompile ( ` ^[0-9a-f] { 4,40}$ ` )
2024-01-19 19:05:02 +03:00
// sha256Pattern can be used to determine if a string is an valid sha
var sha256Pattern = regexp . MustCompile ( ` ^[0-9a-f] { 4,64}$ ` )
2023-12-14 00:02:00 +03:00
type ObjectFormat interface {
2023-12-17 14:56:08 +03:00
// Name returns the name of the object format
Name ( ) string
// EmptyObjectID creates a new empty ObjectID from an object format hash name
EmptyObjectID ( ) ObjectID
2023-12-14 00:02:00 +03:00
// EmptyTree is the hash of an empty tree
EmptyTree ( ) ObjectID
// FullLength is the length of the hash's hex string
FullLength ( ) int
2023-12-19 10:20:47 +03:00
// IsValid returns true if the input is a valid hash
2023-12-14 00:02:00 +03:00
IsValid ( input string ) bool
2023-12-19 10:20:47 +03:00
// MustID creates a new ObjectID from a byte slice
2023-12-14 00:02:00 +03:00
MustID ( b [ ] byte ) ObjectID
2023-12-19 10:20:47 +03:00
// ComputeHash compute the hash for a given ObjectType and content
ComputeHash ( t ObjectType , content [ ] byte ) ObjectID
2023-12-14 00:02:00 +03:00
}
2023-12-17 14:56:08 +03:00
type Sha1ObjectFormatImpl struct { }
2023-12-14 00:02:00 +03:00
2023-12-17 14:56:08 +03:00
var (
2024-01-19 19:05:02 +03:00
emptySha1ObjectID = & Sha1Hash { }
emptySha1Tree = & Sha1Hash {
2023-12-14 00:02:00 +03:00
0x4b , 0x82 , 0x5d , 0xc6 , 0x42 , 0xcb , 0x6e , 0xb9 , 0xa0 , 0x60 ,
0xe5 , 0x4b , 0xf8 , 0xd6 , 0x92 , 0x88 , 0xfb , 0xee , 0x49 , 0x04 ,
}
2023-12-17 14:56:08 +03:00
)
func ( Sha1ObjectFormatImpl ) Name ( ) string { return "sha1" }
func ( Sha1ObjectFormatImpl ) EmptyObjectID ( ) ObjectID {
2024-01-19 19:05:02 +03:00
return emptySha1ObjectID
2023-12-17 14:56:08 +03:00
}
func ( Sha1ObjectFormatImpl ) EmptyTree ( ) ObjectID {
2024-01-19 19:05:02 +03:00
return emptySha1Tree
2023-12-14 00:02:00 +03:00
}
2023-12-17 14:56:08 +03:00
func ( Sha1ObjectFormatImpl ) FullLength ( ) int { return 40 }
func ( Sha1ObjectFormatImpl ) IsValid ( input string ) bool {
2023-12-14 00:02:00 +03:00
return sha1Pattern . MatchString ( input )
}
2023-12-17 14:56:08 +03:00
func ( Sha1ObjectFormatImpl ) MustID ( b [ ] byte ) ObjectID {
2023-12-14 00:02:00 +03:00
var id Sha1Hash
copy ( id [ 0 : 20 ] , b )
return & id
}
2023-12-19 10:20:47 +03:00
// ComputeHash compute the hash for a given ObjectType and content
func ( h Sha1ObjectFormatImpl ) ComputeHash ( t ObjectType , content [ ] byte ) ObjectID {
hasher := sha1 . New ( )
_ , _ = hasher . Write ( t . Bytes ( ) )
_ , _ = hasher . Write ( [ ] byte ( " " ) )
_ , _ = hasher . Write ( [ ] byte ( strconv . FormatInt ( int64 ( len ( content ) ) , 10 ) ) )
_ , _ = hasher . Write ( [ ] byte { 0 } )
2024-04-26 12:49:48 +03:00
_ , _ = hasher . Write ( content )
return h . MustID ( hasher . Sum ( nil ) )
2023-12-14 00:02:00 +03:00
}
2024-01-19 19:05:02 +03:00
type Sha256ObjectFormatImpl struct { }
var (
emptySha256ObjectID = & Sha256Hash { }
emptySha256Tree = & Sha256Hash {
0x6e , 0xf1 , 0x9b , 0x41 , 0x22 , 0x5c , 0x53 , 0x69 , 0xf1 , 0xc1 ,
0x04 , 0xd4 , 0x5d , 0x8d , 0x85 , 0xef , 0xa9 , 0xb0 , 0x57 , 0xb5 ,
0x3b , 0x14 , 0xb4 , 0xb9 , 0xb9 , 0x39 , 0xdd , 0x74 , 0xde , 0xcc ,
0x53 , 0x21 ,
}
)
func ( Sha256ObjectFormatImpl ) Name ( ) string { return "sha256" }
func ( Sha256ObjectFormatImpl ) EmptyObjectID ( ) ObjectID {
return emptySha256ObjectID
}
func ( Sha256ObjectFormatImpl ) EmptyTree ( ) ObjectID {
return emptySha256Tree
}
func ( Sha256ObjectFormatImpl ) FullLength ( ) int { return 64 }
func ( Sha256ObjectFormatImpl ) IsValid ( input string ) bool {
return sha256Pattern . MatchString ( input )
}
func ( Sha256ObjectFormatImpl ) MustID ( b [ ] byte ) ObjectID {
var id Sha256Hash
copy ( id [ 0 : 32 ] , b )
return & id
}
// ComputeHash compute the hash for a given ObjectType and content
func ( h Sha256ObjectFormatImpl ) ComputeHash ( t ObjectType , content [ ] byte ) ObjectID {
hasher := sha256 . New ( )
_ , _ = hasher . Write ( t . Bytes ( ) )
_ , _ = hasher . Write ( [ ] byte ( " " ) )
_ , _ = hasher . Write ( [ ] byte ( strconv . FormatInt ( int64 ( len ( content ) ) , 10 ) ) )
_ , _ = hasher . Write ( [ ] byte { 0 } )
2024-04-26 12:49:48 +03:00
_ , _ = hasher . Write ( content )
return h . MustID ( hasher . Sum ( nil ) )
2024-01-19 19:05:02 +03:00
}
var (
Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl { }
Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl { }
)
2023-12-14 00:02:00 +03:00
2023-12-17 14:56:08 +03:00
func ObjectFormatFromName ( name string ) ObjectFormat {
2024-05-06 19:34:16 +03:00
for _ , objectFormat := range DefaultFeatures ( ) . SupportedObjectFormats {
2023-12-17 14:56:08 +03:00
if name == objectFormat . Name ( ) {
return objectFormat
}
2023-12-14 00:02:00 +03:00
}
2023-12-17 14:56:08 +03:00
return nil
}
2023-12-14 00:02:00 +03:00
2023-12-17 14:56:08 +03:00
func IsValidObjectFormat ( name string ) bool {
return ObjectFormatFromName ( name ) != nil
2023-12-14 00:02:00 +03:00
}