Skip to content

Commit

Permalink
feat(pkg/commands): provide ExitCodeError to use in place of os.Exit (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
thehowl authored May 30, 2024
1 parent 98bd124 commit 4940836
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 16 deletions.
10 changes: 4 additions & 6 deletions gnovm/cmd/gno/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import (
)

type lintCfg struct {
verbose bool
rootDir string
setExitStatus int
verbose bool
rootDir string
// min_confidence: minimum confidence of a problem to print it (default 0.8)
// auto-fix: apply suggested fixes automatically.
}
Expand All @@ -48,7 +47,6 @@ func (c *lintCfg) RegisterFlags(fs *flag.FlagSet) {

fs.BoolVar(&c.verbose, "v", false, "verbose output when lintning")
fs.StringVar(&c.rootDir, "root-dir", rootdir, "clone location of github.com/gnolang/gno (gno tries to guess it)")
fs.IntVar(&c.setExitStatus, "set-exit-status", 1, "set exit status to 1 if any issues are found")
}

func execLint(cfg *lintCfg, args []string, io commands.IO) error {
Expand Down Expand Up @@ -135,8 +133,8 @@ func execLint(cfg *lintCfg, args []string, io commands.IO) error {
// TODO: Add more checkers
}

if hasError && cfg.setExitStatus != 0 {
os.Exit(cfg.setExitStatus)
if hasError {
return commands.ExitCodeError(1)
}

return nil
Expand Down
19 changes: 12 additions & 7 deletions gnovm/cmd/gno/lint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@ func TestLintApp(t *testing.T) {
args: []string{"lint"},
errShouldBe: "flag: help requested",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/run_main/"},
args: []string{"lint", "../../tests/integ/run_main/"},
stderrShouldContain: "./../../tests/integ/run_main: missing 'gno.mod' file (code=1).",
errShouldBe: "exit code: 1",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/undefined_variable_test/undefined_variables_test.gno"},
args: []string{"lint", "../../tests/integ/undefined_variable_test/undefined_variables_test.gno"},
stderrShouldContain: "undefined_variables_test.gno:6: name toto not declared (code=2)",
errShouldBe: "exit code: 1",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/package_not_declared/main.gno"},
args: []string{"lint", "../../tests/integ/package_not_declared/main.gno"},
stderrShouldContain: "main.gno:4: name fmt not declared (code=2).",
errShouldBe: "exit code: 1",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/several-lint-errors/main.gno"},
args: []string{"lint", "../../tests/integ/several-lint-errors/main.gno"},
stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-lint-errors/main.gno:6",
errShouldBe: "exit code: 1",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/run_main/"},
args: []string{"lint", "../../tests/integ/run_main/"},
stderrShouldContain: "./../../tests/integ/run_main: missing 'gno.mod' file (code=1).",
errShouldBe: "exit code: 1",
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/minimalist_gnomod/"},
args: []string{"lint", "../../tests/integ/minimalist_gnomod/"},
// TODO: raise an error because there is a gno.mod, but no .gno files
}, {
args: []string{"lint", "--set-exit-status=0", "../../tests/integ/invalid_module_name/"},
args: []string{"lint", "../../tests/integ/invalid_module_name/"},
// TODO: raise an error because gno.mod is invalid
},

Expand Down
2 changes: 1 addition & 1 deletion gnovm/cmd/gno/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func parseFiles(fnames []string, stderr io.WriteCloser) ([]*gno.FileNode, error)
}

if hasError {
os.Exit(1)
return nil, commands.ExitCodeError(1)
}
return files, nil
}
Expand Down
2 changes: 1 addition & 1 deletion gnovm/cmd/gno/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func gnoTestPkg(
})

if hasError {
os.Exit(1)
return commands.ExitCodeError(1)
}
testPkgName := getPkgNameFromFileset(ifiles)

Expand Down
10 changes: 9 additions & 1 deletion tm2/pkg/commands/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,17 @@ func (c *Command) AddSubCommands(cmds ...*Command) {
// handles the flag.ErrHelp error, ensuring that every command with -h or
// --help won't show an error message:
// 'error parsing commandline arguments: flag: help requested'
//
// Additionally, any error of type [ErrExitCode] will be handled by exiting with
// the given status code.
func (c *Command) Execute(ctx context.Context, args []string) {
if err := c.ParseAndRun(ctx, args); err != nil {
if !errors.Is(err, flag.ErrHelp) {
var ece ExitCodeError
switch {
case errors.Is(err, flag.ErrHelp): // just exit with 1 (help already printed)
case errors.As(err, &ece):
os.Exit(int(ece))
default:
_, _ = fmt.Fprintf(os.Stderr, "%+v\n", err)
}
os.Exit(1)
Expand Down
16 changes: 16 additions & 0 deletions tm2/pkg/commands/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package commands

import (
"strconv"
)

// ExitCodeError is an error to terminate the program without printing any error,
// but passing in the given exit code to os.Exit.
//
// [Command.ParseAndRun] will return any ExitCodeError encountered, but
// [Command.Execute] will handle it and return an appropriate error message.
type ExitCodeError int

func (e ExitCodeError) Error() string {
return "exit code: " + strconv.Itoa(int(e))
}

0 comments on commit 4940836

Please sign in to comment.