use cobra for CLI

This commit is contained in:
golangci 2018-05-05 09:24:37 +03:00
parent 0e4998bb4f
commit c17b41c59a
8 changed files with 307 additions and 48 deletions

135
Gopkg.lock generated
View File

@ -25,6 +25,18 @@
packages = ["."]
revision = "88b7bfd34643dce0c28a6b797652d6b5026091af"
[[projects]]
name = "github.com/fatih/color"
packages = ["."]
revision = "507f6050b8568533fb3f5504de8e5205fa62a114"
version = "v1.6.0"
[[projects]]
name = "github.com/fsnotify/fsnotify"
packages = ["."]
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
name = "github.com/go-ole/go-ole"
packages = [
@ -57,6 +69,65 @@
]
revision = "044f3332f2e8c38cfbb56bab29f65b4245bbe76b"
[[projects]]
branch = "master"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
"json/parser",
"json/scanner",
"json/token"
]
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
[[projects]]
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
name = "github.com/magiconair/properties"
packages = ["."]
revision = "c3beff4c2358b44d0493c7dda585e7db7ff28ae6"
version = "v1.7.6"
[[projects]]
name = "github.com/mattn/go-colorable"
packages = ["."]
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
version = "v0.0.9"
[[projects]]
name = "github.com/mattn/go-isatty"
packages = ["."]
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
branch = "master"
name = "github.com/mitchellh/go-homedir"
packages = ["."]
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
[[projects]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
revision = "00c29f56e2386353d58c599509e8dc3801b0d716"
[[projects]]
name = "github.com/pelletier/go-toml"
packages = ["."]
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
version = "v1.1.0"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
@ -94,6 +165,49 @@
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
version = "v1.0.5"
[[projects]]
name = "github.com/spf13/afero"
packages = [
".",
"mem"
]
revision = "63644898a8da0bc22138abf860edaf5277b6102e"
version = "v1.1.0"
[[projects]]
name = "github.com/spf13/cast"
packages = ["."]
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
name = "github.com/spf13/cobra"
packages = [
".",
"cobra",
"cobra/cmd"
]
revision = "a1f051bc3eba734da4772d60e2d677f47cf93ef4"
version = "v0.0.2"
[[projects]]
branch = "master"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
name = "github.com/spf13/viper"
packages = ["."]
revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736"
version = "v1.0.2"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert"]
@ -130,6 +244,25 @@
]
revision = "6f686a352de66814cdd080d970febae7767857a3"
[[projects]]
name = "golang.org/x/text"
packages = [
"internal/gen",
"internal/triegen",
"internal/ucd",
"transform",
"unicode/cldr",
"unicode/norm"
]
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
name = "gopkg.in/yaml.v2"
packages = ["."]
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[[projects]]
branch = "master"
name = "sourcegraph.com/sourcegraph/go-diff"
@ -145,6 +278,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "fc3abded9121a32e3fc9de887b9f1dd7a4d64ee58e169053e9120881d6c54658"
inputs-digest = "e734f3b5571fe0e9119d20d9e9a7f8ee2b2f316686cf194307a3e5fb3327c85b"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,43 +1,16 @@
package main
import (
"context"
"log"
"os"
"path/filepath"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters"
"github.com/golangci/golangci-shared/pkg/executors"
"github.com/golangci/golangci-lint/internal/commands"
)
func main() {
if err := run(); err != nil {
log.SetFlags(0) // don't print time
e := commands.NewExecutor()
if err := e.Execute(); err != nil {
panic(err)
}
}
func run() error {
var cfg config.Config
config.ReadFromCommandLine(&cfg)
linters := golinters.GetSupportedLinters()
ctx := context.Background()
ex, err := os.Executable()
if err != nil {
return err
}
exPath := filepath.Dir(ex)
exec := executors.NewShell(exPath)
for _, linter := range linters {
res, err := linter.Run(ctx, exec)
if err != nil {
return err
}
log.Print(res)
}
return nil
}

View File

@ -0,0 +1,27 @@
package commands
import (
"github.com/golangci/golangci-lint/pkg/config"
"github.com/spf13/cobra"
)
type Executor struct {
rootCmd *cobra.Command
cfg *config.Config
}
func NewExecutor() *Executor {
e := &Executor{
cfg: config.NewDefault(),
}
e.initRoot()
e.initRun()
return e
}
func (e Executor) Execute() error {
return e.rootCmd.Execute()
}

18
internal/commands/root.go Normal file
View File

@ -0,0 +1,18 @@
package commands
import (
"github.com/spf13/cobra"
)
func (e *Executor) initRoot() {
rootCmd := &cobra.Command{
Use: "golangci-lint",
Short: "golangci-lint is a smart linters runner.",
Long: `Smart, fast linters runner. Run it in cloud for every GitHub pull request on https://golangci.com`,
Run: func(cmd *cobra.Command, args []string) {
_ = cmd.Help()
},
}
rootCmd.PersistentFlags().BoolVarP(&e.cfg.Common.IsVerbose, "verbose", "v", false, "verbose output")
e.rootCmd = rootCmd
}

92
internal/commands/run.go Normal file
View File

@ -0,0 +1,92 @@
package commands
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters"
"github.com/golangci/golangci-lint/pkg/result"
"github.com/golangci/golangci-shared/pkg/executors"
"github.com/spf13/cobra"
)
func (e *Executor) initRun() {
var runCmd = &cobra.Command{
Use: "run",
Short: "Run linters",
Run: e.executeRun,
}
e.rootCmd.AddCommand(runCmd)
runCmd.Flags().StringVarP(&e.cfg.Run.OutFormat, "out-format", "",
config.OutFormatColoredLineNumber,
fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))
}
func (e Executor) executeRun(cmd *cobra.Command, args []string) {
f := func() error {
linters := golinters.GetSupportedLinters()
ctx := context.Background()
ex, err := os.Executable()
if err != nil {
return err
}
exPath := filepath.Dir(ex)
exec := executors.NewShell(exPath)
issues := []result.Issue{}
for _, linter := range linters {
res, err := linter.Run(ctx, exec)
if err != nil {
return err
}
issues = append(issues, res.Issues...)
}
if err = outputIssues(e.cfg.Run.OutFormat, issues); err != nil {
return fmt.Errorf("can't output %d issues: %s", len(issues), err)
}
return nil
}
if err := f(); err != nil {
panic(err)
}
}
func outputIssues(format string, issues []result.Issue) error {
if format == config.OutFormatLineNumber || format == config.OutFormatColoredLineNumber {
if len(issues) == 0 {
outStr := "Congrats! No issues were found."
if format == config.OutFormatColoredLineNumber {
outStr = color.GreenString(outStr)
}
log.Print(outStr)
}
for _, i := range issues {
log.Printf("%s:%d: %s", i.File, i.LineNumber, i.Text)
}
return nil
}
if format == config.OutFormatJSON {
outputJSON, err := json.Marshal(issues)
if err != nil {
return err
}
log.Print(string(outputJSON))
return nil
}
return fmt.Errorf("unknown output format %q", format)
}

View File

@ -1,11 +0,0 @@
package config
import "flag"
func ReadFromCommandLine(cfg *Config) {
flag.Parse()
paths := flag.Args()
if len(paths) != 0 {
cfg.Paths = paths
}
}

View File

@ -1,5 +1,34 @@
package config
type Config struct {
Paths []string
type OutFormat string
const (
OutFormatJSON = "json"
OutFormatLineNumber = "line-number"
OutFormatColoredLineNumber = "colored-line-number"
)
var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON}
type Common struct {
IsVerbose bool
}
type Run struct {
Paths []string
OutFormat string
}
type Config struct {
Common Common
Run Run
}
func NewDefault() *Config {
return &Config{
Run: Run{
Paths: []string{"./..."},
OutFormat: OutFormatColoredLineNumber,
},
}
}

View File

@ -3,7 +3,6 @@ package golinters
import (
"context"
"fmt"
"log"
"path"
"path/filepath"
@ -38,7 +37,6 @@ func processPaths(root string, paths []string, maxPaths int) ([]string, error) {
func getPathsForGoProject(root string) (*ProjectPaths, error) {
excludeDirs := []string{"vendor", "testdata", "examples", "Godeps"}
pr := fsutils.NewPathResolver(excludeDirs, []string{".go"})
log.Printf("root is %q, paths are %q", root, path.Join(root, "..."))
paths, err := pr.Resolve(path.Join(root, "..."))
if err != nil {
return nil, fmt.Errorf("can't resolve paths: %s", err)