func watch(inputPaths, ignoredPaths []string, cmdCh chan<- event) (*fsnotify.Watcher, error) {
	ui, err := createUserIgnorer(ignoredPaths)
	if err != nil {
		return nil, err
	}
	w, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, fmt.Errorf("unable to create watcher: %s", err)
	}
	userPaths := make(map[string]bool)
	includedHiddenFiles := make(map[string]bool)
	for _, path := range inputPaths {
		fullPath, err := filepath.Abs(path)
		if err != nil {
			w.Close()
			return nil, errors.New("unable to get current working directory while working with user-watched paths")
		}
		if userPaths[fullPath] || ui.IsIgnored(path) {
			continue
		}
		err = w.Add(fullPath)
		if err != nil {
			w.Close()
			return nil, fmt.Errorf("unable to watch '%s': %s", path, err)
		}
		userPaths[fullPath] = true
	}
	renameDirs := make(map[string]bool)
	renameChildren := make(map[string]bool)
	for fullPath, _ := range userPaths {
		baseName := filepath.Base(fullPath)
		if strings.HasPrefix(baseName, ".") {
			includedHiddenFiles[fullPath] = true
		}
		dirPath := filepath.Dir(fullPath)
		if !userPaths[dirPath] && dirPath != "" {
			if !renameDirs[dirPath] {
				err = w.Add(dirPath)
				if err != nil {
					w.Close()
					return nil, fmt.Errorf("unable to watch rename-watched-only dir '%s': %s", fullPath, err)
				}
			}
			renameDirs[dirPath] = true
			renameChildren[fullPath] = true
		}
	}
	ig := &smartIgnorer{
		includedHiddenFiles: includedHiddenFiles,
		ui:                  ui,
		renameDirs:          renameDirs,
		renameChildren:      renameChildren,
	}
	go listenForEvents(w, cmdCh, ig)
	return w, nil
}
watch watches the input paths. The returned Watcher should only be used in
tests.
package main
import (
	"errors"
	"fmt"
	"log"
	"path/filepath"
	"strings"
	"time"
	"github.com/fsnotify/fsnotify"
)