Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: calculate hashsum of the full config #854

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 59 additions & 17 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package config

import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"os"
"fmt"
"io"

"github.com/mitchellh/mapstructure"
toml "github.com/pelletier/go-toml/v2"
"gopkg.in/yaml.v3"

"github.com/evilmartians/lefthook/internal/log"
"github.com/evilmartians/lefthook/internal/version"
)

type DumpFormat int

const (
YAMLFormat DumpFormat = iota
JSONFormat
TOMLFormat
JSONFormat
JSONCompactFormat

dumpIndent = 2
yamlIndent = 2
)

type Config struct {
Expand All @@ -45,7 +49,25 @@ func (c *Config) Validate() error {
return version.CheckCovered(c.MinVersion)
}

func (c *Config) Dump(format DumpFormat) error {
func (c *Config) Md5() (checksum string, err error) {
configBytes := new(bytes.Buffer)

err = c.Dump(JSONCompactFormat, configBytes)
if err != nil {
return
}

hash := md5.New()
_, err = io.Copy(hash, configBytes)
if err != nil {
return
}

checksum = hex.EncodeToString(hash.Sum(nil)[:16])
return
}

func (c *Config) Dump(format DumpFormat, out io.Writer) error {
res := make(map[string]interface{})
if err := mapstructure.Decode(c, &res); err != nil {
return err
Expand All @@ -69,23 +91,25 @@ func (c *Config) Dump(format DumpFormat) error {
case TOMLFormat:
dumper = tomlDumper{}
case JSONFormat:
dumper = jsonDumper{}
dumper = jsonDumper{pretty: true}
case JSONCompactFormat:
dumper = jsonDumper{pretty: false}
default:
dumper = yamlDumper{}
}

return dumper.Dump(res)
return dumper.Dump(res, out)
}

type dumper interface {
Dump(map[string]interface{}) error
Dump(map[string]interface{}, io.Writer) error
}

type yamlDumper struct{}

func (yamlDumper) Dump(input map[string]interface{}) error {
encoder := yaml.NewEncoder(os.Stdout)
encoder.SetIndent(dumpIndent)
func (yamlDumper) Dump(input map[string]interface{}, out io.Writer) error {
encoder := yaml.NewEncoder(out)
encoder.SetIndent(yamlIndent)
defer encoder.Close()

err := encoder.Encode(input)
Expand All @@ -98,8 +122,8 @@ func (yamlDumper) Dump(input map[string]interface{}) error {

type tomlDumper struct{}

func (tomlDumper) Dump(input map[string]interface{}) error {
encoder := toml.NewEncoder(os.Stdout)
func (tomlDumper) Dump(input map[string]interface{}, out io.Writer) error {
encoder := toml.NewEncoder(out)
err := encoder.Encode(input)
if err != nil {
return err
Expand All @@ -108,15 +132,33 @@ func (tomlDumper) Dump(input map[string]interface{}) error {
return nil
}

type jsonDumper struct{}
type jsonDumper struct {
pretty bool
}

func (jsonDumper) Dump(input map[string]interface{}) error {
res, err := json.MarshalIndent(input, "", " ")
func (j jsonDumper) Dump(input map[string]interface{}, out io.Writer) error {
var res []byte
var err error
if j.pretty {
res, err = json.MarshalIndent(input, "", " ")
} else {
res, err = json.Marshal(input)
}
if err != nil {
return err
}

log.Info(string(res))
n, err := out.Write(res)
if n != len(res) {
return fmt.Errorf("file not written fully: %d/%d", n, len(res))
}
if err != nil {
return err
}

if j.pretty {
_, _ = out.Write([]byte("\n"))
}

return nil
}
4 changes: 3 additions & 1 deletion internal/lefthook/dump.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package lefthook

import (
"os"

"github.com/evilmartians/lefthook/internal/config"
"github.com/evilmartians/lefthook/internal/log"
)
Expand Down Expand Up @@ -45,7 +47,7 @@ func Dump(opts *Options, args DumpArgs) {
format = config.TOMLFormat
}

if err := cfg.Dump(format); err != nil {
if err := cfg.Dump(format, os.Stdout); err != nil {
log.Errorf("couldn't dump config: %s\n", err)
return
}
Expand Down
45 changes: 4 additions & 41 deletions internal/lefthook/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ package lefthook

import (
"bufio"
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -145,7 +142,7 @@ func (l *Lefthook) syncHooks(cfg *config.Config, fetchRemotes bool) (*config.Con
}

func (l *Lefthook) createHooksIfNeeded(cfg *config.Config, checkHashSum, force bool) error {
if checkHashSum && l.hooksSynchronized() {
if checkHashSum && l.hooksSynchronized(cfg) {
return nil
}

Expand All @@ -158,7 +155,7 @@ func (l *Lefthook) createHooksIfNeeded(cfg *config.Config, checkHashSum, force b
}
}()

checksum, err := l.configChecksum()
checksum, err := cfg.Md5()
if err != nil {
return fmt.Errorf("could not calculate checksum: %w", err)
}
Expand Down Expand Up @@ -224,7 +221,7 @@ func (l *Lefthook) createHooksIfNeeded(cfg *config.Config, checkHashSum, force b
return nil
}

func (l *Lefthook) hooksSynchronized() bool {
func (l *Lefthook) hooksSynchronized(cfg *config.Config) bool {
// Check checksum in a checksum file
file, err := l.Fs.Open(l.checksumFilePath())
if err != nil {
Expand Down Expand Up @@ -264,7 +261,7 @@ func (l *Lefthook) hooksSynchronized() bool {
return true
}

configChecksum, err := l.configChecksum()
configChecksum, err := cfg.Md5()
if err != nil {
return false
}
Expand Down Expand Up @@ -294,40 +291,6 @@ func (l *Lefthook) configLastUpdateTimestamp() (timestamp int64, err error) {
return
}

func (l *Lefthook) configChecksum() (checksum string, err error) {
paths, err := afero.ReadDir(l.Fs, l.repo.RootPath)
if err != nil {
return
}

var config string
for _, file := range paths {
if ok := configGlob.Match(file.Name()); ok {
config = file.Name()
break
}
}
if len(config) == 0 {
err = errNoConfig
return
}

file, err := l.Fs.Open(filepath.Join(l.repo.RootPath, config))
if err != nil {
return
}
defer file.Close()

hash := md5.New()
_, err = io.Copy(hash, file)
if err != nil {
return
}

checksum = hex.EncodeToString(hash.Sum(nil)[:16])
return
}

func (l *Lefthook) addChecksumFile(checksum string) error {
timestamp, err := l.configLastUpdateTimestamp()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/lefthook/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ post-commit:
notify:
run: echo 'Done!'
`,
checksum: "8b2c9fc6b3391b3cf020b97ab7037c61 1555894310\n",
checksum: "939f59e3f706df65f379a9ff5ce0119b 1555894310\n",
wantExist: []string{
configPath,
infoPath(config.ChecksumFileName),
Expand Down
Loading