github.com/clusterize-io/tusk@v0.6.3-0.20211001020217-cfe8a8cd0d4a/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "os/exec" 8 "syscall" 9 10 "github.com/clusterize-io/tusk/appcli" 11 "github.com/clusterize-io/tusk/runner" 12 "github.com/clusterize-io/tusk/ui" 13 "github.com/urfave/cli" 14 ) 15 16 var version = "v6.2.1" 17 18 func main() { 19 status := run(config{ 20 args: os.Args, 21 stdout: os.Stdout, 22 stderr: os.Stderr, 23 }) 24 os.Exit(status) 25 } 26 27 type config struct { 28 args []string 29 stdout io.Writer 30 stderr io.Writer 31 } 32 33 func run(cfg config) (status int) { 34 defer func() { 35 if r := recover(); r != nil { 36 if !appcli.IsCompleting(cfg.args) { 37 err := fmt.Errorf("recovered from panic: %v", r) 38 ui.New().Error(err) 39 } 40 41 if status == 0 { 42 status = 1 43 } 44 } 45 }() 46 47 meta, err := appcli.GetConfigMetadata(cfg.args) 48 if err != nil { 49 if !appcli.IsCompleting(cfg.args) { 50 ui.New().Error(err) 51 } 52 return 1 53 } 54 55 meta.Logger.Stdout = cfg.stdout 56 meta.Logger.Stderr = cfg.stderr 57 58 status, err = runMeta(meta, cfg.args) 59 if err != nil { 60 meta.Logger.Error(err) 61 if status == 0 { 62 return 1 63 } 64 } 65 66 return status 67 } 68 69 func runMeta(meta *runner.Metadata, args []string) (exitStatus int, err error) { 70 printHelp := false 71 72 switch { 73 case appcli.IsCompleting(args): 74 case meta.PrintHelp: 75 printHelp = true 76 case meta.PrintVersion: 77 meta.Logger.Println(version) 78 return 0, nil 79 case meta.InstallCompletion != "": 80 return 0, appcli.InstallCompletion(meta) 81 case meta.UninstallCompletion != "": 82 return 0, appcli.UninstallCompletion(meta) 83 } 84 85 // TODO: Use runner.Context to avoid doing this 86 if err = os.Chdir(meta.Directory); err != nil { 87 return 1, err 88 } 89 90 app, err := appcli.NewApp(args, meta) 91 if err != nil { 92 return 1, err 93 } 94 95 if printHelp { 96 appcli.ShowAppHelp(meta.Logger, app) 97 return 0, nil 98 } 99 100 return runApp(app, meta, args) 101 } 102 103 func runApp(app *cli.App, meta *runner.Metadata, args []string) (int, error) { 104 if err := app.Run(args); err != nil { 105 if exitErr, ok := err.(*exec.ExitError); ok { 106 if meta.Logger.Verbosity < ui.VerbosityLevelVerbose { 107 err = nil 108 } 109 ws := exitErr.Sys().(syscall.WaitStatus) 110 return ws.ExitStatus(), err 111 } 112 113 return 1, err 114 } 115 116 return 0, nil 117 }