Skip to content

Commit

Permalink
feat: support toml dumping (#490)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexox authored May 23, 2023
1 parent 2453910 commit c861c1f
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 86 deletions.
46 changes: 42 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.19.x]
go-version: [1.20.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -28,13 +28,49 @@ jobs:
parallel: true
flag-name: ${{ join(matrix.*, ' ') }}

test-integration:
strategy:
matrix:
go-version: [1.20.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
env:
GOCOVERDIR: _icoverdir_
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Integration tests
run: |
mkdir _icoverdir_
make build-with-coverage
cp examples/complete/lefthook.yml .
# TODO: prepare a framework to test the results
- run: |
./lefthook dump
./lefthook dump --json
./lefthook dump --toml
- name: Format coverage
run: |
go tool covdata textfmt -i _icoverdir_ -o coverage.out
- name: Report coverage
uses: coverallsapp/github-action@v2
with:
file: coverage.out
format: golang
parallel: true
flag-name: integration-${{ join(matrix.*, ' ') }}

build:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
go-version: 1.20.x
- name: Checkout code
uses: actions/checkout@v2
- name: Build binaries
Expand All @@ -53,9 +89,11 @@ jobs:

coverage:
runs-on: ubuntu-latest
needs: test
needs:
- test
- test-integration
steps:
- uses: coverallsapp/github-action@v2
with:
carryforward: "1.19.x ubuntu-latest,1.19.x macos-latest,1.19.x windows-latest"
carryforward: "integration-1.20.x ubuntu-latest,integration-1.20.x macos-latest,1.20.x ubuntu-latest,1.20.x macos-latest,1.20.x windows-latest"
parallel-finished: true
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## master (unreleased)

- feat: support toml dumpint ([#490](https://github.com/evilmartians/lefthook/pull/490)) by @mrexox
- feat: support json configs ([#489](https://github.com/evilmartians/lefthook/pull/489)) by @mrexox

## 1.4.1 (2024-05-22)
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ First off, thanks for taking the time to contribute! Feel free to make Pull Requ

# Requirements

Go >= 1.19.0
Go >= 1.20.0

# Process

Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ COMMIT_HASH = $(shell git rev-parse HEAD)
build:
go build -ldflags "-s -w -X github.com/evilmartians/lefthook/internal/version.commit=$(COMMIT_HASH)" -o lefthook

build-with-coverage:
go build -cover -ldflags "-s -w -X github.com/evilmartians/lefthook/internal/version.commit=$(COMMIT_HASH)" -o lefthook

test:
go test -cpu 24 -race -count=1 -timeout=30s ./...

test-integration: build-with-coverage
./lefthook dump
./lefthook dump --json
./lefthook dump --toml

bench:
go test -cpu 24 -race -run=Bench -bench=. ./...

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Fast and powerful Git hooks manager for Node.js, Ruby or any other type of proje

## Install

With **Go** (>= 1.19):
With **Go** (>= 1.20):

```bash
go install github.com/evilmartians/lefthook@latest
Expand Down
5 changes: 5 additions & 0 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ func newDumpCmd(opts *lefthook.Options) *cobra.Command {
"dump in JSON format",
)

dumpCmd.Flags().BoolVarP(
&dumpArgs.TOML, "toml", "t", false,
"dump in TOML format",
)

return &dumpCmd
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/evilmartians/lefthook

go 1.19
go 1.20

require (
github.com/MakeNowJust/heredoc v1.0.0
Expand Down Expand Up @@ -31,7 +31,7 @@ require (
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pelletier/go-toml/v2 v2.0.6
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
Expand Down
24 changes: 12 additions & 12 deletions internal/config/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ import (
var errFilesIncompatible = errors.New("One of your runners contains incompatible file types")

type Command struct {
Run string `mapstructure:"run" yaml:",omitempty" json:"run,omitempty"`
Run string `mapstructure:"run" yaml:"run" json:"run" toml:"run"`

Skip interface{} `mapstructure:"skip" yaml:",omitempty" json:"skip,omitempty"`
Only interface{} `mapstructure:"only" yaml:",omitempty" json:"only,omitempty"`
Tags []string `mapstructure:"tags" yaml:",omitempty" json:"tags,omitempty"`
Glob string `mapstructure:"glob" yaml:",omitempty" json:"glob,omitempty"`
Files string `mapstructure:"files" yaml:",omitempty" json:"files,omitempty"`
Env map[string]string `mapstructure:"env" yaml:",omitempty" json:"env,omitempty"`
Skip interface{} `mapstructure:"skip" yaml:",omitempty" json:"skip,omitempty" toml:"skip,omitempty,inline"`
Only interface{} `mapstructure:"only" yaml:",omitempty" json:"only,omitempty" toml:"only,omitempty,inline"`
Tags []string `mapstructure:"tags" yaml:",omitempty" json:"tags,omitempty" toml:"tags,omitempty"`
Glob string `mapstructure:"glob" yaml:",omitempty" json:"glob,omitempty" toml:"glob,omitempty"`
Files string `mapstructure:"files" yaml:",omitempty" json:"files,omitempty" toml:"files,omitempty"`
Env map[string]string `mapstructure:"env" yaml:",omitempty" json:"env,omitempty" toml:"env,omitempty"`

Root string `mapstructure:"root" yaml:",omitempty" json:"root,omitempty"`
Exclude string `mapstructure:"exclude" yaml:",omitempty" json:"exclude,omitempty"`
Root string `mapstructure:"root" yaml:",omitempty" json:"root,omitempty" toml:"root,omitempty"`
Exclude string `mapstructure:"exclude" yaml:",omitempty" json:"exclude,omitempty" toml:"exclude,omitempty"`

FailText string `mapstructure:"fail_text" yaml:"fail_text,omitempty" json:"fail_text,omitempty"`
Interactive bool `mapstructure:"interactive" yaml:",omitempty" json:"interactive,omitempty"`
StageFixed bool `mapstructure:"stage_fixed" yaml:"stage_fixed,omitempty" json:"stage_fixed,omitempty"`
FailText string `mapstructure:"fail_text" yaml:"fail_text,omitempty" json:"fail_text,omitempty" toml:"fail_text,omitempty"`
Interactive bool `mapstructure:"interactive" yaml:",omitempty" json:"interactive,omitempty" toml:"interactive,omitempty"`
StageFixed bool `mapstructure:"stage_fixed" yaml:"stage_fixed,omitempty" json:"stage_fixed,omitempty" toml:"stage_fixed,omitempty"`
}

func (c Command) Validate() error {
Expand Down
81 changes: 46 additions & 35 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"encoding/json"
"os"

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

"github.com/evilmartians/lefthook/internal/log"
Expand All @@ -13,72 +15,81 @@ import (
const dumpIndent = 2

type Config struct {
Colors interface{} `mapstructure:"colors" yaml:"colors,omitempty" json:"colors,omitempty"`
Extends []string `mapstructure:"extends" yaml:"extends,omitempty" json:"extends,omitempty"`
Remote Remote `mapstructure:"remote" yaml:"remote,omitempty" json:"remote,omitempty"`
MinVersion string `mapstructure:"min_version" yaml:"min_version,omitempty" json:"min_version,omitempty"`
SkipOutput []string `mapstructure:"skip_output" yaml:"skip_output,omitempty" json:"skip_output,omitempty"`
SourceDir string `mapstructure:"source_dir" yaml:"source_dir,omitempty" json:"source_dir,omitempty"`
SourceDirLocal string `mapstructure:"source_dir_local" yaml:"source_dir_local,omitempty" json:"source_dir_local,omitempty"`
Rc string `mapstructure:"rc" yaml:"rc,omitempty" json:"rc,omitempty"`
NoTTY bool `mapstructure:"no_tty" yaml:"no_tty,omitempty" json:"no_tty,omitempty"`

Hooks map[string]*Hook `yaml:",inline" json:"-"`
MinVersion string `mapstructure:"min_version,omitempty"`
SourceDir string `mapstructure:"source_dir"`
SourceDirLocal string `mapstructure:"source_dir_local"`
Rc string `mapstructure:"rc,omitempty"`
SkipOutput []string `mapstructure:"skip_output,omitempty"`
Extends []string `mapstructure:"extends,omitempty"`
NoTTY bool `mapstructure:"no_tty,omitempty"`
Colors interface{} `mapstructure:"colors,omitempty"`
Remote *Remote `mapstructure:"remote,omitempty" `

Hooks map[string]*Hook `mapstructure:"-"`
}

func (c *Config) Validate() error {
return version.CheckCovered(c.MinVersion)
}

func (c *Config) Dump(asJSON bool) error {
func (c *Config) Dump(asJSON bool, asTOML bool) error {
res := make(map[string]interface{})
if err := mapstructure.Decode(c, &res); err != nil {
return err
}

if c.SourceDir == DefaultSourceDir {
delete(res, "source_dir")
}
if c.SourceDirLocal == DefaultSourceDirLocal {
delete(res, "source_dir_local")
}

for hookName, hook := range c.Hooks {
res[hookName] = hook
}

if asJSON {
return c.dumpJSON()
return dumpJSON(res)
}

if asTOML {
return dumpTOML(res)
}

return c.dumpYAML()
return dumpYAML(res)
}

func (c *Config) dumpYAML() error {
func dumpYAML(input map[string]interface{}) error {
encoder := yaml.NewEncoder(os.Stdout)
encoder.SetIndent(dumpIndent)
defer encoder.Close()

err := encoder.Encode(c)
err := encoder.Encode(input)
if err != nil {
return err
}

return nil
}

func (c *Config) dumpJSON() error {
// This hack allows to inline Hooks
type ConfigForMarshalling *Config
res, err := json.Marshal(ConfigForMarshalling(c))
func dumpJSON(input map[string]interface{}) error {
res, err := json.MarshalIndent(input, "", " ")
if err != nil {
return err
}

var rawMarshalled map[string]json.RawMessage
if err = json.Unmarshal(res, &rawMarshalled); err != nil {
return err
}
log.Info(string(res))

for hook, contents := range c.Hooks {
var hookMarshalled json.RawMessage
hookMarshalled, err = json.Marshal(contents)
if err != nil {
return err
}
rawMarshalled[hook] = hookMarshalled
}
return nil
}

res, err = json.MarshalIndent(rawMarshalled, "", " ")
func dumpTOML(input map[string]interface{}) error {
encoder := toml.NewEncoder(os.Stdout)
err := encoder.Encode(input)
if err != nil {
return err
}

log.Info(string(res))

return nil
}
20 changes: 10 additions & 10 deletions internal/config/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ type Hook struct {
// Should be unmarshalled with `mapstructure:"commands"`
// But replacing '{cmd}' is still an issue
// Unmarshaling it manually, so omit auto unmarshaling
Commands map[string]*Command `mapstructure:"?" yaml:",omitempty" json:"commands,omitempty"`
Commands map[string]*Command `mapstructure:"-" yaml:",omitempty" json:"commands,omitempty" toml:"commands,omitempty"`

// Should be unmarshalled with `mapstructure:"scripts"`
// But parsing keys with dots in it is still an issue: https://github.com/spf13/viper/issues/324
// Unmarshaling it manually, so omit auto unmarshaling
Scripts map[string]*Script `mapstructure:"?" yaml:",omitempty" json:"scripts,omitempty"`

Files string `mapstructure:"files" yaml:",omitempty" json:"files,omitempty"`
Parallel bool `mapstructure:"parallel" yaml:",omitempty" json:"parallel,omitempty"`
Piped bool `mapstructure:"piped" yaml:",omitempty" json:"piped,omitempty"`
ExcludeTags []string `mapstructure:"exclude_tags" yaml:"exclude_tags,omitempty" json:"exclude_tags,omitempty"`
Skip interface{} `mapstructure:"skip" yaml:",omitempty" json:"skip,omitempty"`
Only interface{} `mapstructure:"only" yaml:",omitempty" json:"only,omitempty"`
Follow bool `mapstructure:"follow" yaml:",omitempty" json:"follow,omitempty"`
Scripts map[string]*Script `mapstructure:"-" yaml:",omitempty" json:"scripts,omitempty" toml:"scripts,omitempty"`

Files string `mapstructure:"files" yaml:",omitempty" json:"files,omitempty" toml:"files,omitempty"`
Parallel bool `mapstructure:"parallel" yaml:",omitempty" json:"parallel,omitempty" toml:"parallel,omitempty"`
Piped bool `mapstructure:"piped" yaml:",omitempty" json:"piped,omitempty" toml:"piped,omitempty"`
Follow bool `mapstructure:"follow" yaml:",omitempty" json:"follow,omitempty" toml:"follow,omitempty"`
ExcludeTags []string `mapstructure:"exclude_tags" yaml:"exclude_tags,omitempty" json:"exclude_tags,omitempty" toml:"exclude_tags,omitempty"`
Skip interface{} `mapstructure:"skip" yaml:",omitempty" json:"skip,omitempty" toml:"skip,omitempty,inline"`
Only interface{} `mapstructure:"only" yaml:",omitempty" json:"only,omitempty" toml:"only,omitempty,inline"`
}

func (h *Hook) Validate() error {
Expand Down
Loading

0 comments on commit c861c1f

Please sign in to comment.