diff --git a/cmd/tldr/main.go b/cmd/tldr/main.go index fbded0e..7339a5e 100644 --- a/cmd/tldr/main.go +++ b/cmd/tldr/main.go @@ -4,6 +4,7 @@ import ( "os" "github.com/TheRootDaemon/tlgc/cmd" + "github.com/TheRootDaemon/tlgc/exitcode" "github.com/TheRootDaemon/tlgc/internal/app" "github.com/TheRootDaemon/tlgc/logger" ) @@ -12,7 +13,7 @@ func main() { cli, err := cmd.Parse() if err != nil { logger.Error("%v", err) - os.Exit(1) + os.Exit(exitcode.InvalidArguments) } logger.SetDefault( diff --git a/exitcode/exitcode.go b/exitcode/exitcode.go new file mode 100644 index 0000000..c977de8 --- /dev/null +++ b/exitcode/exitcode.go @@ -0,0 +1,16 @@ +// Package exitcode defines the exit status codes used by tlgc. +package exitcode + +const ( + // Success indicates that the command completed sucessfully. + Success int = iota + + // InvalidArguments indicates that the command was invoked with invalid arguments. + InvalidArguments + + // CacheUpdateFailure indicates that updating the cache failed. + CacheUpdateFailure + + // LintFailure indicates that the tldr page has lint error(s). + LintFailure +) diff --git a/internal/app/app.go b/internal/app/app.go index f8ad6fc..c8dc435 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -5,6 +5,7 @@ import ( "os" "github.com/TheRootDaemon/tlgc/cmd" + "github.com/TheRootDaemon/tlgc/exitcode" "github.com/TheRootDaemon/tlgc/internal/config" "github.com/TheRootDaemon/tlgc/locale" "github.com/TheRootDaemon/tlgc/logger" @@ -89,7 +90,8 @@ func New(opts ...Option) *App { // Otherwise the command is delegated // to dispatch, whose result becomes the exit code. // -// It returns 0 on success and 1 on error. +// It returns [exitcode.Success] on success, +// or the corresponding error-specific exitcode on failure. func (a *App) Run(cli *cmd.CLI) int { needsConfig := !cli.GenConfig && !cli.ConfigPath && !cli.ShowVersion && !cli.ShowHelp @@ -103,7 +105,7 @@ func (a *App) Run(cli *cmd.CLI) int { if shouldAutoUpdate(cli) { if err := a.autoUpdate(cli); err != nil { logger.Error("failed to update cache: %v", err) - return 1 + return exitcode.CacheUpdateFailure } } @@ -119,7 +121,8 @@ func (a *App) Run(cli *cmd.CLI) int { // win over the bare page-lookup that handles positional arguments in cli.Page. // When no case matches, the command is a no-op and returns 0. // -// It returns 0 on success and 1 on error. +// It returns [exitcode.Success] on success, +// or the corresponding error-specific exitcode on failure. func (a *App) dispatch(cli *cmd.CLI) int { switch { case cli.Update: @@ -153,7 +156,7 @@ func (a *App) dispatch(cli *cmd.CLI) int { case len(cli.Page) > 0: return a.lookupAndRenderPage(cli) default: - return 0 + return exitcode.Success } } diff --git a/internal/app/format.go b/internal/app/format.go index a7debe9..5871fc5 100644 --- a/internal/app/format.go +++ b/internal/app/format.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/TheRootDaemon/tlgc/cmd" + "github.com/TheRootDaemon/tlgc/exitcode" "github.com/TheRootDaemon/tlgc/internal/lint" "github.com/TheRootDaemon/tlgc/logger" "github.com/TheRootDaemon/tlgc/termcolor" @@ -16,8 +17,8 @@ import ( // back to the source file, or to a single output file // depending on the flags. // -// It returns 0 when every page formatted without lint errors and 1 -// otherwise. +// It returns [exitcode.Success] when every page formatted without lint errors +// and 1 otherwise. func (a *App) formatPages(cli *cmd.CLI) int { files, err := collectFiles(cli.Page) if err != nil { @@ -51,7 +52,7 @@ func (a *App) formatPages(cli *cmd.CLI) int { } if failed { - return 1 + return exitcode.LintFailure } return 0 diff --git a/internal/app/lint.go b/internal/app/lint.go index 4c2ca5e..04e3645 100644 --- a/internal/app/lint.go +++ b/internal/app/lint.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/TheRootDaemon/tlgc/cmd" + "github.com/TheRootDaemon/tlgc/exitcode" "github.com/TheRootDaemon/tlgc/internal/lint" "github.com/TheRootDaemon/tlgc/logger" "github.com/TheRootDaemon/tlgc/termcolor" @@ -21,7 +22,7 @@ type lintViolation struct { // lintPages runs the linter over every page reachable // from the CLI paths and reports each violation to stderr. // -// It returns 0 when every file passed without violations +// It returns [exitcode.Success] when every file passed without violations // and 1 otherwise; // a failure to collect or open any file is logged and also yields 1. func (a *App) lintPages(cli *cmd.CLI) int { @@ -56,7 +57,7 @@ func (a *App) lintPages(cli *cmd.CLI) int { } if failed { - return 1 + return exitcode.LintFailure } return 0 diff --git a/internal/app/update.go b/internal/app/update.go index 950b19d..c563f6d 100644 --- a/internal/app/update.go +++ b/internal/app/update.go @@ -4,6 +4,7 @@ import ( "context" "github.com/TheRootDaemon/tlgc/cmd" + "github.com/TheRootDaemon/tlgc/exitcode" "github.com/TheRootDaemon/tlgc/internal/cache" "github.com/TheRootDaemon/tlgc/internal/config" "github.com/TheRootDaemon/tlgc/internal/upstream" @@ -12,7 +13,7 @@ import ( // updateCache downloads the latest tldr-pages // for the configured languages. -// Returns 0 on success, 1 on error. +// Returns [exitcode.Success] on success, [exitcode.CacheUpdateFailure] on error. func (a *App) updateCache(cli *cmd.CLI) int { c := cache.New() languages := a.resolveLanguages(cli.Languages) @@ -20,9 +21,10 @@ func (a *App) updateCache(cli *cmd.CLI) int { if err := c.Update(context.Background(), languages, client); err != nil { logger.Error("failed to update cache: %v", err) - return 1 + return exitcode.CacheUpdateFailure } - return 0 + + return exitcode.Success } // shouldAutoUpdate reports whether a stale cache maybe updated