diff options
Diffstat (limited to 'object')
| -rw-r--r-- | object/id/algorithm.go | 8 | ||||
| -rw-r--r-- | object/id/algorithm_details.go | 68 | ||||
| -rw-r--r-- | object/id/algorithm_ops.go | 60 | ||||
| -rw-r--r-- | object/id/algorithm_parse.go | 8 | ||||
| -rw-r--r-- | object/id/errors.go | 12 | ||||
| -rw-r--r-- | object/id/object_id.go | 9 |
6 files changed, 164 insertions, 1 deletions
diff --git a/object/id/algorithm.go b/object/id/algorithm.go index 47a1b02a..1b02cbc4 100644 --- a/object/id/algorithm.go +++ b/object/id/algorithm.go @@ -5,7 +5,7 @@ type Algorithm uint8 const ( // AlgorithmUnknown identifies an unknown object ID hash algorithm. - AlgorithmUknown Algorithm = iota + AlgorithmUnknown Algorithm = iota // AlgorithmSHA1 identifies the SHA-1 object ID hash algorithm. // This is the default for all versions of Git until Git 3.0. @@ -15,3 +15,9 @@ const ( // This is the default for Git 3.0 and beyond. AlgorithmSHA256 ) + +// SupportedAlgorithms returns all object ID algorithms supported by furgit. +// Labels: Mut-No. +func SupportedAlgorithms() []Algorithm { + return supportedAlgorithms +} diff --git a/object/id/algorithm_details.go b/object/id/algorithm_details.go new file mode 100644 index 00000000..d3fd665d --- /dev/null +++ b/object/id/algorithm_details.go @@ -0,0 +1,68 @@ +package id + +import ( + "crypto/sha1" //#nosec:G505 + "crypto/sha256" + "hash" +) + +type algorithmDetails struct { + name string + size int + packHashID uint32 + signatureHeaderName string + sum func([]byte) ObjectID + new func() hash.Hash + emptyTree ObjectID +} + +func (algo Algorithm) info() algorithmDetails { + return algorithmTable[algo] +} + +//nolint:gochecknoglobals +var algorithmTable = [...]algorithmDetails{ + AlgorithmUnknown: {}, + AlgorithmSHA1: { + name: "sha1", + size: sha1.Size, + packHashID: 1, + signatureHeaderName: "gpgsig", + new: sha1.New, + }, + AlgorithmSHA256: { + name: "sha256", + size: sha256.Size, + packHashID: 2, + signatureHeaderName: "gpgsig-sha256", + new: sha256.New, + }, +} + +// maxObjectIDSize MUST be >= the largest supported algorithm size. +const maxObjectIDSize = sha256.Size + +var ( + //nolint:gochecknoglobals + algorithmByName = map[string]Algorithm{} + //nolint:gochecknoglobals + algorithmBySignatureHeaderName = map[string]Algorithm{} + //nolint:gochecknoglobals + supportedAlgorithms []Algorithm +) + +func init() { //nolint:gochecknoinits + // Skip over AlgorithmUnknown. + for algo := Algorithm(1); int(algo) < len(algorithmTable); algo++ { + info := &algorithmTable[algo] + + info.emptyTree = info.sum([]byte("tree 0\x00")) + + algorithmByName[info.name] = algo + if info.signatureHeaderName != "" { + algorithmBySignatureHeaderName[info.signatureHeaderName] = algo + } + + supportedAlgorithms = append(supportedAlgorithms, algo) + } +} diff --git a/object/id/algorithm_ops.go b/object/id/algorithm_ops.go new file mode 100644 index 00000000..b746dc5f --- /dev/null +++ b/object/id/algorithm_ops.go @@ -0,0 +1,60 @@ +package id + +import "hash" + +// EmptyTree returns the object ID of +// an empty tree ("tree 0\x00") +// for this algorithm. +func (algo Algorithm) EmptyTree() ObjectID { + return algo.info().emptyTree +} + +// HexLen returns the encoded hexadecimal length. +func (algo Algorithm) HexLen() int { + return algo.Size() * 2 +} + +// Size returns the hash size in bytes. +func (algo Algorithm) Size() int { + return algo.info().size +} + +// New returns a new hash.Hash for this algorithm. +func (algo Algorithm) New() (hash.Hash, error) { + newFn := algo.info().new + if newFn == nil { + return nil, ErrInvalidAlgorithm + } + + return newFn(), nil +} + +// PackHashID returns the Git pack/rev hash-id encoding for this algorithm. +// +// Unknown algorithms return 0. +func (algo Algorithm) PackHashID() uint32 { + return algo.info().packHashID +} + +// SignatureHeaderName returns the signature header name for this algorithm. +func (algo Algorithm) SignatureHeaderName() string { + return algo.info().signatureHeaderName +} + +// String returns the canonical algorithm name. +func (algo Algorithm) String() string { + return algo.info().name +} + +// Sum computes an object ID from raw data using the selected algorithm. +func (algo Algorithm) Sum(data []byte) ObjectID { + return algo.info().sum(data) +} + +// Zero returns the all-zero object ID for this algorithm. +func (algo Algorithm) Zero() ObjectID { + return ObjectID{ + algo: algo, + data: [maxObjectIDSize]byte{}, + } +} diff --git a/object/id/algorithm_parse.go b/object/id/algorithm_parse.go new file mode 100644 index 00000000..7349288f --- /dev/null +++ b/object/id/algorithm_parse.go @@ -0,0 +1,8 @@ +package id + +// ParseAlgorithm parses a canonical algorithm name (e.g. "sha1", "sha256"). +func ParseAlgorithm(s string) (Algorithm, bool) { + algo, ok := algorithmByName[s] + + return algo, ok +} diff --git a/object/id/errors.go b/object/id/errors.go new file mode 100644 index 00000000..11c471ed --- /dev/null +++ b/object/id/errors.go @@ -0,0 +1,12 @@ +package id + +import "errors" + +var ( + // ErrInvalidAlgorithm indicates an unsupported object ID algorithm. + ErrInvalidAlgorithm = errors.New("objectid: invalid algorithm") + + // ErrInvalidObjectID indicates malformed object ID data. + // ErrInvalidObjectID = errors.New("objectid: invalid object id") + // TODO +) diff --git a/object/id/object_id.go b/object/id/object_id.go new file mode 100644 index 00000000..4cf562fa --- /dev/null +++ b/object/id/object_id.go @@ -0,0 +1,9 @@ +package id + +// ObjectID represents a Git object ID. +// +//nolint:recvcheck +type ObjectID struct { + algo Algorithm + data [maxObjectIDSize]byte +} |
