// UninstallPlugin uninstall the given plugin of the given version // If version is not specified, it uninstalls all the versions of given plugin func UninstallPlugin(pluginName string, version string) { pluginsHome, err := common.GetPrimaryPluginsInstallDir() if err != nil { logger.Fatalf("Failed to uninstall plugin %s. %s", pluginName, err.Error()) } if !common.DirExists(filepath.Join(pluginsHome, pluginName, version)) { logger.Errorf("Plugin %s not found.", strings.TrimSpace(pluginName+" "+version)) os.Exit(0) } var failed bool pluginsDir := filepath.Join(pluginsHome, pluginName) filepath.Walk(pluginsDir, func(dir string, info os.FileInfo, err error) error { if err == nil && info.IsDir() && dir != pluginsDir && strings.HasPrefix(filepath.Base(dir), version) { if err := uninstallVersionOfPlugin(dir, pluginName, filepath.Base(dir)); err != nil { logger.Errorf("Failed to uninstall plugin %s %s. %s", pluginName, version, err.Error()) failed = true } } return nil }) if failed { os.Exit(1) } if version == "" { if err := os.RemoveAll(pluginsDir); err != nil { logger.Fatalf("Failed to remove directory %s. %s", pluginsDir, err.Error()) } } }
// InitializeProject initializes a Gauge project with specified template func InitializeProject(templateName string) { wd, err := os.Getwd() if err != nil { logger.Fatalf("Failed to find working directory. %s", err.Error()) } config.ProjectRoot = wd exists, _ := common.UrlExists(getTemplateURL(templateName)) if exists { err = initializeTemplate(templateName) } else { err = createProjectTemplate(templateName) } if err != nil { logger.Fatalf("Failed to initialize project. %s", err.Error()) } logger.Info("Successfully initialized the project. Run specifications with \"gauge specs/\"\n") language := getTemplateLangauge(templateName) if !install.IsCompatiblePluginInstalled(language, true) { logger.Info("Compatible langauge plugin %s is not installed. Installing plugin...", language) install.HandleInstallResult(install.InstallPlugin(language, ""), language, true) } }
// ListTemplates lists all the Gauge templates available in GaugeTemplatesURL func ListTemplates() { templatesURL := config.GaugeTemplatesUrl() _, err := common.UrlExists(templatesURL) if err != nil { logger.Fatalf("Gauge templates URL is not reachable: %s", err.Error()) } tempDir := common.GetTempDir() defer util.Remove(tempDir) templatesPage, err := util.Download(templatesURL, tempDir, "", true) if err != nil { util.Remove(tempDir) logger.Fatalf("Error occurred while downloading templates list: %s", err.Error()) } templatePageContents, err := common.ReadFileContents(templatesPage) if err != nil { util.Remove(tempDir) logger.Fatalf("Failed to read contents of file %s: %s", templatesPage, err.Error()) } templates := getTemplateNames(templatePageContents) for _, template := range templates { logger.Info(template) } logger.Info("\nRun `gauge --init <template_name>` to create a new Gauge project.") }
func validateFlags() { if !InParallel { return } if NumberOfExecutionStreams < 1 { logger.Fatalf("Invalid input(%s) to --n flag.", strconv.Itoa(NumberOfExecutionStreams)) } if !isValidStrategy(Strategy) { logger.Fatalf("Invalid input(%s) to --strategy flag.", Strategy) } }
// LoadEnv first loads the default env properties and then the user specified env properties. // This way user specified env variable can overwrite default if required func LoadEnv(envName string) { currentEnv = envName err := loadDefaultProperties() if err != nil { logger.Fatalf("Failed to load the default property. %s", err.Error()) } err = loadEnvDir(currentEnv) if err != nil { logger.Fatalf("Failed to load env. %s", err.Error()) } }
func InstallAllPlugins() { manifest, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } installPluginsFromManifest(manifest) }
// GetConceptFiles returns the list of concept files present in the PROJECTROOT/base_dir_of_path func GetConceptFiles(path string) []string { absPath, err := filepath.Abs(path) if err != nil { logger.Fatalf("Error getting absolute path. %v", err) } projRoot := config.ProjectRoot if projRoot == "" { logger.Fatalf("Failed to get project root. %v", err) } projRoot += string(filepath.Separator) path = strings.TrimPrefix(absPath, projRoot) path = strings.Split(path, string(filepath.Separator))[0] return FindConceptFilesIn(path) }
// RunInBackground runs Gauge in daemonized mode on the given apiPort func RunInBackground(apiPort string, specDirs []string) { var port int var err error if apiPort != "" { port, err = strconv.Atoi(apiPort) if err != nil { logger.Fatalf(fmt.Sprintf("Invalid port number: %s", apiPort)) } os.Setenv(common.APIPortEnvVariableName, apiPort) } else { port, err = conn.GetPortFromEnvironmentVariable(common.APIPortEnvVariableName) if err != nil { logger.Fatalf(fmt.Sprintf("Failed to start API Service. %s \n", err.Error())) } } runAPIServiceIndefinitely(port, specDirs) }
func validateTagExpression(tagExpression string) { filter := &ScenarioFilterBasedOnTags{tagExpression: tagExpression} filter.replaceSpecialChar() _, err := filter.formatAndEvaluateExpression(make(map[string]bool, 0), func(a map[string]bool, b string) bool { return true }) if err != nil { logger.Fatalf(err.Error()) } }
//TODO : duplicate in execute.go. Need to fix runner init. func startAPI() *runner.TestRunner { sc := api.StartAPI() select { case runner := <-sc.RunnerChan: return runner case err := <-sc.ErrorChan: logger.Fatalf("Failed to start gauge API: %s", err.Error()) } return nil }
func refactorInit(args []string) { if len(args) < 1 { logger.Fatalf("Flag needs at least two arguments: --refactor\nUsage : gauge --refactor <old step> <new step> [[spec directories]]") } var specDirs = []string{common.SpecsDirectoryName} if len(args) > 1 { specDirs = args[1:] } startChan := api.StartAPI() refactor.RefactorSteps(*refactorSteps, args[0], startChan, specDirs) }
// InitializeProject initializes a Gauge project with specified template func InitializeProject(templateName string) { wd, err := os.Getwd() if err != nil { logger.Fatalf("Failed to find working directory. %s", err.Error()) } config.ProjectRoot = wd exists, _ := common.UrlExists(getTemplateURL(templateName)) if exists { err = initializeTemplate(templateName) } else { err = createProjectTemplate(templateName) } if err != nil { logger.Fatalf("Failed to initialize. %s", err.Error()) } logger.Info("\nSuccessfully initialized the project. Run specifications with \"gauge specs/\"") }
func runAPIServiceIndefinitely(port int, wg *sync.WaitGroup) { wg.Add(1) startChan := &runner.StartChannels{RunnerChan: make(chan *runner.TestRunner), ErrorChan: make(chan error), KillChan: make(chan bool)} go StartAPIService(port, startChan) select { case runner := <-startChan.RunnerChan: runner.Kill() case err := <-startChan.ErrorChan: logger.Fatalf(err.Error()) } }
func startAPI() *runner.TestRunner { startChan := &runner.StartChannels{RunnerChan: make(chan *runner.TestRunner), ErrorChan: make(chan error), KillChan: make(chan bool)} go api.StartAPIService(0, startChan) select { case runner := <-startChan.RunnerChan: return runner case err := <-startChan.ErrorChan: logger.Fatalf("Failed to start gauge API: %s", err.Error()) } return nil }
func InstallPluginZip(zipFile string, pluginName string) { tempDir := common.GetTempDir() unzippedPluginDir, err := common.UnzipArchive(zipFile, tempDir) defer common.Remove(tempDir) if err != nil { common.Remove(tempDir) logger.Fatalf("Failed to install plugin. %s\n", err.Error()) } logger.Info("Plugin unzipped to => %s\n", unzippedPluginDir) hasPluginJSON := common.FileExists(filepath.Join(unzippedPluginDir, pluginJSON)) if hasPluginJSON { err = installPluginFromDir(unzippedPluginDir) } else { err = installRunnerFromDir(unzippedPluginDir, pluginName) } if err != nil { common.Remove(tempDir) logger.Fatalf("Failed to install plugin. %s\n", err.Error()) } logger.Info("Successfully installed plugin from file.") }
// SetWorkingDir sets the current working directory to specified location func SetWorkingDir(workingDir string) { targetDir, err := filepath.Abs(workingDir) if err != nil { logger.Fatalf("Unable to set working directory : %s", err.Error()) } if !common.DirExists(targetDir) { err = os.Mkdir(targetDir, 0777) if err != nil { logger.Fatalf("Unable to set working directory : %s", err.Error()) } } err = os.Chdir(targetDir) if err != nil { logger.Fatalf("Unable to set working directory : %s", err.Error()) } _, err = os.Getwd() if err != nil { logger.Fatalf("Unable to set working directory : %s", err.Error()) } }
func AddPluginToProject(pluginName string, pluginArgs string) { additionalArgs := make(map[string]string) if pluginArgs != "" { // plugin args will be comma separated values // eg: version=1.0, foo_version = 2.41 args := strings.Split(pluginArgs, ",") for _, arg := range args { keyValuePair := strings.Split(arg, "=") if len(keyValuePair) == 2 { additionalArgs[strings.TrimSpace(keyValuePair[0])] = strings.TrimSpace(keyValuePair[1]) } } } manifest, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } if err := addPluginToTheProject(pluginName, additionalArgs, manifest); err != nil { logger.Fatalf(fmt.Sprintf("Failed to add plugin %s to project : %s\n", pluginName, err.Error())) } else { logger.Info("Plugin %s was successfully added to the project\n", pluginName) } }
// LoadEnv first generates the map of the env vars that needs to be set. // It starts by populating the map with the env passed by the user in --env flag. // It then adds the default values of the env vars which are required by Gauge, // but are not present in the map. // // Finally, all the env vars present in the map are actually set in the shell. func LoadEnv(envName string) { envVars = make(map[string]string) currentEnv = envName err := loadEnvDir(currentEnv) if err != nil { logger.Fatalf("Failed to load env. %s", err.Error()) } if currentEnv != "default" { err := loadEnvDir("default") if err != nil { logger.Fatalf("Failed to load env. %s", err.Error()) } } loadDefaultEnvVars() err = setEnvVars() if err != nil { logger.Fatalf("Failed to load env. %s", err.Error()) } }
func Validate(args []string) { specsToExecute, conceptsDictionary := parseSpecs(args) manifest, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } runner := startAPI() errMap := validateSpecs(manifest, specsToExecute, runner, conceptsDictionary) runner.Kill() if len(errMap.stepErrs) > 0 { os.Exit(1) } logger.Info("No error found.") os.Exit(0) }
// UpdatePlugins updates all the currently installed plugins to its latest version func UpdatePlugins() { var failedPlugin []string for _, pluginInfo := range plugin.GetPluginsInfo() { logger.Info("Updating plugin '%s'", pluginInfo.Name) passed := HandleUpdateResult(InstallPlugin(pluginInfo.Name, ""), pluginInfo.Name, false) if !passed { failedPlugin = append(failedPlugin, pluginInfo.Name) } fmt.Println() } if len(failedPlugin) > 0 { logger.Fatalf("Failed to update '%s' plugins.", strings.Join(failedPlugin, ", ")) } logger.Info("Successfully updated all the plugins.") }
func newExecutionInfo(s *gauge.SpecCollection, r *runner.TestRunner, ph *plugin.Handler, rep reporter.Reporter, e *validation.ValidationErrMaps, p bool) *executionInfo { m, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } return &executionInfo{ manifest: m, specs: s, runner: r, pluginHandler: ph, consoleReporter: rep, errMaps: e, inParallel: p, numberOfStreams: NumberOfExecutionStreams, } }
func runAPIServiceIndefinitely(port int, specDirs []string) { startChan := &runner.StartChannels{RunnerChan: make(chan *runner.TestRunner), ErrorChan: make(chan error), KillChan: make(chan bool)} sig := &infoGatherer.SpecInfoGatherer{SpecDirs: specDirs} sig.MakeListOfAvailableSteps() go startAPIService(port, startChan, sig) go checkParentIsAlive(startChan) for { select { case runner := <-startChan.RunnerChan: logger.Info("Got a kill message. Killing runner.") runner.Kill() case err := <-startChan.ErrorChan: logger.Fatalf("Killing Gauge daemon. %v", err.Error()) } } }
func ValidateSpecs(args []string, r *runner.TestRunner) (*gauge.SpecCollection, *ValidationErrMaps) { s, c := parseSpecs(args) manifest, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } v := newValidator(manifest, s, r, c) vErrs := v.validate() errMap := &ValidationErrMaps{ SpecErrs: make(map[*gauge.Specification][]*StepValidationError), ScenarioErrs: make(map[*gauge.Scenario][]*StepValidationError), StepErrs: make(map[*gauge.Step]*StepValidationError), } if len(vErrs) > 0 { printValidationFailures(vErrs) fillErrors(errMap, vErrs) } return gauge.NewSpecCollection(s), errMap }
func ExecuteSpecs(args []string) int { validateFlags() if checkUpdatesDuringExecution && config.CheckUpdates() { i := &install.UpdateFacade{} i.BufferUpdateDetails() defer i.PrintUpdateBuffer() } specsToExecute, conceptsDictionary := parseSpecs(args) manifest, err := manifest.ProjectManifest() if err != nil { logger.Fatalf(err.Error()) } runner := startAPI() errMap := validateSpecs(manifest, specsToExecute, runner, conceptsDictionary) executionInfo := newExecutionInfo(manifest, &specStore{specs: specsToExecute}, runner, nil, reporter.Current(), errMap, InParallel) execution := newExecution(executionInfo) execution.start() result := execution.run() execution.finish() exitCode := printExecutionStatus(result, errMap) return exitCode }
func main() { flag.Parse() util.SetWorkingDir(*workingDir) initPackageFlags() validGaugeProject := true err := config.SetProjectRoot(flag.Args()) if err != nil { validGaugeProject = false } env.LoadEnv(*currentEnv) logger.Initialize(*logLevel) if *gaugeVersion && *machineReadable { printJSONVersion() } else if *machineReadable { fmt.Printf("flag '--machine-readable' can only be used with '--version' or '-v'\n\n") fmt.Printf("Usage:\n\n") flag.PrintDefaults() os.Exit(1) } else if *gaugeVersion { printVersion() } else if *initialize != "" { projectInit.InitializeProject(*initialize) } else if *installZip != "" && *installPlugin != "" { install.HandleInstallResult(install.InstallPluginFromZipFile(*installZip, *installPlugin), *installPlugin, true) } else if *installPlugin != "" { install.HandleInstallResult(install.InstallPlugin(*installPlugin, *pluginVersion), *installPlugin, true) } else if *uninstallPlugin != "" { install.UninstallPlugin(*uninstallPlugin, *pluginVersion) } else if *installAll { install.InstallAllPlugins() } else if *update != "" { install.HandleUpdateResult(install.InstallPlugin(*update, *pluginVersion), *update, true) } else if *updateAll { install.UpdatePlugins() } else if *checkUpdates { install.PrintUpdateInfoWithDetails() } else if *addPlugin != "" { install.AddPluginToProject(*addPlugin, *pluginArgs) } else if *listTemplates { projectInit.ListTemplates() } else if flag.NFlag() == 0 && len(flag.Args()) == 0 { printUsage() os.Exit(0) } else if validGaugeProject { var specDirs = []string{common.SpecsDirectoryName} if len(flag.Args()) > 0 { specDirs = flag.Args() } if *refactorSteps != "" { refactorInit(flag.Args()) } else if *daemonize { api.RunInBackground(*apiPort, specDirs) } else if *specFilesToFormat != "" { formatter.FormatSpecFilesIn(*specFilesToFormat) } else if *validate { validation.Validate(flag.Args()) } else { exitCode := execution.ExecuteSpecs(specDirs) os.Exit(exitCode) } } else { logger.Fatalf(err.Error()) } }
func handleUninstallFailure(err error, pluginName string) { logger.Error("%s plugin uninstallation failed", pluginName) logger.Fatalf(err.Error()) }
func DownloadAndInstallPlugin(plugin, version, messageFormat string) { err := downloadAndInstall(plugin, version, fmt.Sprintf(messageFormat, plugin)) if err != nil { logger.Fatalf(err.Error()) } }