mirror of https://github.com/harness/drone.git
144 lines
3.4 KiB
Go
144 lines
3.4 KiB
Go
// Copyright 2023 Harness, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package sha
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/gob"
|
|
"encoding/json"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/harness/gitness/errors"
|
|
|
|
"github.com/swaggest/jsonschema-go"
|
|
)
|
|
|
|
var (
|
|
Nil = Must("0000000000000000000000000000000000000000")
|
|
None = SHA{}
|
|
// regex defines the valid SHA format accepted by GIT (full form and short forms).
|
|
// Note: as of now SHA is at most 40 characters long, but in the future it's moving to sha256
|
|
// which is 64 chars - keep this forward-compatible.
|
|
regex = regexp.MustCompile("^[0-9a-f]{4,64}$")
|
|
nilRegex = regexp.MustCompile("^0{4,64}$")
|
|
|
|
// EmptyTree is the SHA of an empty tree.
|
|
EmptyTree = Must("4b825dc642cb6eb9a060e54bf8d69288fbee4904")
|
|
)
|
|
|
|
// SHA represents a git sha.
|
|
type SHA struct {
|
|
str string
|
|
}
|
|
|
|
// New creates and validates SHA from the value.
|
|
func New(value string) (SHA, error) {
|
|
value = strings.TrimSpace(value)
|
|
value = strings.ToLower(value)
|
|
if !regex.MatchString(value) {
|
|
return SHA{}, errors.InvalidArgument("the provided commit sha '%s' is of invalid format.", value)
|
|
}
|
|
return SHA{
|
|
str: value,
|
|
}, nil
|
|
}
|
|
|
|
// NewOrEmpty returns None if value is empty otherwise it will try to create
|
|
// and validate new SHA object.
|
|
func NewOrEmpty(value string) (SHA, error) {
|
|
if value == "" {
|
|
return None, nil
|
|
}
|
|
return New(value)
|
|
}
|
|
|
|
func (s SHA) GobEncode() ([]byte, error) {
|
|
buffer := &bytes.Buffer{}
|
|
err := gob.NewEncoder(buffer).Encode(s.str)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to pack sha value: %w", err)
|
|
}
|
|
return buffer.Bytes(), nil
|
|
}
|
|
|
|
func (s *SHA) GobDecode(v []byte) error {
|
|
if err := gob.NewDecoder(bytes.NewReader(v)).Decode(&s.str); err != nil {
|
|
return fmt.Errorf("failed to unpack sha value: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *SHA) UnmarshalJSON(content []byte) error {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
var str string
|
|
err := json.Unmarshal(content, &str)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sha, err := NewOrEmpty(str)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.str = sha.str
|
|
return nil
|
|
}
|
|
|
|
func (s SHA) MarshalJSON() ([]byte, error) {
|
|
return []byte("\"" + s.str + "\""), nil
|
|
}
|
|
|
|
// String returns string representation of the SHA.
|
|
func (s SHA) String() string {
|
|
return s.str
|
|
}
|
|
|
|
// IsNil returns whether this SHA is all zeroes.
|
|
func (s SHA) IsNil() bool {
|
|
return nilRegex.MatchString(s.str)
|
|
}
|
|
|
|
// IsEmpty returns whether this SHA is empty string.
|
|
func (s SHA) IsEmpty() bool {
|
|
return s.str == ""
|
|
}
|
|
|
|
// Equal returns true if val has the same SHA.
|
|
func (s SHA) Equal(val SHA) bool {
|
|
return s.str == val.str
|
|
}
|
|
|
|
// Must returns sha if there is an error it will panic.
|
|
func Must(value string) SHA {
|
|
sha, err := New(value)
|
|
if err != nil {
|
|
panic("invalid SHA" + err.Error())
|
|
}
|
|
return sha
|
|
}
|
|
|
|
func (s SHA) JSONSchema() (jsonschema.Schema, error) {
|
|
var schema jsonschema.Schema
|
|
|
|
schema.AddType(jsonschema.String)
|
|
schema.WithDescription("Git object hash")
|
|
|
|
return schema, nil
|
|
}
|