github.com/mattdotmatt/gauge@v0.3.2-0.20160421115137-425a4cdccb62/gauge.go (about)

     1  // Copyright 2015 ThoughtWorks, Inc.
     2  
     3  // This file is part of Gauge.
     4  
     5  // Gauge is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  
    10  // Gauge is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  
    15  // You should have received a copy of the GNU General Public License
    16  // along with Gauge.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package main
    19  
    20  import (
    21  	"encoding/json"
    22  	"fmt"
    23  	"os"
    24  	"path/filepath"
    25  	"time"
    26  
    27  	"github.com/getgauge/common"
    28  	"github.com/getgauge/gauge/api"
    29  	"github.com/getgauge/gauge/config"
    30  	"github.com/getgauge/gauge/env"
    31  	"github.com/getgauge/gauge/execution"
    32  	"github.com/getgauge/gauge/filter"
    33  	"github.com/getgauge/gauge/formatter"
    34  	"github.com/getgauge/gauge/logger"
    35  	"github.com/getgauge/gauge/plugin"
    36  	"github.com/getgauge/gauge/refactor"
    37  	"github.com/getgauge/gauge/reporter"
    38  	"github.com/getgauge/gauge/validation"
    39  	"github.com/getgauge/gauge/version"
    40  
    41  	"github.com/getgauge/gauge/plugin/install"
    42  	"github.com/getgauge/gauge/projectInit"
    43  	"github.com/getgauge/gauge/util"
    44  	flag "github.com/getgauge/mflag"
    45  )
    46  
    47  // Command line flags
    48  var daemonize = flag.Bool([]string{"-daemonize"}, false, "Run as a daemon")
    49  var gaugeVersion = flag.Bool([]string{"v", "-version", "version"}, false, "Print the current version and exit. Eg: gauge --version")
    50  var verbosity = flag.Bool([]string{"-verbose"}, false, "Enable step level reporting on console, default being scenario level. Eg: gauge --verbose specs")
    51  var logLevel = flag.String([]string{"-log-level"}, "", "Set level of logging to debug, info, warning, error or critical")
    52  var simpleConsoleOutput = flag.Bool([]string{"-simple-console"}, false, "Removes colouring and simplifies from the console output")
    53  var initialize = flag.String([]string{"-init"}, "", "Initializes project structure in the current directory. Eg: gauge --init java")
    54  var installPlugin = flag.String([]string{"-install"}, "", "Downloads and installs a plugin. Eg: gauge --install java")
    55  var uninstallPlugin = flag.String([]string{"-uninstall"}, "", "Uninstalls a plugin. Eg: gauge --uninstall java")
    56  var installAll = flag.Bool([]string{"-install-all"}, false, "Installs all the plugins specified in project manifest, if not installed. Eg: gauge --install-all")
    57  var update = flag.String([]string{"-update"}, "", "Updates a plugin. Eg: gauge --update java")
    58  var pluginVersion = flag.String([]string{"-plugin-version"}, "", "Version of plugin to be installed. This is used with --install")
    59  var installZip = flag.String([]string{"-file", "f"}, "", "Installs the plugin from zip file. This is used with --install. Eg: gauge --install java -f ZIP_FILE")
    60  var currentEnv = flag.String([]string{"-env"}, "default", "Specifies the environment. If not specified, default will be used")
    61  var addPlugin = flag.String([]string{"-add-plugin"}, "", "Adds the specified non-language plugin to the current project")
    62  var pluginArgs = flag.String([]string{"-plugin-args"}, "", "Specified additional arguments to the plugin. This is used together with --add-plugin")
    63  var specFilesToFormat = flag.String([]string{"-format"}, "", "Formats the specified spec files")
    64  var executeTags = flag.String([]string{"-tags"}, "", "Executes the specs and scenarios tagged with given tags. Eg: gauge --tags tag1,tag2 specs")
    65  var tableRows = flag.String([]string{"-table-rows"}, "", "Executes the specs and scenarios only for the selected rows. Eg: gauge --table-rows \"1-3\" specs/hello.spec")
    66  var apiPort = flag.String([]string{"-api-port"}, "", "Specifies the api port to be used. Eg: gauge --daemonize --api-port 7777")
    67  var refactorSteps = flag.String([]string{"-refactor"}, "", "Refactor steps. Eg: gauge --refactor <old step> <new step> [[spec directories]]")
    68  var parallel = flag.Bool([]string{"-parallel", "p"}, false, "Execute specs in parallel")
    69  var numberOfExecutionStreams = flag.Int([]string{"n"}, util.NumberOfCores(), "Specify number of parallel execution streams")
    70  var distribute = flag.Int([]string{"g", "-group"}, -1, "Specify which group of specification to execute based on -n flag")
    71  var workingDir = flag.String([]string{"-dir"}, ".", "Set the working directory for the current command, accepts a path relative to current directory.")
    72  var strategy = flag.String([]string{"-strategy"}, "lazy", "Set the parallelization strategy for execution. Possible options are: `eager`, `lazy`. Ex: gauge -p --strategy=\"eager\"")
    73  var doNotRandomize = flag.Bool([]string{"-sort", "s"}, false, "Run specs in Alphabetical Order. Eg: gauge -s specs")
    74  var validate = flag.Bool([]string{"-validate", "#-check"}, false, "Check for validation and parse errors. Eg: gauge --validate specs")
    75  var updateAll = flag.Bool([]string{"-update-all"}, false, "Updates all the installed Gauge plugins. Eg: gauge --update-all")
    76  var checkUpdates = flag.Bool([]string{"-check-updates"}, false, "Checks for Gauge and plugins updates. Eg: gauge --check-updates")
    77  var listTemplates = flag.Bool([]string{"-list-templates"}, false, "Lists all the Gauge templates available. Eg: gauge --list-templates")
    78  var machineReadable = flag.Bool([]string{"-machine-readable"}, false, "Used with `--version` to produce JSON output of currently installed Gauge and plugin versions. e.g: gauge --version --machine-readable")
    79  
    80  func main() {
    81  	flag.Parse()
    82  	util.SetWorkingDir(*workingDir)
    83  	initPackageFlags()
    84  	validGaugeProject := true
    85  	err := config.SetProjectRoot(flag.Args())
    86  	if err != nil {
    87  		validGaugeProject = false
    88  	}
    89  	env.LoadEnv(*currentEnv)
    90  	logger.Initialize(*logLevel)
    91  	if *gaugeVersion && *machineReadable {
    92  		printJSONVersion()
    93  	} else if *machineReadable {
    94  		fmt.Printf("flag '--machine-readable' can only be used with '--version' or '-v'\n\n")
    95  		fmt.Printf("Usage:\n\n")
    96  		flag.PrintDefaults()
    97  		os.Exit(1)
    98  	} else if *gaugeVersion {
    99  		printVersion()
   100  	} else if *initialize != "" {
   101  		projectInit.InitializeProject(*initialize)
   102  	} else if *installZip != "" && *installPlugin != "" {
   103  		install.HandleInstallResult(install.InstallPluginFromZipFile(*installZip, *installPlugin), *installPlugin, true)
   104  	} else if *installPlugin != "" {
   105  		install.HandleInstallResult(install.InstallPlugin(*installPlugin, *pluginVersion), *installPlugin, true)
   106  	} else if *uninstallPlugin != "" {
   107  		install.UninstallPlugin(*uninstallPlugin, *pluginVersion)
   108  	} else if *installAll {
   109  		install.InstallAllPlugins()
   110  	} else if *update != "" {
   111  		install.HandleUpdateResult(install.InstallPlugin(*update, *pluginVersion), *update, true)
   112  	} else if *updateAll {
   113  		install.UpdatePlugins()
   114  	} else if *checkUpdates {
   115  		install.PrintUpdateInfoWithDetails()
   116  	} else if *addPlugin != "" {
   117  		install.AddPluginToProject(*addPlugin, *pluginArgs)
   118  	} else if *listTemplates {
   119  		projectInit.ListTemplates()
   120  	} else if flag.NFlag() == 0 && len(flag.Args()) == 0 {
   121  		printUsage()
   122  		os.Exit(0)
   123  	} else if validGaugeProject {
   124  		var specDirs = []string{common.SpecsDirectoryName}
   125  		if len(flag.Args()) > 0 {
   126  			specDirs = flag.Args()
   127  		}
   128  		if *refactorSteps != "" {
   129  			refactorInit(flag.Args())
   130  		} else if *daemonize {
   131  			api.RunInBackground(*apiPort, specDirs)
   132  		} else if *specFilesToFormat != "" {
   133  			formatter.FormatSpecFilesIn(*specFilesToFormat)
   134  		} else if *validate {
   135  			validation.Validate(flag.Args())
   136  		} else {
   137  			exitCode := execution.ExecuteSpecs(specDirs)
   138  			os.Exit(exitCode)
   139  		}
   140  	} else {
   141  		logger.Fatalf(err.Error())
   142  	}
   143  }
   144  
   145  func refactorInit(args []string) {
   146  	if len(args) < 1 {
   147  		logger.Fatalf("Flag needs at least two arguments: --refactor\nUsage : gauge --refactor <old step> <new step> [[spec directories]]")
   148  	}
   149  	var specDirs = []string{common.SpecsDirectoryName}
   150  	if len(args) > 1 {
   151  		specDirs = args[1:]
   152  	}
   153  	startChan := api.StartAPI()
   154  	refactor.RefactorSteps(*refactorSteps, args[0], startChan, specDirs)
   155  }
   156  
   157  func printJSONVersion() {
   158  	type pluginJSON struct {
   159  		Name    string `json:"name"`
   160  		Version string `json:"version"`
   161  	}
   162  	type versionJSON struct {
   163  		Version string        `json:"version"`
   164  		Plugins []*pluginJSON `json:"plugins"`
   165  	}
   166  	gaugeVersion := versionJSON{version.FullVersion(), make([]*pluginJSON, 0)}
   167  	allPluginsWithVersion, err := plugin.GetAllInstalledPluginsWithVersion()
   168  	for _, pluginInfo := range allPluginsWithVersion {
   169  		gaugeVersion.Plugins = append(gaugeVersion.Plugins, &pluginJSON{pluginInfo.Name, filepath.Base(pluginInfo.Path)})
   170  	}
   171  	b, err := json.MarshalIndent(gaugeVersion, "", "    ")
   172  	if err != nil {
   173  		fmt.Println("error:", err)
   174  	}
   175  	fmt.Println(fmt.Sprintf("%s\n", string(b)))
   176  }
   177  
   178  func printVersion() {
   179  	fmt.Printf("Gauge version: %s\n\n", version.FullVersion())
   180  	fmt.Println("Plugins\n-------")
   181  	allPluginsWithVersion, err := plugin.GetAllInstalledPluginsWithVersion()
   182  	if err != nil {
   183  		fmt.Println("No plugins found")
   184  		fmt.Println("Plugins can be installed with `gauge --install {plugin-name}`")
   185  		os.Exit(0)
   186  	}
   187  	for _, pluginInfo := range allPluginsWithVersion {
   188  		fmt.Printf("%s (%s)\n", pluginInfo.Name, filepath.Base(pluginInfo.Path))
   189  	}
   190  }
   191  
   192  func printUsage() {
   193  	fmt.Printf("gauge -version %s\n", version.FullVersion())
   194  	fmt.Printf("Copyright %d ThoughtWorks, Inc.\n\n", time.Now().Year())
   195  	fmt.Println("Usage:")
   196  	fmt.Println("\tgauge specs/")
   197  	fmt.Println("\tgauge specs/spec_name.spec")
   198  	fmt.Println("\nOptions:")
   199  	flag.PrintDefaults()
   200  }
   201  
   202  func initPackageFlags() {
   203  	if *parallel {
   204  		*simpleConsoleOutput = true
   205  	}
   206  	reporter.SimpleConsoleOutput = *simpleConsoleOutput
   207  	reporter.Verbose = *verbosity
   208  	execution.ExecuteTags = *executeTags
   209  	execution.TableRows = *tableRows
   210  	execution.NumberOfExecutionStreams = *numberOfExecutionStreams
   211  	execution.InParallel = *parallel
   212  	filter.ExecuteTags = *executeTags
   213  	filter.DoNotRandomize = *doNotRandomize
   214  	filter.Distribute = *distribute
   215  	filter.NumberOfExecutionStreams = *numberOfExecutionStreams
   216  	execution.Strategy = *strategy
   217  	if *distribute != -1 {
   218  		execution.Strategy = execution.Eager
   219  	}
   220  }