diff options
author | Toon Claes <toon@gitlab.com> | 2022-07-12 18:31:16 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-07-18 12:04:56 +0300 |
commit | b3d0d5c58218b5ec9b7dac6fd1accbce42839779 (patch) | |
tree | b6cd22691f493006f0c3f6eea42a2b8521487db5 | |
parent | e2ea91705833e60c11600651a60be497e751c806 (diff) |
git: Add package that handles sha256 hashes
SHA256 hashes are 64 hexadecimal characters, compared to the 40 chars
for SHA1. This change adds validators for this longer object format.
-rw-r--r-- | internal/git/sha256/id.go | 36 | ||||
-rw-r--r-- | internal/git/sha256/id_test.go | 106 |
2 files changed, 142 insertions, 0 deletions
diff --git a/internal/git/sha256/id.go b/internal/git/sha256/id.go new file mode 100644 index 000000000..42a4a7c5f --- /dev/null +++ b/internal/git/sha256/id.go @@ -0,0 +1,36 @@ +package sha256 + +import ( + "fmt" + "regexp" + + "gitlab.com/gitlab-org/gitaly/v15/internal/git" +) + +const ( + // EmptyTreeOID is the Git tree object sha256 hash that corresponds to an empty tree (directory) + EmptyTreeOID = git.ObjectID("6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321") +) + +var objectIDRegex = regexp.MustCompile(`\A[0-9a-f]{64}\z`) + +// NewObjectIDFromHex constructs a new ObjectID from the given hex +// representation of the object ID. Returns ErrInvalidObjectID if the given +// OID is not valid. +func NewObjectIDFromHex(hex string) (git.ObjectID, error) { + if err := ValidateObjectID(hex); err != nil { + return "", err + } + return git.ObjectID(hex), nil +} + +// ValidateObjectID checks if id is a syntactically correct object ID. Abbreviated +// object IDs are not deemed to be valid. Returns an ErrInvalidObjectID if the +// id is not valid. +func ValidateObjectID(id string) error { + if objectIDRegex.MatchString(id) { + return nil + } + + return fmt.Errorf("%w: %q", git.ErrInvalidObjectID, id) +} diff --git a/internal/git/sha256/id_test.go b/internal/git/sha256/id_test.go new file mode 100644 index 000000000..1be75e98f --- /dev/null +++ b/internal/git/sha256/id_test.go @@ -0,0 +1,106 @@ +package sha256 + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidateObjectID(t *testing.T) { + for _, tc := range []struct { + desc string + oid string + valid bool + }{ + { + desc: "valid object ID", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92e", + valid: true, + }, + { + desc: "object ID with non-hex characters fails", + oid: "xff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92e", + valid: false, + }, + { + desc: "object ID with upper-case letters fails", + oid: "CFF96308C1B0C36602CA031013B563074EDDDB203EFA61C4F01BE1BD2482D92E", + valid: false, + }, + { + desc: "too short object ID fails", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92", + valid: false, + }, + { + desc: "too long object ID fails", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92eb", + valid: false, + }, + { + desc: "empty string fails", + oid: "", + valid: false, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + err := ValidateObjectID(tc.oid) + if tc.valid { + require.NoError(t, err) + } else { + require.Error(t, err) + require.EqualError(t, err, fmt.Sprintf("invalid object ID: %q", tc.oid)) + } + }) + } +} + +func TestNewObjectIDFromHex(t *testing.T) { + for _, tc := range []struct { + desc string + oid string + valid bool + }{ + { + desc: "valid object ID", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92e", + valid: true, + }, + { + desc: "object ID with non-hex characters fails", + oid: "xff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92e", + valid: false, + }, + { + desc: "object ID with upper-case letters fails", + oid: "CFF96308C1B0C36602CA031013B563074EDDDB203EFA61C4F01BE1BD2482D92E", + valid: false, + }, + { + desc: "too short object ID fails", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92", + valid: false, + }, + { + desc: "too long object ID fails", + oid: "cff96308c1b0c36602ca031013b563074edddb203efa61c4f01be1bd2482d92eb", + valid: false, + }, + { + desc: "empty string fails", + oid: "", + valid: false, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + oid, err := NewObjectIDFromHex(tc.oid) + if tc.valid { + require.NoError(t, err) + require.Equal(t, tc.oid, oid.String()) + } else { + require.Error(t, err) + } + }) + } +} |