Пример #1
0
// Kill kills the underlying application if its started
func (h *ExecuteHandle) Kill(reason StepResult) {

	if reason == nil {
		reason = ErrorAppKilled
	}

	gwl.LogDebug("hitting kill lock")
	h.Lock()
	gwl.LogDebug("done with kill lock")
	if h.running {
		cmd := h.cmd
		proc := cmd.Process

		gwl.LogDebug("Killing")

		if proc != nil {
			if err := proc.Kill(); err != nil && err.Error() != errorProcessAlreadyFinished.Error() {
				gwl.LogDebug("process didn't seem to exit gracefully", err)
				reason = err
			}
		}

		h.writeError(reason)
		h.errorCode = reason
		h.running = false
		h.halted = true
		close(h.result)
	} else if h.errorCode == nil {
		gwl.LogDebug("process never started %s", reason.Error())
		h.writeError(reason)
	}

	h.Unlock()
}
Пример #2
0
func setupIgnorePaths(root string) []string {
	gwl.LogDebug("Ignore globs.")
	paths := strings.Split(*ignore, ",")

	expandedPaths := []string{}
	for _, path := range paths {
		abs := filepath.Join(root, path)
		gwl.LogDebug("\t%s\n", abs)
		expandedPaths = append(expandedPaths, abs)
	}

	return expandedPaths
}
Пример #3
0
func (h *ExecuteHandle) writeError(reason StepResult) {
	if h.running {
		gwl.LogDebug("sending error")
		h.result <- reason
	} else {
		h.errorCode = reason
	}
}
Пример #4
0
func (handle *WatchHandle) handleFileEvent(projectName string) {
	lastEvent, timeSinceLastEvent := "", time.Now().AddDate(-1, 0, 0)

	watcher := handle.watcher
	ignorePaths := handle.ignorePaths
	errorChan := watcher.Errors

	for {
		select {
		case <-time.After(time.Second):
			continue

		case err := <-errorChan:
			if err != nil {
				gwl.LogError("Closing file watcher error routine %s", err.Error())
			}

		case event, ok := <-watcher.Events:

			if !ok {
				gwl.LogDebug("closing file event channel")
				return
			}
			_, filename := filepath.Split(event.Name)

			// ignore any files that have the same name as the package
			if projectName == filename || event.Op&fsnotify.Chmod == fsnotify.Chmod {
				gwl.LogDebug("ignoring go build artifacts")
				continue
			}

			//ignores individual files that may match any ignore paths
			if shouldIgnore(event.Name, ignorePaths) {
				gwl.LogDebug("%s in ignore path ", event.Name)
				continue
			}

			// debounces file events
			if event.Name == lastEvent && timeSinceLastEvent.Add(time.Second).After(time.Now()) {
				gwl.LogDebug("ignoring extra file watch events")
				timeSinceLastEvent = time.Now()
				continue
			}

			lastEvent = event.Name
			timeSinceLastEvent = time.Now()

			if handle.halted {
				gwl.LogDebug("\tfilewatcher halteds")
				return
			} else if handle.fileUpdateCb != nil {
				gwl.LogDebug("\tinvoking file callback with %s", event.Name)
				handle.Lock()
				handle.fileUpdateCb(event.Name)
				handle.Unlock()
				gwl.LogDebug("\tfile callback complete")
			}
		}
	}
}
Пример #5
0
func test(projectDirectory string) bool {
	gwl.LogDebug("testing code...")

	cmd := exec.Command("go", "test")
	cmd.Dir = projectDirectory
	cmd.Env = os.Environ()

	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		gwl.LogDebug("test failures: ", err)
		return false
	}

	return true
}
Пример #6
0
func main() {
	flag.Parse()

	setupLogging()

	projectPath := getAbsPathToProject()

	gwl.LogDebug("watching", projectPath)

	handleWatch(projectPath, setupIgnorePaths(projectPath))
}
Пример #7
0
func (w *WatchHandle) Halt() {
	w.Lock()
	defer w.Unlock()
	if !w.halted {
		gwl.LogDebug("Halting watcher")
		w.halted = true
		w.fileUpdateCb = nil
		go func() {
			w.watcher.Close()
		}()
	}
}
Пример #8
0
func addFilesToWatch(dir string, ignorePaths []string, watcher *fsnotify.Watcher) {
	filepath.Walk(dir, func(p string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if shouldIgnore(filepath.Join(p, info.Name()), ignorePaths) {
				return filepath.SkipDir
			} else if err := watcher.Add(p); err != nil {
				gwl.LogDebug("error adding watched dir", p, info.Name(), err.Error())
				return err
			}
		}
		return nil
	})
}
Пример #9
0
func shouldIgnore(file string, ignorePaths []string) bool {
	for _, pattern := range ignorePaths {

		matched, err := filepath.Match(strings.Replace(pattern, "/", "", -1), strings.Replace(file, "/", "", -1))

		if err != nil {
			gwl.LogError(err.Error())
		}

		if matched && err == nil {
			gwl.LogDebug("\tIgnore %s -> %s\n", pattern, file)
			return true
		}
	}

	return false
}
Пример #10
0
func (h *ExecuteHandle) start(cmd *exec.Cmd) {
	h.Lock()
	h.cmd = cmd
	err := cmd.Start()
	h.running = true
	h.Unlock()

	if err != nil {
		h.Kill(err)
	}

	waiter := make(chan bool)
	go func() {
		close(waiter)
		if err := cmd.Wait(); err != nil {
			gwl.LogDebug("app exited prematurely")
			h.Kill(err)
		}
	}()
	<-waiter
}
Пример #11
0
func handleWatch(projectPath string, ignorePaths []string) {
	watchHandle := watch.StartWatch(projectPath, ignorePaths)

	for {
		gwl.LogDebug("---Starting app monitor---")
		time.Sleep(*wait)
		execHandle := project.ExecuteBuildSteps(projectPath, *appArgs, *shouldTest, *shouldLint)

		gwl.LogDebug("---Setting up watch cb---")
		watchHandle.Subscribe(func(fileName string) {
			if !execHandle.Halted() {
				gwl.LogError("attempting to kill process")
				execHandle.Kill(nil)
				gwl.LogDebug("exiting file watch routine in main")
			}
		})

		gwl.LogDebug("waiting on app to exit")
		err := execHandle.Error()
		gwl.LogDebug("---App exited---")
		watchHandle.Subscribe(nil)

		exitedSuccessfully := err == nil || err == project.ErrorAppKilled

		if exitedSuccessfully {
			color.Green("exited successfully\n")
		} else {
			color.Red("%s\n", err.Error())
		}

		sync := make(chan bool)
		if (!exitedSuccessfully && !*restartOnError) || (!*restartOnExit && err != project.ErrorAppKilled) {
			watchHandle.Subscribe(func(fileName string) {
				close(sync)
				watchHandle.Subscribe(nil)
			})
			gwl.LogDebug("waiting on file notification")
			<-sync
		}
	}
}
Пример #12
0
func lint(projectDirectory string) bool {
	gwl.LogDebug("linting code...")
	lint := &linter.Linter{}

	files := make(map[string]map[string][]byte)
	filepath.Walk(projectDirectory, func(p string, info os.FileInfo, err error) error {
		if filepath.Ext(p) == ".go" {
			fileWithPackage := strings.TrimPrefix(p, projectDirectory)
			packageName := strings.Trim(strings.TrimSuffix(fileWithPackage, info.Name()), "/")

			if packageName == "" {
				packageName = "main"
			}

			files[packageName] = make(map[string][]byte)

			f, err := os.Open(p)
			if err != nil {
				return err
			}

			if files[packageName][p], err = ioutil.ReadAll(f); err != nil {
				return err
			}
		}
		return nil
	})

	lintErrors := false
	for k, v := range files {
		gwl.LogDebug("linting package %s", k)

		problems, err := lint.LintFiles(v)

		if err != nil {
			color.Red("[ERROR]", err)
			lintErrors = true
		} else if len(problems) > 0 {

			gwl.LogDebug("lint issues found")
			color.Yellow("%d lint issue(s) found in %s\n\n", len(problems), k)
			linterConfidenceThresholdReached := false
			for i, p := range problems {
				position := p.Position
				fileWithPackage := strings.Trim(strings.TrimPrefix(position.Filename, projectDirectory), "/")
				lintInfo := strings.Split(p.String(), "\n")

				gwl.LogDebug("%d out of 3", len(lintInfo))

				readableLintError := ""

				if len(lintInfo) >= 3 {
					readableLintError = fmt.Sprintf("- %s", lintInfo[2])
				}

				lintLineOutput := fmt.Sprintf("\t%d. %s line %d %s\n\t%s\n\n",
					i+1, fileWithPackage, position.Line, readableLintError, lintInfo[0])

				if p.Confidence > 0.5 {
					color.Red(lintLineOutput)
					linterConfidenceThresholdReached = true
				} else {
					color.Yellow(lintLineOutput)
				}
			}
			lintErrors = linterConfidenceThresholdReached
		}
	}

	return !lintErrors
}