Example #1
0
func watch(base string, ignorePatterns []*regexp.Regexp, watcher *fsnotify.Watcher) error {
	if base == "" {
		base = "."
	}

	if debug {
		log.Printf("walks watched directories '%s'", base)
	}

	// register watched directories.
	err := filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() {
			// watche only directries
			return nil
		}

		path = normalizePath(path)

		for _, pattern := range ignorePatterns {
			if !strings.HasPrefix(path, "/") {
				// add "/" to the path
				if ok := pattern.MatchString("/" + path); ok {
					return nil
				}
			} else {
				if ok := pattern.MatchString(path); ok {
					return nil
				}
			}
		}

		err = watcher.Add(path)
		if err != nil {
			return err
		}

		if debug {
			log.Printf("added watched dir '%s'", path)
		}

		return nil
	})

	if err != nil {
		return err
	}

	return nil
}
Example #2
0
func startWatching(watcher *fsnotify.Watcher, state *core.BuildState, labels []core.BuildLabel, files cmap.ConcurrentMap) {
	// Deduplicate seen targets & sources.
	targets := map[*core.BuildTarget]struct{}{}
	dirs := map[string]struct{}{}

	var startWatch func(*core.BuildTarget)
	startWatch = func(target *core.BuildTarget) {
		if _, present := targets[target]; present {
			return
		}
		targets[target] = struct{}{}
		for _, source := range target.AllSources() {
			if source.Label() == nil {
				for _, src := range source.Paths(state.Graph) {
					files.Set(src, struct{}{})
					if info, err := os.Stat(src); err == nil && !info.IsDir() {
						src = path.Dir(src)
					}
					if _, present := dirs[src]; !present {
						log.Notice("Adding watch on %s", src)
						dirs[src] = struct{}{}
						if err := watcher.Add(src); err != nil {
							log.Error("Failed to add watch on %s: %s", src, err)
						}
					}
				}
			}
		}
		for _, dep := range target.Dependencies() {
			startWatch(dep)
		}
		for _, subinclude := range state.Graph.PackageOrDie(target.Label.PackageName).Subincludes {
			startWatch(state.Graph.TargetOrDie(subinclude))
		}
	}

	for _, label := range labels {
		startWatch(state.Graph.TargetOrDie(label))
	}
	// Drop a message here so they know when it's actually ready to go.
	fmt.Println("And now my watch begins...")
}
Example #3
0
// AddRecursiveWatch handles adding watches recursively for the path provided
// and its subdirectories.  If a non-directory is specified, this call is a no-op.
// Recursive logic from https://github.com/bronze1man/kmg/blob/master/fsnotify/Watcher.go
func AddRecursiveWatch(watcher *fsnotify.Watcher, path string) error {
	file, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return fmt.Errorf("error introspecting path %s: %v", path, err)
	}
	if !file.IsDir() {
		return nil
	}

	folders, err := getSubFolders(path)
	for _, v := range folders {
		glog.V(5).Infof("adding watch on path %s", v)
		err = watcher.Add(v)
		if err != nil {
			// "no space left on device" issues are usually resolved via
			// $ sudo sysctl fs.inotify.max_user_watches=65536
			return fmt.Errorf("error adding watcher for path %s: %v", v, err)
		}
	}
	return nil
}
// ReadLogs read the container log and redirect into stdout and stderr.
func ReadLogs(path string, apiOpts *api.PodLogOptions, stdout, stderr io.Writer) error {
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to open log file %q: %v", path, err)
	}
	defer f.Close()

	// Convert api.PodLogOptions into internal log options.
	opts := newLogOptions(apiOpts, time.Now())

	// Search start point based on tail line.
	start, err := tail(f, opts.tail)
	if err != nil {
		return fmt.Errorf("failed to tail %d lines of log file %q: %v", opts.tail, path, err)
	}
	if _, err := f.Seek(start, os.SEEK_SET); err != nil {
		return fmt.Errorf("failed to seek %d in log file %q: %v", start, path, err)
	}

	// Start parsing the logs.
	r := bufio.NewReader(f)
	// Do not create watcher here because it is not needed if `Follow` is false.
	var watcher *fsnotify.Watcher
	var parse parseFunc
	writer := newLogWriter(stdout, stderr, opts)
	msg := &logMessage{}
	for {
		l, err := r.ReadBytes(eol[0])
		if err != nil {
			if err != io.EOF { // This is an real error
				return fmt.Errorf("failed to read log file %q: %v", path, err)
			}
			if !opts.follow {
				// Return directly when reading to the end if not follow.
				if len(l) > 0 {
					glog.Warningf("Incomplete line in log file %q: %q", path, l)
				}
				glog.V(2).Infof("Finish parsing log file %q", path)
				return nil
			}
			// Reset seek so that if this is an incomplete line,
			// it will be read again.
			if _, err := f.Seek(-int64(len(l)), os.SEEK_CUR); err != nil {
				return fmt.Errorf("failed to reset seek in log file %q: %v", path, err)
			}
			if watcher == nil {
				// Intialize the watcher if it has not been initialized yet.
				if watcher, err = fsnotify.NewWatcher(); err != nil {
					return fmt.Errorf("failed to create fsnotify watcher: %v", err)
				}
				defer watcher.Close()
				if err := watcher.Add(f.Name()); err != nil {
					return fmt.Errorf("failed to watch file %q: %v", f.Name(), err)
				}
			}
			// Wait until the next log change.
			if err := waitLogs(watcher); err != nil {
				return fmt.Errorf("failed to wait logs for log file %q: %v", path, err)
			}
			continue
		}
		if parse == nil {
			// Intialize the log parsing function.
			parse, err = getParseFunc(l)
			if err != nil {
				return fmt.Errorf("failed to get parse function: %v", err)
			}
		}
		// Parse the log line.
		msg.reset()
		if err := parse(l, msg); err != nil {
			glog.Errorf("Failed with err %v when parsing log for log file %q: %q", err, path, l)
			continue
		}
		// Write the log line into the stream.
		if err := writer.write(msg); err != nil {
			if err == errMaximumWrite {
				glog.V(2).Infof("Finish parsing log file %q, hit bytes limit %d(bytes)", path, opts.bytes)
				return nil
			}
			glog.Errorf("Failed with err %v when writing log for log file %q: %+v", err, path, msg)
		}
	}
}