2023-12-13 22:02:00 +01:00
|
|
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
package git
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/sha1"
|
2024-01-19 17:05:02 +01:00
|
|
|
"crypto/sha256"
|
2024-04-26 10:02:47 +02:00
|
|
|
"hash"
|
2023-12-13 22:02:00 +01:00
|
|
|
"regexp"
|
2023-12-19 08:20:47 +01:00
|
|
|
"strconv"
|
2023-12-13 22:02:00 +01: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 17:05:02 +01: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-13 22:02:00 +01:00
|
|
|
type ObjectFormat interface {
|
2023-12-17 12:56:08 +01: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-13 22:02:00 +01: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 08:20:47 +01:00
|
|
|
// IsValid returns true if the input is a valid hash
|
2023-12-13 22:02:00 +01:00
|
|
|
IsValid(input string) bool
|
2023-12-19 08:20:47 +01:00
|
|
|
// MustID creates a new ObjectID from a byte slice
|
2023-12-13 22:02:00 +01:00
|
|
|
MustID(b []byte) ObjectID
|
2023-12-19 08:20:47 +01:00
|
|
|
// ComputeHash compute the hash for a given ObjectType and content
|
|
|
|
ComputeHash(t ObjectType, content []byte) ObjectID
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|
|
|
|
|
2024-04-26 10:02:47 +02:00
|
|
|
func computeHash(dst []byte, hasher hash.Hash, t ObjectType, content []byte) []byte {
|
|
|
|
_, _ = hasher.Write(t.Bytes())
|
|
|
|
_, _ = hasher.Write([]byte(" "))
|
|
|
|
_, _ = hasher.Write([]byte(strconv.Itoa(len(content))))
|
|
|
|
_, _ = hasher.Write([]byte{0})
|
|
|
|
_, _ = hasher.Write(content)
|
|
|
|
return hasher.Sum(dst)
|
|
|
|
}
|
|
|
|
|
2024-01-19 17:05:02 +01:00
|
|
|
/* SHA1 Type */
|
2023-12-17 12:56:08 +01:00
|
|
|
type Sha1ObjectFormatImpl struct{}
|
2023-12-13 22:02:00 +01:00
|
|
|
|
2023-12-17 12:56:08 +01:00
|
|
|
var (
|
2024-01-19 17:05:02 +01:00
|
|
|
emptySha1ObjectID = &Sha1Hash{}
|
|
|
|
emptySha1Tree = &Sha1Hash{
|
2023-12-13 22:02:00 +01:00
|
|
|
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
|
|
|
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
|
|
|
}
|
2023-12-17 12:56:08 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
|
|
|
|
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
|
2024-01-19 17:05:02 +01:00
|
|
|
return emptySha1ObjectID
|
2023-12-17 12:56:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
|
2024-01-19 17:05:02 +01:00
|
|
|
return emptySha1Tree
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|
2023-12-17 12:56:08 +01:00
|
|
|
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
|
|
|
|
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
|
2023-12-13 22:02:00 +01:00
|
|
|
return sha1Pattern.MatchString(input)
|
|
|
|
}
|
|
|
|
|
2023-12-17 12:56:08 +01:00
|
|
|
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
|
2023-12-13 22:02:00 +01:00
|
|
|
var id Sha1Hash
|
|
|
|
copy(id[0:20], b)
|
|
|
|
return &id
|
|
|
|
}
|
|
|
|
|
2023-12-19 08:20:47 +01:00
|
|
|
// ComputeHash compute the hash for a given ObjectType and content
|
|
|
|
func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
|
2024-04-26 10:02:47 +02:00
|
|
|
var obj Sha1Hash
|
|
|
|
computeHash(obj[:0], sha1.New(), t, content)
|
|
|
|
return &obj
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|
|
|
|
|
2024-01-19 17:05:02 +01:00
|
|
|
/* SHA256 Type */
|
|
|
|
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 {
|
2024-04-26 10:02:47 +02:00
|
|
|
var obj Sha256Hash
|
|
|
|
computeHash(obj[:0], sha256.New(), t, content)
|
|
|
|
return &obj
|
2024-01-19 17:05:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
|
|
|
Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{}
|
|
|
|
)
|
2023-12-13 22:02:00 +01:00
|
|
|
|
2023-12-17 12:56:08 +01:00
|
|
|
var SupportedObjectFormats = []ObjectFormat{
|
|
|
|
Sha1ObjectFormat,
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|
|
|
|
|
2023-12-17 12:56:08 +01:00
|
|
|
func ObjectFormatFromName(name string) ObjectFormat {
|
|
|
|
for _, objectFormat := range SupportedObjectFormats {
|
|
|
|
if name == objectFormat.Name() {
|
|
|
|
return objectFormat
|
|
|
|
}
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|
2023-12-17 12:56:08 +01:00
|
|
|
return nil
|
|
|
|
}
|
2023-12-13 22:02:00 +01:00
|
|
|
|
2023-12-17 12:56:08 +01:00
|
|
|
func IsValidObjectFormat(name string) bool {
|
|
|
|
return ObjectFormatFromName(name) != nil
|
2023-12-13 22:02:00 +01:00
|
|
|
}
|