feat: allow missing formatters #6
3
internal/cache/cache.go
vendored
3
internal/cache/cache.go
vendored
@ -61,6 +61,9 @@ func Open(treeRoot string, clean bool) (err error) {
|
||||
}
|
||||
|
||||
func Close() error {
|
||||
if db == nil {
|
||||
return nil
|
||||
}
|
||||
return db.Close()
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,11 @@ import "github.com/charmbracelet/log"
|
||||
var Cli = Options{}
|
||||
|
||||
type Options struct {
|
||||
Verbosity int `name:"verbose" short:"v" type:"counter" default:"0" env:"LOG_LEVEL" help:"Set the verbosity of logs e.g. -vv"`
|
||||
AllowMissingFormatter bool `default:"false" help:"Do not exit with error if a configured formatter is missing"`
|
||||
ClearCache bool `short:"c" help:"Reset the evaluation cache. Use in case the cache is not precise enough"`
|
||||
ConfigFile string `type:"existingfile" default:"./treefmt.toml"`
|
||||
TreeRoot string `type:"existingdir" default:"."`
|
||||
ClearCache bool `short:"c" help:"Reset the evaluation cache. Use in case the cache is not precise enough"`
|
||||
Verbosity int `name:"verbose" short:"v" type:"counter" default:"0" env:"LOG_LEVEL" help:"Set the verbosity of logs e.g. -vv"`
|
||||
|
||||
Format Format `cmd:"" default:"."`
|
||||
}
|
||||
|
@ -44,7 +44,12 @@ func (f *Format) Run() error {
|
||||
|
||||
// init formatters
|
||||
for name, formatter := range cfg.Formatters {
|
||||
if err = formatter.Init(name); err != nil {
|
||||
err = formatter.Init(name)
|
||||
if err == format.ErrFormatterNotFound && Cli.AllowMissingFormatter {
|
||||
l.Debugf("formatter not found: %v", name)
|
||||
// remove this formatter
|
||||
delete(cfg.Formatters, name)
|
||||
} else if err != nil {
|
||||
return errors.Annotatef(err, "failed to initialise formatter: %v", name)
|
||||
}
|
||||
}
|
||||
@ -155,5 +160,7 @@ func (f *Format) Run() error {
|
||||
return cache.ChangeSet(ctx, Cli.TreeRoot, pathsCh)
|
||||
})
|
||||
|
||||
// shutdown.Listen(syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
return eg.Wait()
|
||||
}
|
||||
|
68
internal/cli/format_test.go
Normal file
68
internal/cli/format_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.numtide.com/numtide/treefmt/internal/format"
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func writeConfig(t *testing.T, path string, cfg format.Config) {
|
||||
t.Helper()
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create a new config file: %v", err)
|
||||
}
|
||||
encoder := toml.NewEncoder(f)
|
||||
if err = encoder.Encode(cfg); err != nil {
|
||||
t.Fatalf("failed to write to config file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newKong(t *testing.T, cli interface{}, options ...kong.Option) *kong.Kong {
|
||||
t.Helper()
|
||||
options = append([]kong.Option{
|
||||
kong.Name("test"),
|
||||
kong.Exit(func(int) {
|
||||
t.Helper()
|
||||
t.Fatalf("unexpected exit()")
|
||||
}),
|
||||
}, options...)
|
||||
parser, err := kong.New(cli, options...)
|
||||
assert.NoError(t, err)
|
||||
return parser
|
||||
}
|
||||
|
||||
func newCli(t *testing.T, args ...string) (*kong.Context, error) {
|
||||
t.Helper()
|
||||
p := newKong(t, &Cli)
|
||||
return p.Parse(args)
|
||||
}
|
||||
|
||||
func TestAllowMissingFormatter(t *testing.T) {
|
||||
as := require.New(t)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
configPath := tempDir + "/treefmt.toml"
|
||||
|
||||
writeConfig(t, configPath, format.Config{
|
||||
Formatters: map[string]*format.Formatter{
|
||||
"foo-fmt": {
|
||||
Command: "foo-fmt",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
ctx, err := newCli(t, "--config-file", configPath, "--tree-root", tempDir)
|
||||
as.NoError(err)
|
||||
as.Error(ctx.Run(), format.ErrFormatterNotFound)
|
||||
|
||||
ctx, err = newCli(t, "--config-file", configPath, "--tree-root", tempDir, "--allow-missing-formatter")
|
||||
as.NoError(err)
|
||||
|
||||
as.NoError(ctx.Run())
|
||||
}
|
@ -6,7 +6,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
func TestReadConfigFile(t *testing.T) {
|
||||
as := require.New(t)
|
||||
|
||||
cfg, err := ReadConfigFile("../../test/treefmt.toml")
|
||||
@ -119,4 +119,9 @@ shfmt -i 2 -s -w "$@"
|
||||
as.Equal([]string{"fmt"}, terraform.Options)
|
||||
as.Equal([]string{"*.tf"}, terraform.Includes)
|
||||
as.Nil(terraform.Excludes)
|
||||
|
||||
// missing
|
||||
foo, ok := cfg.Formatters["foo-fmt"]
|
||||
as.True(ok, "foo formatter not found")
|
||||
as.Equal("foo-fmt", foo.Command)
|
||||
}
|
||||
|
@ -10,6 +10,10 @@ import (
|
||||
"github.com/juju/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrFormatterNotFound = errors.ConstError("formatter not found")
|
||||
)
|
||||
|
||||
type Formatter struct {
|
||||
Name string
|
||||
Command string
|
||||
@ -32,8 +36,13 @@ type Formatter struct {
|
||||
|
||||
func (f *Formatter) Init(name string) error {
|
||||
f.Name = name
|
||||
f.log = log.WithPrefix("format | " + name)
|
||||
|
||||
// test if the formatter is available
|
||||
if err := exec.Command(f.Command, "--help").Run(); err != nil {
|
||||
return ErrFormatterNotFound
|
||||
}
|
||||
|
||||
f.log = log.WithPrefix("format | " + name)
|
||||
f.inbox = make(chan string, 1024)
|
||||
|
||||
f.batchSize = 1024
|
||||
|
@ -80,3 +80,6 @@ includes = ["*.sh"]
|
||||
command = "terraform"
|
||||
options = ["fmt"]
|
||||
includes = ["*.tf"]
|
||||
|
||||
[formatter.foo-fmt]
|
||||
command = "foo-fmt"
|
Reference in New Issue
Block a user