Skip to content

Commit

Permalink
Change hashFiles template function to generate SHA256 hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
ste93cry committed Jul 19, 2022
1 parent 7f43131 commit 534a993
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 31 deletions.
5 changes: 3 additions & 2 deletions internal/plugin/plugin.go
Expand Up @@ -2,6 +2,7 @@
package plugin

import (
"crypto/md5" // #nosec
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -89,9 +90,9 @@ func (p *Plugin) Exec() error { // nolint: funlen,cyclop
return fmt.Errorf("parse failed, falling back to default, %w", err)
}

options = append(options, cache.WithFallbackGenerator(keygen.NewHash(p.Metadata.Commit.Branch)))
options = append(options, cache.WithFallbackGenerator(keygen.NewHash(md5.New, p.Metadata.Commit.Branch)))
} else {
generator = keygen.NewHash(p.Metadata.Commit.Branch)
generator = keygen.NewHash(md5.New, p.Metadata.Commit.Branch)
options = append(options, cache.WithFallbackGenerator(keygen.NewStatic(p.Metadata.Commit.Branch)))
}

Expand Down
32 changes: 17 additions & 15 deletions key/generator/hash.go
Expand Up @@ -2,23 +2,35 @@ package generator

import (
"fmt"
hash2 "hash"
"io"
"strings"
)

// Hash implements a key generator with md5.
// Hash implements a key generator that uses the specified hash algorithm.
type Hash struct {
hasher func() hash2.Hash
defaultParts []string
}

// NewHash creates a new hash kye generator.
func NewHash(defaultParts ...string) *Hash {
return &Hash{defaultParts: defaultParts}
// NewHash creates a new hash key generator.
func NewHash(hasher func() hash2.Hash, defaultParts ...string) *Hash {
return &Hash{
hasher: hasher,
defaultParts: defaultParts,
}
}

// Generate generates key from given parts or templates as parameter.
func (h *Hash) Generate(parts ...string) (string, error) {
key, err := hash(append(parts, h.defaultParts...)...)
parts = append(parts, h.defaultParts...)
readers := make([]io.Reader, len(parts))

for i, p := range parts {
readers[i] = strings.NewReader(p)
}

key, err := readerHasher(h.hasher, readers...)
if err != nil {
return "", fmt.Errorf("generate hash key for mounted, %w", err)
}
Expand All @@ -28,13 +40,3 @@ func (h *Hash) Generate(parts ...string) (string, error) {

// Check checks if generator functional.
func (h *Hash) Check() error { return nil }

// hash generates a key based on given strings (ie. filename paths and branch).
func hash(parts ...string) ([]byte, error) {
readers := make([]io.Reader, len(parts))
for i, p := range parts {
readers[i] = strings.NewReader(p)
}

return readerHasher(readers...)
}
3 changes: 2 additions & 1 deletion key/generator/hash_test.go
@@ -1,6 +1,7 @@
package generator

import (
"crypto/md5"
"testing"

"github.com/meltwater/drone-cache/test"
Expand All @@ -9,7 +10,7 @@ import (
func TestGenerateHash(t *testing.T) {
t.Parallel()

actual, err := NewHash().Generate("hash")
actual, err := NewHash(md5.New).Generate("hash")
test.Ok(t, err)

expected := "0800fc577294c34e0b28ad2839435945"
Expand Down
19 changes: 14 additions & 5 deletions key/generator/metadata.go
Expand Up @@ -2,8 +2,11 @@ package generator

import (
"bytes"
"crypto/md5" // #nosec
"crypto/sha256"
"errors"
"fmt"
hash2 "hash"
"io"
"os"
"path/filepath"
Expand Down Expand Up @@ -92,7 +95,7 @@ func (g *Metadata) parseTemplate() (*template.Template, error) {

func checksumFunc(logger log.Logger) func(string) string {
return func(p string) string {
return fmt.Sprintf("%x", fileHash(p, logger))
return fmt.Sprintf("%x", fileHash(p, logger, md5.New))
}
}

Expand All @@ -104,49 +107,55 @@ func hashFilesFunc(logger log.Logger) func(...string) string {
paths, err := filepath.Glob(pattern)
if err != nil {
level.Error(logger).Log("could not parse file path as a glob pattern")

continue
}

for _, p := range paths {
readers = append(readers, bytes.NewReader(fileHash(p, logger)))
readers = append(readers, bytes.NewReader(fileHash(p, logger, sha256.New)))
}
}

if len(readers) == 0 {
level.Debug(logger).Log("no matches found for glob")

return ""
}

level.Debug(logger).Log("found %d files to hash", len(readers))

h, err := readerHasher(readers...)
h, err := readerHasher(sha256.New, readers...)
if err != nil {
level.Error(logger).Log("could not generate the hash of the input files: %s", err.Error())

return ""
}

return fmt.Sprintf("%x", h)
}
}

func fileHash(path string, logger log.Logger) []byte {
func fileHash(path string, logger log.Logger, hasher func() hash2.Hash) []byte {
path, err := filepath.Abs(filepath.Clean(path))
if err != nil {
level.Error(logger).Log("could not compute the absolute file path: %s", err.Error())

return []byte{}
}

f, err := os.Open(path)
if err != nil {
level.Error(logger).Log("could not open the file: %s", err.Error())

return []byte{}
}

defer internal.CloseWithErrLogf(logger, f, "checksum close defer")

h, err := readerHasher(f)
h, err := readerHasher(hasher, f)
if err != nil {
level.Error(logger).Log("could not generate the hash of the input file: %s", err.Error())

return []byte{}
}

Expand Down
6 changes: 3 additions & 3 deletions key/generator/metadata_test.go
Expand Up @@ -23,9 +23,9 @@ func TestGenerate(t *testing.T) {
{`{{ checksum "checksum_file_test.txt"}}`, "04a29c732ecbce101c1be44c948a50c6"},
{`{{ checksum "../../docs/drone_env_vars.md"}}`, "f8b5b7f96f3ffaa828e4890aab290e59"},
{`{{ hashFiles "" }}`, ""},
{`{{ hashFiles "checksum_file_test.txt" }}`, "5c3544faf206777a2827f5db8fca3a9a"},
{`{{ hashFiles "checksum_file_test.txt" "checksum_file_test.txt" }}`, "1ce4114d3f702eecca6de4fed10250f3"},
{`{{ hashFiles "checksum_file_tes*.txt" }}`, "5c3544faf206777a2827f5db8fca3a9a"},
{`{{ hashFiles "checksum_file_test.txt" }}`, "b9fff559e00dd879bdffee979ee73e08c67dee2117da071083d3b833cbff7bc8"},
{`{{ hashFiles "checksum_file_test.txt" "checksum_file_test.txt" }}`, "fed16eb2e98f501968c74e261feb26a8776b2ae03b205ad7302f949e75ca455f"},
{`{{ hashFiles "checksum_file_tes*.txt" }}`, "b9fff559e00dd879bdffee979ee73e08c67dee2117da071083d3b833cbff7bc8"},
{`{{ epoch }}`, "1550563151"},
{`{{ arch }}`, runtime.GOARCH},
{`{{ os }}`, runtime.GOOS},
Expand Down
8 changes: 3 additions & 5 deletions key/generator/util.go
@@ -1,15 +1,13 @@
package generator

import (
"crypto/md5" // #nosec
"fmt"
hash2 "hash"
"io"
)

// readerHasher generic md5 hash generater from io.Reader.
func readerHasher(readers ...io.Reader) ([]byte, error) {
// Use go1.14 new hashmap functions.
h := md5.New() // #nosec
func readerHasher(hasher func() hash2.Hash, readers ...io.Reader) ([]byte, error) {
h := hasher()

for _, r := range readers {
if _, err := io.Copy(h, r); err != nil {
Expand Down

0 comments on commit 534a993

Please sign in to comment.