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

Support godotenv and auto watch imported pkg path #76

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion runner/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
logPkg "log"
"time"
"strings"

"github.com/mattn/go-colorable"
)
Expand Down Expand Up @@ -35,7 +36,7 @@ func fatal(err error) {
type appLogWriter struct{}

func (a appLogWriter) Write(p []byte) (n int, err error) {
appLog(string(p))
appLog(strings.Replace(string(p), "%", "%%", -1))

return len(p), nil
}
5 changes: 5 additions & 0 deletions runner/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
var settings = map[string]string{
"config_path": "./runner.conf",
"root": ".",
"env": ".env",
"tmp_path": "./tmp",
"build_name": "runner-build",
"build_log": "runner-build-errors.log",
Expand Down Expand Up @@ -112,6 +113,10 @@ func root() string {
return settings["root"]
}

func envFile() string {
return settings["env"]
}

func tmpPath() string {
return settings["tmp_path"]
}
Expand Down
10 changes: 9 additions & 1 deletion runner/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"runtime"
"strings"
"time"
"github.com/joho/godotenv"
)

var (
Expand Down Expand Up @@ -73,6 +74,7 @@ func start() {
}
run()
}
watch()

started = true
mainLog(strings.Repeat("-", 20))
Expand All @@ -94,6 +96,12 @@ func initLogFuncs() {
}

func setEnvVars() {
if _, err := os.Stat(envFile()); !os.IsNotExist(err) {
err := godotenv.Load(envFile())
if err != nil {
fatal(err)
}
}
os.Setenv("DEV_RUNNER", "1")
wd, err := os.Getwd()
if err == nil {
Expand All @@ -113,8 +121,8 @@ func Start() {
initSettings()
initLogFuncs()
initFolders()
initWatcher()
setEnvVars()
watch()
start()
startChannel <- "/"

Expand Down
141 changes: 121 additions & 20 deletions runner/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,60 @@ package runner

import (
"os"
"path/filepath"
"strings"

"fmt"
"github.com/howeyc/fsnotify"
"io"
"io/ioutil"
"os/exec"
"runtime"
)

func watchFolder(path string) {
watcher, err := fsnotify.NewWatcher()
var watchedFolders = map[string]struct{}{}
var pkgName = ""
var pkgPath = ""
var goPaths = []string{}
var watcher *fsnotify.Watcher

func initWatcher() {
// parse running package name
separator := ":"
if runtime.GOOS == "windows" {
separator = ";"
}
goPaths = strings.Split(os.Getenv("GOPATH"), separator)
root := root()
dir, err := os.Getwd()
if err != nil {
fatal(err)
}
if root != "." {
pkgName = root
for _, gopath := range goPaths {
pkgPath = gopath + "/src/" + pkgName
e, err := exists(pkgPath)
if err != nil {
fatal(err)
}
if e {
break
}
}
} else {
for _, gopath := range goPaths {
if strings.HasPrefix(dir, gopath) && len(dir) > len(gopath)+5 {
pkgName = dir[len(gopath)+5:]
pkgPath = dir
break
}
}
}

// init watcher
watcher, err = fsnotify.NewWatcher()
if err != nil {
fatal(err)
}
go func() {
for {
select {
Expand All @@ -27,31 +69,90 @@ func watchFolder(path string) {
}
}
}()
}

// exists returns whether the given file or directory exists or not
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return true, err
}

watcherLog("Watching %s", path)
err = watcher.Watch(path)
func getFolders() map[string]struct{} {
cmd := exec.Command("go", "list", "-f", `{{ join .Deps "\n" }}`, pkgName)

stderr, err := cmd.StderrPipe()
if err != nil {
fatal(err)
}

stdout, err := cmd.StdoutPipe()
if err != nil {
fatal(err)
}

err = cmd.Start()
if err != nil {
fatal(err)
}

imps, _ := ioutil.ReadAll(stdout)
io.Copy(os.Stderr, stderr)

err = cmd.Wait()
if err != nil {
fatal(err)
}

_imps := strings.Split(strings.Trim(string(imps), "\n"), "\n")
_watchedFolders := map[string]struct{}{pkgPath: struct{}{}}
for _, imp := range _imps {
for _, gopath := range goPaths {
path := fmt.Sprintf("%s/src/%s", gopath, imp)
e, err := exists(path)
if err != nil {
fatal(err)
}
if e {
_watchedFolders[path] = struct{}{}
break
}
}
}

return _watchedFolders
}

func watch() {
root := root()
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if info.IsDir() && !isTmpDir(path) {
if len(path) > 1 && strings.HasPrefix(filepath.Base(path), ".") {
return filepath.SkipDir
_watchedFolders := getFolders()
for folder, _ := range watchedFolders {
_, ok := _watchedFolders[folder]
if !ok {
watcherLog("remove watch %s", folder)
err := watcher.RemoveWatch(folder)
if err != nil {
fatal(err)
}

if isIgnoredFolder(path) {
watcherLog("Ignoring %s", path)
return filepath.SkipDir
}
}
for folder, _ := range _watchedFolders {
_, ok := watchedFolders[folder]
if !ok && !isTmpDir(folder) {
if isIgnoredFolder(folder) {
watcherLog("Ignoring %s", folder)
continue
}
watcherLog("add watch %s", folder)
err := watcher.Watch(folder)
if err != nil {
fatal(err)
}

watchFolder(path)
}

return err
})
}
watchedFolders = _watchedFolders
}