diff options
Diffstat (limited to 'vendor/github.com/google/yamlfmt/command/command.go')
| -rw-r--r-- | vendor/github.com/google/yamlfmt/command/command.go | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/vendor/github.com/google/yamlfmt/command/command.go b/vendor/github.com/google/yamlfmt/command/command.go new file mode 100644 index 0000000..3224f46 --- /dev/null +++ b/vendor/github.com/google/yamlfmt/command/command.go @@ -0,0 +1,258 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package command + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + + "github.com/google/yamlfmt" + "github.com/google/yamlfmt/engine" + "github.com/mitchellh/mapstructure" + + "github.com/braydonk/yaml" +) + +type FormatterConfig struct { + Type string `mapstructure:"type"` + FormatterSettings map[string]any `mapstructure:",remain"` +} + +// NewFormatterConfig returns an empty formatter config with all fields initialized. +func NewFormatterConfig() *FormatterConfig { + return &FormatterConfig{FormatterSettings: make(map[string]any)} +} + +type Config struct { + Extensions []string `mapstructure:"extensions"` + MatchType yamlfmt.MatchType `mapstructure:"match_type"` + Include []string `mapstructure:"include"` + Exclude []string `mapstructure:"exclude"` + RegexExclude []string `mapstructure:"regex_exclude"` + FormatterConfig *FormatterConfig `mapstructure:"formatter,omitempty"` + Doublestar bool `mapstructure:"doublestar"` + ContinueOnError bool `mapstructure:"continue_on_error"` + LineEnding yamlfmt.LineBreakStyle `mapstructure:"line_ending"` + GitignoreExcludes bool `mapstructure:"gitignore_excludes"` + GitignorePath string `mapstructure:"gitignore_path"` + OutputFormat engine.EngineOutputFormat `mapstructure:"output_format"` +} + +type Command struct { + Operation yamlfmt.Operation + Registry *yamlfmt.Registry + Config *Config + Quiet bool +} + +func (c *Command) Run() error { + formatter, err := c.getFormatter() + if err != nil { + return err + } + + lineSepChar, err := c.Config.LineEnding.Separator() + if err != nil { + return err + } + + eng := &engine.ConsecutiveEngine{ + LineSepCharacter: lineSepChar, + Formatter: formatter, + Quiet: c.Quiet, + ContinueOnError: c.Config.ContinueOnError, + OutputFormat: c.Config.OutputFormat, + } + + collectedPaths, err := c.collectPaths() + if err != nil { + return err + } + if c.Config.GitignoreExcludes { + newPaths, err := yamlfmt.ExcludeWithGitignore(c.Config.GitignorePath, collectedPaths) + if err != nil { + return err + } + collectedPaths = newPaths + } + + paths, err := c.analyzePaths(collectedPaths) + if err != nil { + fmt.Printf("path analysis found the following errors:\n%v", err) + fmt.Println("Continuing...") + } + + switch c.Operation { + case yamlfmt.OperationFormat: + out, err := eng.Format(paths) + if out != nil { + fmt.Print(out) + } + if err != nil { + return err + } + case yamlfmt.OperationLint: + out, err := eng.Lint(paths) + if err != nil { + return err + } + if out != nil { + // This will be picked up by log.Fatal in main() and + // cause an exit code of 1, which is a critical + // component of the lint functionality. + return errors.New(out.String()) + } + case yamlfmt.OperationDry: + out, err := eng.DryRun(paths) + if err != nil { + return err + } + if out != nil { + fmt.Print(out) + } else if !c.Quiet { + fmt.Println("No files will be changed.") + } + case yamlfmt.OperationStdin: + stdinYaml, err := readFromStdin() + if err != nil { + return err + } + out, err := eng.FormatContent(stdinYaml) + if err != nil { + return err + } + fmt.Print(string(out)) + case yamlfmt.OperationPrintConfig: + commandConfig := map[string]any{} + err = mapstructure.Decode(c.Config, &commandConfig) + if err != nil { + return err + } + delete(commandConfig, "formatter") + out, err := yaml.Marshal(commandConfig) + if err != nil { + return err + } + fmt.Print(string(out)) + + formatterConfigMap, err := formatter.ConfigMap() + if err != nil { + return err + } + out, err = yaml.Marshal(map[string]any{ + "formatter": formatterConfigMap, + }) + if err != nil { + return err + } + fmt.Print(string(out)) + } + + return nil +} + +func (c *Command) getFormatter() (yamlfmt.Formatter, error) { + var factoryType string + + // In the existing codepaths, this value is always set. But + // it's a habit of mine to check anything that can possibly be nil + // if I remember that to be the case. :) + if c.Config.FormatterConfig != nil { + factoryType = c.Config.FormatterConfig.Type + + // The line ending set within the formatter settings takes precedence over setting + // it from the top level config. If it's not set in formatter settings, then + // we use the value from the top level. + if _, ok := c.Config.FormatterConfig.FormatterSettings["line_ending"]; !ok { + c.Config.FormatterConfig.FormatterSettings["line_ending"] = c.Config.LineEnding + } + } + + factory, err := c.Registry.GetFactory(factoryType) + if err != nil { + return nil, err + } + return factory.NewFormatter(c.Config.FormatterConfig.FormatterSettings) +} + +func (c *Command) collectPaths() ([]string, error) { + collector, err := c.makePathCollector() + if err != nil { + return nil, err + } + + return collector.CollectPaths() +} + +func (c *Command) analyzePaths(paths []string) ([]string, error) { + analyzer, err := c.makeAnalyzer() + if err != nil { + return nil, err + } + includePaths, _, err := analyzer.ExcludePathsByContent(paths) + return includePaths, err +} + +func (c *Command) makePathCollector() (yamlfmt.PathCollector, error) { + switch c.Config.MatchType { + case yamlfmt.MatchTypeDoublestar: + return &yamlfmt.DoublestarCollector{ + Include: c.Config.Include, + Exclude: c.Config.Exclude, + }, nil + case yamlfmt.MatchTypeGitignore: + files := c.Config.Include + if len(files) == 0 { + files = []string{yamlfmt.DefaultPatternFile} + } + + patternFile, err := yamlfmt.NewPatternFileCollector(files...) + if err != nil { + return nil, fmt.Errorf("NewPatternFile(%q): %w", files, err) + } + + return patternFile, nil + default: + return &yamlfmt.FilepathCollector{ + Include: c.Config.Include, + Exclude: c.Config.Exclude, + Extensions: c.Config.Extensions, + }, nil + } +} + +func (c *Command) makeAnalyzer() (yamlfmt.ContentAnalyzer, error) { + return yamlfmt.NewBasicContentAnalyzer(c.Config.RegexExclude) +} + +func readFromStdin() ([]byte, error) { + stdin := bufio.NewReader(os.Stdin) + data := []byte{} + for { + b, err := stdin.ReadByte() + if err != nil { + if err == io.EOF { + break + } else { + return nil, err + } + } + data = append(data, b) + } + return data, nil +} |
