Skip to content
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
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,24 @@ err = http.ListenAndServe(":3000", web.ErrorChecker(m))
...
```

## Using livereload.js

[What is LiveReload?](https://github.com/livereload/livereload-js#what-is-livereload)

This script is meant to be included into the web pages you want to monitor, like this:

```js
...
<script src="http://localhost:35729/livereload.js"></script>
...
```

## Configuration Settings

```yml
# The root of your application relative to your configuration file.
app_root: .
# List of folders you don't want to watch. The more folders you ignore, the
# List of folders you don't want to watch. The more folders you ignore, the
# faster things will be.
ignored_folders:
- vendor
Expand All @@ -70,7 +82,7 @@ build_path: /tmp
# unnecessary builds, a delay is used to ignore extra events.
build_delay: 200ms
# If you have a specific sub-directory of your project you want to build.
build_target_path : "./cmd/cli"
build_target_path: "./cmd/cli"
# What you would like to name the built binary.
binary_name: refresh-build
# Extra command line flags you want passed to the built binary when running it.
Expand All @@ -79,4 +91,14 @@ command_flags: ["--env", "development"]
command_env: ["PORT=1234"]
# If you want colors to be used when printing out log messages.
enable_colors: true
# If you want livereload websocket server to be used.
livereload:
# Enable livereload
enable: false
# server port
port: 35729
# Run commands when you change in included_folders files.
tasks: []
# List of folders you want to watch.
included_folders: []
```
10 changes: 8 additions & 2 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,19 @@ var initCmd = &cobra.Command{
AppRoot: ".",
IgnoredFolders: []string{"vendor", "log", "logs", "tmp", "node_modules", "bin", "templates"},
IncludedExtensions: []string{".go"},
BinaryName: "refresh-build",
BuildDelay: 200,
BuildTargetPath: "",
BuildPath: os.TempDir(),
BuildDelay: 200,
BinaryName: "refresh-build",
CommandFlags: []string{},
CommandEnv: []string{},
EnableColors: true,
Livereload: refresh.Livereload{
Enable: false,
Port: 35729,
IncludedFolders: []string{},
Tasks: []string{},
},
}

if cfgFile == "" {
Expand Down
2 changes: 1 addition & 1 deletion cmd/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package cmd

const Version = "1.4.0"
const Version = "1.4.1"
15 changes: 11 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
module github.com/markbates/refresh

go 1.17
go 1.18

require (
github.com/fatih/color v1.13.0
github.com/fsnotify/fsnotify v1.5.1
github.com/jaschaephraim/lrserver v0.0.0-20171129202958-50d19f603f71
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/cobra v1.2.1
gopkg.in/yaml.v2 v2.4.0
github.com/spf13/cobra v1.4.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
)

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
golang.org/x/sys v0.1.0 // indirect
)
578 changes: 21 additions & 557 deletions go.sum

Large diffs are not rendered by default.

14 changes: 0 additions & 14 deletions refresh.yml

This file was deleted.

41 changes: 35 additions & 6 deletions refresh/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"crypto/md5"
"fmt"
"io"
"io/ioutil"

"os"
"path"
"runtime"
"strings"
"time"

yaml "gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v3"
)

type Configuration struct {
Expand All @@ -21,8 +21,8 @@ type Configuration struct {
BuildFlags []string `yaml:"build_flags"`
BuildPath string `yaml:"build_path"`
BuildTargetPath string `yaml:"build_target_path"`
CommandEnv []string `yaml:"command_env"`
CommandFlags []string `yaml:"command_flags"`
CommandEnv []string `yaml:"command_env"`
EnableColors bool `yaml:"enable_colors"`
ForcePolling bool `yaml:"force_polling,omitempty"`
IgnoredFolders []string `yaml:"ignored_folders"`
Expand All @@ -33,6 +33,14 @@ type Configuration struct {
Stderr io.Writer `yaml:"-"`
Stdin io.Reader `yaml:"-"`
Stdout io.Writer `yaml:"-"`
Livereload Livereload
}

type Livereload struct {
Enable bool `yaml:"enable"`
Port uint16 `yaml:"port"`
IncludedFolders []string `yaml:"included_folders"`
Tasks []string `yaml:"tasks"`
}

func (c *Configuration) FullBuildPath() string {
Expand All @@ -46,20 +54,41 @@ func (c *Configuration) FullBuildPath() string {
}

func (c *Configuration) Load(path string) error {
data, err := ioutil.ReadFile(path)
// "io/ioutil" has been deprecated since Go 1.16: As of Go 1.16,
// the same functionality is now provided by package io or package os,
// and those implementations should be preferred in new code.
data, err := os.ReadFile(path)
if err != nil {
return err
}
c.Path = path
return yaml.Unmarshal(data, c)
err = yaml.Unmarshal(data, c)
if err != nil {
return err
}

if c.Livereload.Port == 0 {
c.Livereload.Port = 35729
}

return nil
}

func (c *Configuration) Dump(path string) error {
data, err := yaml.Marshal(c)
if err != nil {
return err
}
return ioutil.WriteFile(path, data, 0666)

f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
if err != nil {
return err
}
_, err = f.Write(data)
if err != nil {
return err
}
return nil
}

func ID() string {
Expand Down
51 changes: 44 additions & 7 deletions refresh/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"context"
"fmt"
"log"

"os"
"os/exec"
"strings"
"sync"
"time"

"github.com/fsnotify/fsnotify"
"github.com/jaschaephraim/lrserver"
)

type Manager struct {
Expand All @@ -21,6 +23,7 @@ type Manager struct {
cancelFunc context.CancelFunc
context context.Context
gil *sync.Once
lr *lrserver.Server
}

func New(c *Configuration) *Manager {
Expand All @@ -44,30 +47,38 @@ func NewWithContext(c *Configuration, ctx context.Context) *Manager {
func (r *Manager) Start() error {
w := NewWatcher(r)
w.Start()
r.startLivereload()

go r.build(fsnotify.Event{Name: ":start:"})
if !r.Debug {
go func() {
OuterLoop:
for {
select {
case event := <-w.Events():
case event := <-w.MainWatcher.Events():
if event.Op != fsnotify.Chmod {
go r.build(event)
}
w.Remove(event.Name)
w.Add(event.Name)
w.MainWatcher.Remove(event.Name)
w.MainWatcher.Add(event.Name)
case event := <-w.LivereloadWatcher.Events():
go r.Reload(event)
case <-r.context.Done():
break
break OuterLoop
}
}
}()
}
go func() {
OuterLoop:
for {
select {
case err := <-w.Errors():
case err := <-w.MainWatcher.Errors():
r.Logger.Error(err)
case err := <-w.LivereloadWatcher.Errors():
r.Logger.Error(err)
case <-r.context.Done():
break
break OuterLoop
}
}
}()
Expand All @@ -82,7 +93,6 @@ func (r *Manager) build(event fsnotify.Event) {
}()
r.buildTransaction(func() error {
// time.Sleep(r.BuildDelay * time.Millisecond)

now := time.Now()
r.Logger.Print("Rebuild on: %s", event.Name)

Expand Down Expand Up @@ -120,3 +130,30 @@ func (r *Manager) buildTransaction(fn func() error) {
os.Remove(lpath)
}
}

func (r *Manager) Reload(event fsnotify.Event) {
r.gil.Do(func() {
defer func() {
r.gil = &sync.Once{}
}()
r.runTasks()
r.lr.Reload(event.Name)
})
}

func (r *Manager) isLivereloaderEnable() bool {
if r.Livereload.Enable && r.Livereload.IncludedFolders != nil {
return true
}
return false
}

func (r *Manager) startLivereload() {
// Create and start LiveReload server
if !r.isLivereloaderEnable() {
return
}
lr := lrserver.New(lrserver.DefaultName, r.Livereload.Port)
go lr.ListenAndServe()
r.lr = lr
}
38 changes: 35 additions & 3 deletions refresh/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ func (m *Manager) runAndListen(cmd *exec.Cmd) error {
cmd.Stdout = os.Stdout
}

var stderr bytes.Buffer

var (
stderr bytes.Buffer
)
cmd.Stderr = io.MultiWriter(&stderr, cmd.Stderr)

// Set the environment variables from config
Expand All @@ -66,10 +67,41 @@ func (m *Manager) runAndListen(cmd *exec.Cmd) error {
return fmt.Errorf("%s\n%s", err, stderr.String())
}

m.Logger.Success("Running: %s (PID: %d)", strings.Join(cmd.Args, " "), cmd.Process.Pid)
m.Logger.Success("Main Running: %s (PID: %d)", strings.Join(cmd.Args, " "), cmd.Process.Pid)

err = cmd.Wait()
if err != nil {
return fmt.Errorf("%s\n%s", err, stderr.String())
}
return nil
}

func (m *Manager) runTasks() error {
var taskCmds []*exec.Cmd
if len(m.Livereload.Tasks) != 0 {
for _, v := range m.Livereload.Tasks {
ss := strings.Split(v, " ")
taskCmds = append(taskCmds, exec.Command(ss[0], ss[1:]...))
}
cmd := taskCmds[0]
err := cmd.Start()
if err != nil {
return err
}
m.Logger.Success("Task Running: %s", strings.Join(cmd.Args, " "))

for _, v := range taskCmds[1:] {
pipe, err := v.StdoutPipe()
if err != nil {
return err
}
m.Logger.Success("Task Running: %s", strings.Join(v.Args, " "))
cmd.Stdin = pipe
}

if err := cmd.Wait(); err != nil {
return err
}
}
return nil
}
Loading