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  }