Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

addes support for .watch file where one can list the directors outside the watching path to watch #28

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode/
16 changes: 6 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Watcher [![GoDoc](https://godoc.org/github.com/canthefason/go-watcher?status.svg)](https://godoc.org/github.com/canthefason/go-watcher) [![Build Status](https://travis-ci.org/canthefason/go-watcher.svg?branch=master)](https://travis-ci.org/canthefason/go-watcher)
Watcher [![GoDoc](https://godoc.org/github.com/torniker/go-watcher?status.svg)](https://godoc.org/github.com/torniker/go-watcher) [![Build Status](https://travis-ci.org/torniker/go-watcher.svg?branch=master)](https://travis-ci.org/torniker/go-watcher)
=======

Watcher is a command line tool inspired by [fresh](https://github.com/pilu/fresh) and used for watching .go file changes, and restarting the app in case of an update/delete/add operation.
Expand All @@ -9,11 +9,11 @@ Most of the existing file watchers have a configuration burden, and even though

Get the package with:

`go get github.com/canthefason/go-watcher`
`go get github.com/torniker/go-watcher`

Install the binary under go/bin folder:

`go install github.com/canthefason/go-watcher/cmd/watcher`
`go install github.com/torniker/go-watcher/cmd/watcher`

After this step, please make sure that your go/bin folder is appended to PATH environment variable.

Expand Down Expand Up @@ -51,15 +51,15 @@ Since Globs and some optional folder arrays will make it harder to configure, we

## Watcher in Docker

If you want to run Watcher in a containerized local environment, you can achieve this by using [canthefason/go-watcher](https://hub.docker.com/r/canthefason/go-watcher/) image in Docker Hub. There is an example project under [/docker-example](https://github.com/canthefason/go-watcher/tree/dockerfile-gvm/docker-examples) directoy. Let's try to dockerize this example code first.
If you want to run Watcher in a containerized local environment, you can achieve this by using [torniker/go-watcher](https://hub.docker.com/r/torniker/go-watcher/) image in Docker Hub. There is an example project under [/docker-example](https://github.com/torniker/go-watcher/tree/dockerfile-gvm/docker-examples) directoy. Let's try to dockerize this example code first.

In our example, we are creating a server that listens to port 7000 and responds to all clients with "watcher is running" string. The most essential thing to run your code in Docker is, mounting your project volume to a container. In the containerized Watcher, our GOPATH is set to /go directory by default, so you need to mount your project to this GOPATH.

`docker run -v /path/to/hello:/go/src/hello -p 7000:7000 canthefason/go-watcher watcher -run hello`
`docker run -v /path/to/hello:/go/src/hello -p 7000:7000 torniker/go-watcher watcher -run hello`

Containerized Watcher also supports different versions of Go by leveraging [gvm](https://github.com/moovweb/gvm). Currently it only supports major versions right now. If you don't set anything, by default Watcher will pick version 1.7. If you want to change the Go version, you can use GO_VERSION environment variable. Currently it only supports 1.4, 1.5, 1.6, 1.7 at the moment

`docker run -v /path/to/hello:/go/src/hello -e GO_VERSION=1.6 -p 7000:7000 canthefason/go-watcher watcher -run hello`
`docker run -v /path/to/hello:/go/src/hello -e GO_VERSION=1.6 -p 7000:7000 torniker/go-watcher watcher -run hello`

To provide a more structured repo, we also integrated a docker-compose manifest file. That file already handles volume mounting operation that and exposes the port to the localhost. With docker-compose the only thing that you need to do from the root, invoking `docker-compose up

Expand All @@ -70,10 +70,6 @@ You can resolve this problem by setting CGO_ENABLED=0
https://github.com/golang/go/issues/14514
https://codereview.appspot.com/22020045

## Author

* [Can Yucel](http://canthefason.com)

## License

The MIT License (MIT) - see LICENSE.md for more details
Expand Down
2 changes: 1 addition & 1 deletion cmd/watcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"os"

"github.com/canthefason/go-watcher"
"github.com/torniker/go-watcher"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestParamsClone(t *testing.T) {
params.cloneRunFlag()
watch := params.Get("watch")
if watch != "statler" {
t.Error("Expected statler but got %s when watch param is not set", watch)
t.Errorf("Expected statler but got %s when watch param is not set", watch)
}

params.Watcher["watch"] = "waldorf"
Expand Down
7 changes: 4 additions & 3 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ func (r *Runner) Run(p *Params) {
}

r.cmd = cmd
removeFile(fileName)

go func(cmd *exec.Cmd) {
go func(cmd *exec.Cmd, fileName string) {
if err := cmd.Wait(); err != nil {
log.Printf("process interrupted: %s \n", err)
r.kill(cmd)
}
}(r.cmd)

removeFile(fileName)
}(r.cmd, fileName)
}
}

Expand Down
80 changes: 55 additions & 25 deletions watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package watcher
import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
Expand Down Expand Up @@ -41,7 +42,7 @@ func MustRegisterWatcher(params *Params) *Watcher {
if watchVendorStr != "" {
watchVendor, err = strconv.ParseBool(watchVendorStr)
if err != nil {
log.Println("Wrong watch-vendor value: %s (default=false)", watchVendorStr)
log.Printf("Wrong watch-vendor value: %s (default=false)\n", watchVendorStr)
}
}

Expand Down Expand Up @@ -110,6 +111,24 @@ func isWatchedFileType(fileName string) bool {
return existIn(ext, watchedFileExt)
}

func parseWatchList(wd string) []string {
var watchList []string
watchFile := wd + "/.watch"
if _, err := os.Stat(watchFile); err == nil {
b, err := ioutil.ReadFile(watchFile) // just pass the file name
if err != nil {
fmt.Print(err)
return watchList
}
watchStr := string(b)
watchListRelative := strings.Split(watchStr, "\n")
for _, wlr := range watchListRelative {
watchList = append(watchList, wd+"/"+wlr)
}
}
return watchList
}

// Wait waits for the latest messages
func (w *Watcher) Wait() <-chan struct{} {
return w.update
Expand All @@ -125,38 +144,49 @@ func (w *Watcher) Close() {
// starting from the working directory
func (w *Watcher) watchFolders() {
wd, err := w.prepareRootDir()

if err != nil {
fmt.Printf("Could not get root working directory: %s\n", err)
log.Fatalf("Could not get root working directory: %s", err)
}
var dirs []string
dirs = append(dirs, wd)
dirs = append(dirs, parseWatchList(wd)...)
// dirs = append(dirs, wd+"/../../build")
// dirs = append(dirs, wd+"/../../constant")
// dirs = append(dirs, wd+"/../../env")
// dirs = append(dirs, wd+"/../../model")
// dirs = append(dirs, wd+"/../../repo")
// dirs = append(dirs, wd+"/../../schema")
// dirs = append(dirs, wd+"/../../util")
fmt.Println("Watching:")
for _, dir := range dirs {
fmt.Println(dir)
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
// skip files
if info == nil {
log.Fatalf("wrong watcher package: %s", path)
}

filepath.Walk(wd, func(path string, info os.FileInfo, err error) error {
// skip files
if info == nil {
log.Fatalf("wrong watcher package: %s", path)
}
if !info.IsDir() {
return nil
}

if !info.IsDir() {
return nil
}
if !w.watchVendor {
// skip vendor directory
vendor := fmt.Sprintf("%s/vendor", wd)
if strings.HasPrefix(path, vendor) {
return filepath.SkipDir
}
}

if !w.watchVendor {
// skip vendor directory
vendor := fmt.Sprintf("%s/vendor", wd)
if strings.HasPrefix(path, vendor) {
// skip hidden folders
if len(path) > 1 && strings.HasPrefix(filepath.Base(path), ".") {
return filepath.SkipDir
}
}

// skip hidden folders
if len(path) > 1 && strings.HasPrefix(filepath.Base(path), ".") {
return filepath.SkipDir
}

w.addFolder(path)

return err
})
w.addFolder(path)
return err
})
}
}

// addFolder adds given folder name to the watched folders, and starts
Expand Down
8 changes: 4 additions & 4 deletions watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,24 @@ func TestPrepareRootDir(t *testing.T) {
}

func TestIsTestFile(t *testing.T) {
fileName := "/go/src/github.com/canthefason/go-watcher/common.go"
fileName := "/go/src/github.com/torniker/go-watcher/common.go"
if isTestFile(fileName) {
t.Error("expected false, got true")
}

fileName = "/go/src/github.com/canthefason/go-watcher/common_test.go"
fileName = "/go/src/github.com/torniker/go-watcher/common_test.go"
if !isTestFile(fileName) {
t.Error("expected true, got false")
}
}

func TestIsWatchedFileType(t *testing.T) {
fileName := "/go/src/github.com/canthefason/go-watcher/common.go"
fileName := "/go/src/github.com/torniker/go-watcher/common.go"
if !isWatchedFileType(fileName) {
t.Errorf("expected true, got false")
}

fileName = "/go/src/github.com/canthefason/go-watcher/README.md"
fileName = "/go/src/github.com/torniker/go-watcher/README.md"

if isWatchedFileType(fileName) {
t.Errorf("expected false, got true")
Expand Down