forked from Shiloh/githaven
d68a613ba8
Currently only SHA1 repositories are supported by Gitea. This adds support for alternate SHA256 with the additional aim of easier support for additional hash types in the future. Fixes: #13794 Limited by: https://github.com/go-git/go-git/issues/899 Depend on: #28138 <img width="776" alt="图片" src="https://github.com/go-gitea/gitea/assets/81045/5448c9a7-608e-4341-a149-5dd0069c9447"> --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: 6543 <6543@obermui.de>
147 lines
3.9 KiB
Go
147 lines
3.9 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package git
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
// sha1Pattern can be used to determine if a string is an valid sha
|
|
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
|
|
|
// sha256Pattern can be used to determine if a string is an valid sha
|
|
var sha256Pattern = regexp.MustCompile(`^[0-9a-f]{4,64}$`)
|
|
|
|
type ObjectFormat interface {
|
|
// Name returns the name of the object format
|
|
Name() string
|
|
// EmptyObjectID creates a new empty ObjectID from an object format hash name
|
|
EmptyObjectID() ObjectID
|
|
// EmptyTree is the hash of an empty tree
|
|
EmptyTree() ObjectID
|
|
// FullLength is the length of the hash's hex string
|
|
FullLength() int
|
|
// IsValid returns true if the input is a valid hash
|
|
IsValid(input string) bool
|
|
// MustID creates a new ObjectID from a byte slice
|
|
MustID(b []byte) ObjectID
|
|
// ComputeHash compute the hash for a given ObjectType and content
|
|
ComputeHash(t ObjectType, content []byte) ObjectID
|
|
}
|
|
|
|
/* SHA1 Type */
|
|
type Sha1ObjectFormatImpl struct{}
|
|
|
|
var (
|
|
emptySha1ObjectID = &Sha1Hash{}
|
|
emptySha1Tree = &Sha1Hash{
|
|
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
|
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
|
}
|
|
)
|
|
|
|
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
|
|
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
|
|
return emptySha1ObjectID
|
|
}
|
|
|
|
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
|
|
return emptySha1Tree
|
|
}
|
|
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
|
|
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
|
|
return sha1Pattern.MatchString(input)
|
|
}
|
|
|
|
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
|
|
var id Sha1Hash
|
|
copy(id[0:20], b)
|
|
return &id
|
|
}
|
|
|
|
// 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})
|
|
|
|
// HashSum generates a SHA1 for the provided hash
|
|
var sha1 Sha1Hash
|
|
copy(sha1[:], hasher.Sum(nil))
|
|
return &sha1
|
|
}
|
|
|
|
/* 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 {
|
|
hasher := sha256.New()
|
|
_, _ = hasher.Write(t.Bytes())
|
|
_, _ = hasher.Write([]byte(" "))
|
|
_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
|
_, _ = hasher.Write([]byte{0})
|
|
|
|
// HashSum generates a SHA256 for the provided hash
|
|
var sha256 Sha1Hash
|
|
copy(sha256[:], hasher.Sum(nil))
|
|
return &sha256
|
|
}
|
|
|
|
var (
|
|
Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
|
Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{}
|
|
)
|
|
|
|
var SupportedObjectFormats = []ObjectFormat{
|
|
Sha1ObjectFormat,
|
|
}
|
|
|
|
func ObjectFormatFromName(name string) ObjectFormat {
|
|
for _, objectFormat := range SupportedObjectFormats {
|
|
if name == objectFormat.Name() {
|
|
return objectFormat
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func IsValidObjectFormat(name string) bool {
|
|
return ObjectFormatFromName(name) != nil
|
|
}
|