Beispiel #1
0
func (gcmd *command) toExecCmd() (cmd *exec.Cmd, err error) {
	cmd = exec.Command(gcmd.executable, gcmd.argv...)
	if gcmd.wd != "" {
		cmd.Dir = gcmd.wd
	}

	cmd.Env = effectiveEnv(gcmd.env)
	cmd.Stdin = os.Stdin

	if gcmd.capture&CaptureStderr > 0 {
		cmd.Stderr = newFileWrapper(os.Stderr, &gcmd.buf, ansi.Red)
	} else {
		cmd.Stderr = os.Stderr
	}
	if gcmd.capture&CaptureStdout > 0 {
		cmd.Stdout = newFileWrapper(os.Stdout, &gcmd.buf, "")
	} else {
		cmd.Stdout = os.Stdout
	}

	if verbose {
		if Env != "" {
			util.Debug("#", "Env: %s\n", Env)
		}
		util.Debug("#", "%s\n", gcmd.commandstr)
	}

	return cmd, nil
}
Beispiel #2
0
func runAndWatch(godoFile string) {
	done := make(chan bool, 1)
	run := func(forceBuild bool) (*exec.Cmd, string) {
		cmd, exe := buildCommand(godoFile, forceBuild)
		cmd.Start()
		go func() {
			err := cmd.Wait()
			done <- true
			if err != nil {
				if isVerbose {
					util.Debug("godo", "godo process killed\n")
				}
			}
		}()
		return cmd, exe
	}

	bufferSize := 2048
	watchr, err := watcher.NewWatcher(bufferSize)
	if err != nil {
		util.Panic("project", "%v\n", err)
	}
	godoDir := filepath.Dir(godoFile)
	watchr.WatchRecursive(godoDir)
	watchr.ErrorHandler = func(err error) {
		util.Error("godo", "Watcher error %v\n", err)
	}

	cmd, exe := run(false)
	// this function will block forever, Ctrl+C to quit app
	// var lastHappenedTime int64
	watchr.Start()
	util.Info("godo", "watching %s ...\n", godoDir)

	<-time.After(godo.GetWatchDelay() + (300 * time.Millisecond))

	// forloop:
	for {
		select {
		case event := <-watchr.Event:
			if event.Path == exe {
				continue
			}
			util.Debug("watchmain", "%+v\n", event)
			syscall.Kill(cmd.Process.Pid, syscall.SIGQUIT)
			cmd.Process.Kill()
			<-done
			cmd, _ = run(true)
		}
	}

}
Beispiel #3
0
// Run runs all the dependencies of this task and when they have completed,
// runs this task.
func (task *Task) Run() error {
	if !watching && task.Complete {
		util.Debug(task.Name, "Already ran\n")
		return nil
	}
	return task.RunWithEvent(task.Name, nil)
}
Beispiel #4
0
func (gcmd *command) runAsync() error {
	cmd, err := gcmd.toExecCmd()
	if err != nil {
		return err
	}

	id := gcmd.commandstr

	// kills previously spawned process (if exists)
	killSpawned(id)
	runnerWaitGroup.Add(1)
	waitExit = true
	go func() {
		err = cmd.Start()
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		Processes[id] = cmd.Process
		if verbose {
			util.Debug("#", "Processes[%q] added\n", id)
		}
		cmd.Wait()
		runnerWaitGroup.Done()
	}()
	return nil
}
Beispiel #5
0
func killSpawned(command string) {
	process := Processes[command]
	if process == nil {
		return
	}

	err := process.Kill()
	delete(Processes, command)
	if err != nil && !strings.Contains(err.Error(), "process already finished") {
		util.Error("Start", "Could not kill existing process %+v\n%s\n", process, err.Error())
		return
	}
	if verbose {
		util.Debug("#", "Processes[%q] killed\n", command)
	}
}
Beispiel #6
0
func buildMain(src string, forceBuild bool) string {
	mustBeMain(src)
	dir := filepath.Dir(src)

	exeFile := "godobin-" + godo.Version
	if isWindows {
		exeFile += ".exe"
	}

	exe := filepath.Join(dir, exeFile)

	build := false
	reasonFormat := ""
	if isRebuild || forceBuild {
		build = true
		reasonFormat = "Rebuilding %s...\n"
	} else {
		build = util.Outdated([]string{dir + "/**/*.go"}, []string{exe})
		reasonFormat = "Godo tasks changed. Rebuilding %s...\n"
	}

	if build {
		util.Debug("godo", reasonFormat, exe)
		_, err := godo.Run("go build -a -o "+exeFile, godo.M{"$in": dir})
		if err != nil {
			panic(fmt.Sprintf("Error building %s: %s\n", src, err.Error()))
		}
		// for some reason go build does not delete the exe named after the dir
		// which ends up with Gododir/Gododir
		if filepath.Base(dir) == "Gododir" {
			orphanedFile := filepath.Join(dir, filepath.Base(dir))
			if _, err := os.Stat(orphanedFile); err == nil {
				os.Remove(orphanedFile)
			}
		}
	}

	if isRebuild {
		util.Info("godo", "ok\n")
	}

	return exe
}
Beispiel #7
0
// RunWithEvent runs this task when triggered from a watch.
// *e* FileEvent contains information about the file/directory which changed
// in watch mode.
func (task *Task) RunWithEvent(logName string, e *watcher.FileEvent) (err error) {
	if task.RunOnce && task.Complete {
		util.Debug(task.Name, "Already ran\n")
		return nil
	}

	task.expandGlobs()
	if !task.shouldRun(e) {
		util.Info(logName, "up-to-date 0ms\n")
		return nil
	}

	start := time.Now()
	if len(task.SrcGlobs) > 0 && len(task.SrcFiles) == 0 {
		util.Error("task", "\""+task.Name+"\" '%v' did not match any files\n", task.SrcGlobs)
	}

	// Run this task only if the file matches watch Regexps
	rebuilt := ""
	if e != nil {
		rebuilt = "rebuilt "
		if !task.isWatchedFile(e.Path) && len(task.SrcGlobs) > 0 {
			return nil
		}
		if verbose {
			util.Debug(logName, "%s\n", e.String())
		}
	}

	log := true
	if task.Handler != nil {
		context := Context{Task: task, Args: task.argm}
		defer func() {
			if p := recover(); p != nil {
				sp, ok := p.(*softPanic)
				if !ok {
					panic(p)
				}
				err = fmt.Errorf("%q: %s", logName, sp)
			}
		}()

		task.Handler.Handle(&context)
		if context.Error != nil {
			return fmt.Errorf("%q: %s", logName, context.Error.Error())
		}
	} else if len(task.dependencies) > 0 {
		// no need to log if just dependency
		log = false
	} else {
		util.Info(task.Name, "Ignored. Task does not have a handler or dependencies.\n")
		return nil
	}

	if log {
		util.Info(logName, "%s%vms\n", rebuilt, time.Since(start).Nanoseconds()/1e6)
	}

	task.Complete = true

	return nil
}
Beispiel #8
0
func logVerbose(msg string, format string, args ...interface{}) {
	if !verbose {
		return
	}
	util.Debug(msg, format, args...)
}