Пример #1
0
func watchTask(root string, logName string, handler func(e *watcher.FileEvent)) {
	bufferSize := 2048
	watchr, err := watcher.NewWatcher(bufferSize)
	if err != nil {
		util.Panic("project", "%v\n", err)
	}
	watchr.WatchRecursive(root)
	watchr.ErrorHandler = func(err error) {
		util.Error("project", "%v\n", err)
	}

	// this function will block forever, Ctrl+C to quit app
	var lastHappenedTime int64
	firstTime := true
	for {
		if firstTime {
			util.Info(logName, "watching %s ...\n", root)
			firstTime = false
		}
		event := <-watchr.Event
		//util.Debug("DBG", "watchr.Event %+v\n", event)
		isOlder := event.UnixNano < lastHappenedTime
		lastHappenedTime = event.UnixNano

		if isOlder {
			continue
		}
		handler(event)
	}
}
Пример #2
0
// Expands glob patterns.
func (task *Task) expandGlobs() {
	files, regexps, err := Glob(task.WatchGlobs)
	if err != nil {
		util.Error(task.Name, "%v", err)
		return
	}
	task.WatchRegexps = regexps
	task.WatchFiles = files
}
Пример #3
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) error {
	if task.RunOnce && task.Complete {
		//util.Debug(task.Name, "Already ran\n")
		return nil
	}

	start := time.Now()
	if len(task.WatchGlobs) > 0 && len(task.WatchFiles) == 0 {
		task.expandGlobs()
		if len(task.WatchFiles) == 0 {
			util.Error("task", "\""+task.Name+"\" '%v' did not match any files\n", task.WatchGlobs)
		}
	}
	// Run this task only if the file matches watch Regexps
	rebuilt := ""
	if e != nil {
		rebuilt = "rebuilt "
		if !task.isWatchedFile(e) {
			return nil
		}
		if verbose {
			util.Debug(logName, "%s\n", e.String())
		}
	}

	var err error
	log := true
	if task.Handler != nil {
		context := Context{Task: task, Args: contextArgm}
		err = task.Handler.Handle(&context)
		if err != nil {
			return fmt.Errorf("%q: %s", logName, err.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
	}

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

	task.Complete = true
	return nil
}
Пример #4
0
func (project *Project) mustTask(name string) (*Project, *Task) {
	namespace, taskName := project.namespaceTaskName(name)

	proj := project.Namespace[namespace]
	if proj == nil {
		util.Panic("project", "Could not find project having namespace \"%s\"\n", namespace)
	}

	task := proj.Tasks[taskName]
	if task == nil {
		util.Error("ERR", `"%s" task is not defined`+"\n", name)
		os.Exit(1)
	}
	return proj, task
}
Пример #5
0
func killSpawned(command string) {
	process := Processes[command]
	if process == nil {
		return
	}

	err := process.Kill()
	delete(Processes, command)
	if err != nil {
		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)
	}
}
Пример #6
0
// Watch watches the Files of a task and reruns the task on a watch event. Any
// direct dependency is also watched. Returns true if watching.
func (project *Project) Watch(names []string, isParent bool) bool {
	funcs := []func(){}

	taskClosure := func(project *Project, task *Task, taskname string, logName string) func() {
		globs, _ := project.gatherWatchInfo(task)
		paths := calculateWatchPaths(globs)
		return func() {
			if len(paths) == 0 {
				return
			}
			for _, pth := range paths {
				go func(path string) {
					watchTask(path, logName, func(e *watcher.FileEvent) {
						err := project.run(taskname, taskname, e)
						if err != nil {
							util.Error("ERR", "%s\n", err.Error())
						}
					})
				}(pth)
			}
		}
	}

	for _, taskname := range names {
		proj, task := project.mustTask(taskname)
		if len(task.WatchFiles) > 0 {
			funcs = append(funcs, taskClosure(proj, task, taskname, taskname))
		}
	}

	if len(funcs) > 0 {
		done := all(funcs)
		<-done
		return true
	}
	return false
}
Пример #7
0
func checkError(err error, format string, args ...interface{}) {
	if err != nil {
		util.Error("ERR", format, args...)
		os.Exit(1)
	}
}
Пример #8
0
func godo(tasksFunc func(*Project), argv []string) {
	if argv == nil {
		argm = minimist.Parse()
	} else {
		argm = minimist.ParseArgv(argv)
	}

	help = argm.ZeroBool("help", "h", "?")
	verbose = argm.ZeroBool("verbose", "v")
	version = argm.ZeroBool("version", "V")
	watching = argm.ZeroBool("watch", "w")
	deprecatedWarnings = argm.ZeroBool("D")
	contextArgm = minimist.ParseArgv(argm.Unparsed())

	project := NewProject(tasksFunc)

	if help {
		Usage(project.usage())
		os.Exit(0)
	}

	if version {
		fmt.Printf("godo %s\n", Version)
		os.Exit(0)
	}

	// Run each task including their dependencies.
	args := []string{}
	for _, v := range argm.Leftover() {
		args = append(args, fmt.Sprintf("%v", v))
	}

	if len(args) == 0 {
		if project.Tasks["default"] != nil {
			args = append(args, "default")
		} else {
			Usage(project.usage())
			os.Exit(0)
		}
	}

	// quick fix to make cascading watch work on default task
	if len(args) == 1 && args[0] == "default" {
		args = project.Tasks["default"].Dependencies
	}

	for _, name := range args {
		err := project.Run(name)
		if err != nil {
			util.Error("ERR", "%s\n", err.Error())
			os.Exit(1)
		}
	}

	if watching {
		if project.Watch(args, true) {
			waitgroup.Add(1)
			waitExit = true
		} else {
			fmt.Println("Nothing to watch. Use W{} or Watch{} to specify glob patterns")
			os.Exit(0)
		}
	}

	if waitExit {
		waitgroup.Wait()
	}
}