summaryrefslogtreecommitdiffstats
path: root/modules/git/object_format.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/git/object_format.go')
-rw-r--r--modules/git/object_format.go143
1 files changed, 143 insertions, 0 deletions
diff --git a/modules/git/object_format.go b/modules/git/object_format.go
new file mode 100644
index 0000000..db9120d
--- /dev/null
+++ b/modules/git/object_format.go
@@ -0,0 +1,143 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package git
+
+import (
+ "crypto/sha1"
+ "crypto/sha256"
+ "hash"
+ "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
+}
+
+func computeHash(dst []byte, hasher hash.Hash, t ObjectType, content []byte) {
+ _, _ = hasher.Write(t.Bytes())
+ _, _ = hasher.Write([]byte(" "))
+ _, _ = hasher.Write([]byte(strconv.Itoa(len(content))))
+ _, _ = hasher.Write([]byte{0})
+ _, _ = hasher.Write(content)
+ hasher.Sum(dst)
+}
+
+/* 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 {
+ var obj Sha1Hash
+ computeHash(obj[:0], sha1.New(), t, content)
+ return &obj
+}
+
+/* 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 {
+ var obj Sha256Hash
+ computeHash(obj[:0], sha256.New(), t, content)
+ return &obj
+}
+
+var (
+ Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
+ Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{}
+ // any addition must be reflected in IsEmptyCommitID
+)
+
+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
+}