github.com/jdhenke/godel@v0.0.0-20161213181855-abeb3861bf0d/apps/okgo/cmd/check.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "fmt" 19 "io" 20 "strings" 21 22 "github.com/nmiyake/pkg/dirs" 23 "github.com/palantir/amalgomate/amalgomated" 24 "github.com/palantir/pkg/cli" 25 "github.com/palantir/pkg/cli/cfgcli" 26 "github.com/palantir/pkg/cli/flag" 27 "github.com/palantir/pkg/pkgpath" 28 "github.com/pkg/errors" 29 30 "github.com/palantir/godel/apps/okgo/checkoutput" 31 "github.com/palantir/godel/apps/okgo/checks" 32 "github.com/palantir/godel/apps/okgo/cmd/cmdlib" 33 "github.com/palantir/godel/apps/okgo/config" 34 "github.com/palantir/godel/apps/okgo/params" 35 ) 36 37 const packagesFlagName = "packages" 38 39 var packagesFlag = flag.StringSlice{ 40 Name: packagesFlagName, 41 Usage: "Packages to check", 42 Optional: true, 43 } 44 45 func RunAllCommand(supplier amalgomated.CmderSupplier) cli.Command { 46 return cli.Command{ 47 Name: "runAll", 48 Usage: "Run all checks", 49 Flags: []flag.Flag{ 50 packagesFlag, 51 }, 52 Action: func(ctx cli.Context) error { 53 cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON) 54 if err != nil { 55 return err 56 } 57 wd, err := dirs.GetwdEvalSymLinks() 58 if err != nil { 59 return err 60 } 61 return DoRunAll(ctx.Slice(packagesFlagName), cfg, supplier, wd, ctx.App.Stdout) 62 }, 63 } 64 } 65 66 func DoRunAll(pkgs []string, cfg params.OKGo, supplier amalgomated.CmderSupplier, wd string, stdout io.Writer) error { 67 var checksWithOutput []amalgomated.Cmd 68 for _, cmd := range cmdlib.Instance().Cmds() { 69 // if "omit" is true, skip the check 70 if cmdCfg, ok := cfg.Checks[cmd]; ok && cmdCfg.Skip { 71 continue 72 } 73 74 cmder, err := supplier(cmd) 75 if err != nil { 76 return errors.Wrapf(err, "%s is not a valid command", cmd.Name()) 77 } 78 79 producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, pkgs, wd, stdout) 80 if err != nil { 81 // indicates unexpected hard failure -- check returning non-0 exit code will not trigger 82 return errors.Wrapf(err, "check %s failed", cmd.Name()) 83 } 84 85 if producedOutput { 86 checksWithOutput = append(checksWithOutput, cmd) 87 } 88 } 89 90 if len(checksWithOutput) != 0 { 91 return errors.Errorf("Checks produced output: %v", checksWithOutput) 92 } 93 return nil 94 } 95 96 func SingleCheckCommand(cmd amalgomated.Cmd, supplier amalgomated.CmderSupplier) cli.Command { 97 return cli.Command{ 98 Name: cmd.Name(), 99 Usage: "Run " + cmd.Name(), 100 Flags: []flag.Flag{ 101 packagesFlag, 102 }, 103 Action: func(ctx cli.Context) error { 104 cfg, err := config.Load(cfgcli.ConfigPath, cfgcli.ConfigJSON) 105 if err != nil { 106 return err 107 } 108 wd, err := dirs.GetwdEvalSymLinks() 109 if err != nil { 110 return err 111 } 112 113 cmder, err := supplier(cmd) 114 if err != nil { 115 return errors.Wrapf(err, "failed to create Cmder for %s", cmd.Name()) 116 } 117 118 if producedOutput, err := executeSingleCheckWithOutput(cmd, cmder, cfg, ctx.Slice(packagesFlagName), wd, ctx.App.Stdout); producedOutput { 119 return fmt.Errorf("") 120 } else if err != nil { 121 return err 122 } 123 return nil 124 }, 125 } 126 } 127 128 // executeSingleCheckWithOutput runs the specified check and outputs the result to stdOut. Returns true if the check 129 // produced any output, false otherwise. 130 func executeSingleCheckWithOutput(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, wd string, stdout io.Writer) (bool, error) { 131 output, err := singleCheck(cmd, cmder, cfg, pkgs, wd, stdout) 132 if err != nil { 133 return false, err 134 } 135 136 producedOutput := len(output) != 0 137 if producedOutput { 138 outputLines := make([]string, len(output)) 139 for i, currLine := range output { 140 outputLines[i] = currLine.String() 141 } 142 fmt.Fprintln(stdout, strings.Join(outputLines, "\n")) 143 } 144 return producedOutput, nil 145 } 146 147 func singleCheck(cmd amalgomated.Cmd, cmder amalgomated.Cmder, cfg params.OKGo, pkgs []string, cmdWd string, stdout io.Writer) ([]checkoutput.Issue, error) { 148 checker, err := checks.GetChecker(cmd) 149 if err != nil { 150 return nil, err 151 } 152 153 fmt.Fprintf(stdout, "Running %v...\n", cmd.Name()) 154 155 if len(pkgs) == 0 { 156 // if no arguments were provided, run check on "all" 157 return checker.Check(cmder, cmdWd, cfg) 158 } 159 160 // convert arguments to packages 161 packages, err := pkgpath.PackagesFromPaths(cmdWd, pkgs) 162 if err != nil { 163 return nil, errors.Wrapf(err, "failed to convert arguments to packages: %v", pkgs) 164 } 165 166 // run check on specified packages 167 return checker.CheckPackages(cmder, packages, cfg) 168 }