package cli import ( "errors" "flag" "fmt" "io" "os" "path/filepath" "git.vakhrushev.me/av/convy/internal/check" "git.vakhrushev.me/av/convy/internal/manifest" "git.vakhrushev.me/av/convy/internal/suite" ) func runSuiteCheck(env Env, args []string) ExitCode { fs := flag.NewFlagSet("convy suite check", flag.ContinueOnError) fs.SetOutput(env.Err) root := fs.String("root", "", "root of the suite; by default it is looked up upwards from the current directory") quiet := fs.Bool("quiet", false, "print findings only") if err := fs.Parse(args); err != nil { return Usage } dir := *root if dir == "" { found, err := manifest.Find(env.Dir) if err != nil { if errors.Is(err, manifest.ErrNotFound) { fmt.Fprintf(env.Err, "not a conventions suite: no %s here or above\n", manifest.Name) if _, err := os.Stat(filepath.Join(env.Dir, ".conventions.toml")); err == nil { fmt.Fprintln(env.Err, "this is a project — checking what is here is called \"convy check\"") } return Usage } fmt.Fprintln(env.Err, err) return Usage } dir = found } s, err := suite.Load(dir) if err != nil { fmt.Fprintln(env.Err, err) return Usage } rep := check.Suite(s) printReport(env.Out, rep, s, *quiet) if rep.Errors() > 0 { return Failed } return OK } func printReport(w io.Writer, rep *check.Report, s *suite.Suite, quiet bool) { findings := rep.Findings() current := "" for _, f := range findings { if f.Path != current { if current != "" { fmt.Fprintln(w) } fmt.Fprintf(w, "%s\n", f.Path) current = f.Path } where := "" if f.Line > 0 { where = fmt.Sprintf(":%d", f.Line) } fmt.Fprintf(w, " %s%s %s [%s]\n", f.Severity, where, f.Msg, f.Family) } if quiet { return } if len(findings) > 0 { fmt.Fprintln(w) } fmt.Fprintf(w, "suite: %s, %s, language version %d (%s)\n", plural(len(s.Docs), "file"), plural(len(s.Manifest.LiveTopics()), "topic"), s.Manifest.Language.Version, s.Manifest.Language.Lang) switch { case rep.Errors() > 0: fmt.Fprintf(w, "errors: %d, warnings: %d\n", rep.Errors(), rep.Warnings()) case rep.Warnings() > 0: fmt.Fprintf(w, "no errors, warnings: %d\n", rep.Warnings()) default: fmt.Fprintln(w, "suite integrity holds") } } // plural agrees a noun with a count: 1 file, 4 files. func plural(n int, noun string) string { if n == 1 { return fmt.Sprintf("%d %s", n, noun) } return fmt.Sprintf("%d %ss", n, noun) }