Merge branch 'dev' into master
This commit is contained in:
commit
6000dbe0f8
|
@ -3,6 +3,7 @@ language: go
|
|||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
|
271
realize.go
271
realize.go
|
@ -7,87 +7,43 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/tockins/interact"
|
||||
"github.com/tockins/realize/server"
|
||||
"github.com/tockins/realize/settings"
|
||||
"github.com/tockins/realize/style"
|
||||
"github.com/tockins/realize/watcher"
|
||||
"github.com/tockins/interact"
|
||||
cli "gopkg.in/urfave/cli.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
appVersion = "1.4.1"
|
||||
config = "realize.yaml"
|
||||
outputs = "outputs.log"
|
||||
errs = "errors.log"
|
||||
logs = "logs.log"
|
||||
host = "localhost"
|
||||
port = 3001
|
||||
interval = 200
|
||||
version = "1.4.1"
|
||||
config = "realize.yaml"
|
||||
directory = ".realize"
|
||||
outputs = "outputs.log"
|
||||
errs = "errors.log"
|
||||
logs = "logs.log"
|
||||
host = "localhost"
|
||||
port = 3001
|
||||
interval = 200
|
||||
)
|
||||
|
||||
// Realize struct contains the general app informations
|
||||
type realize struct {
|
||||
settings.Settings `yaml:"settings,omitempty"`
|
||||
Sync chan string `yaml:"-"`
|
||||
Blueprint watcher.Blueprint `yaml:"-"`
|
||||
Server server.Server `yaml:"-"`
|
||||
Projects *[]watcher.Project `yaml:"projects" json:"projects"`
|
||||
}
|
||||
|
||||
// New realize instance
|
||||
var r realize
|
||||
|
||||
// Cli commands
|
||||
func main() {
|
||||
// Realize struct contains the general app informations
|
||||
type realize struct {
|
||||
settings.Settings `yaml:"settings,omitempty"`
|
||||
Sync chan string `yaml:"-"`
|
||||
Blueprint watcher.Blueprint `yaml:"-"`
|
||||
Server server.Server `yaml:"-"`
|
||||
Projects *[]watcher.Project `yaml:"projects" json:"projects"`
|
||||
}
|
||||
var r realize
|
||||
// Before of every exec of a cli method
|
||||
before := func(*cli.Context) error {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
return errors.New("$GOPATH isn't set properly")
|
||||
}
|
||||
r = realize{
|
||||
Sync: make(chan string),
|
||||
Settings: settings.Settings{
|
||||
Config: settings.Config{
|
||||
Create: true,
|
||||
},
|
||||
Resources: settings.Resources{
|
||||
Config: config,
|
||||
Outputs: outputs,
|
||||
Logs: logs,
|
||||
Errors: errs,
|
||||
},
|
||||
Server: settings.Server{
|
||||
Status: false,
|
||||
Open: false,
|
||||
Host: host,
|
||||
Port: port,
|
||||
},
|
||||
},
|
||||
}
|
||||
r.Blueprint = watcher.Blueprint{
|
||||
Settings: &r.Settings,
|
||||
Sync: r.Sync,
|
||||
}
|
||||
r.Server = server.Server{
|
||||
Blueprint: &r.Blueprint,
|
||||
Settings: &r.Settings,
|
||||
Sync: r.Sync,
|
||||
}
|
||||
r.Projects = &r.Blueprint.Projects
|
||||
|
||||
// read if exist
|
||||
r.Read(&r)
|
||||
|
||||
// increase the file limit
|
||||
if r.Config.Flimit != 0 {
|
||||
if err := r.Flimit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
app := &cli.App{
|
||||
Name: "Realize",
|
||||
Version: appVersion,
|
||||
Version: version,
|
||||
Authors: []*cli.Author{
|
||||
{
|
||||
Name: "Alessio Pracchia",
|
||||
|
@ -118,29 +74,18 @@ func main() {
|
|||
&cli.BoolFlag{Name: "no-config", Aliases: []string{"nc"}, Value: false, Usage: "Ignore existing configurations."},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
if p.Bool("legacy") {
|
||||
r.Config.Legacy = settings.Legacy{
|
||||
Status: p.Bool("legacy"),
|
||||
Interval: interval,
|
||||
}
|
||||
polling(p, &r.Config.Legacy)
|
||||
noconf(p, &r.Settings.Config)
|
||||
if err := insert(p, &r.Blueprint); err != nil {
|
||||
return err
|
||||
}
|
||||
if p.Bool("no-config") || len(r.Blueprint.Projects) <= 0 {
|
||||
if p.Bool("no-config") {
|
||||
r.Config.Create = false
|
||||
}
|
||||
r.Blueprint.Projects = []watcher.Project{}
|
||||
if err := r.Blueprint.Add(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.Server.Start(p); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.Blueprint.Run(p); err != nil {
|
||||
return err
|
||||
}
|
||||
if !p.Bool("no-config") {
|
||||
if r.Config.Create {
|
||||
if err := r.Record(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -167,14 +112,13 @@ func main() {
|
|||
&cli.BoolFlag{Name: "no-config", Aliases: []string{"nc"}, Value: false, Usage: "Ignore existing configurations."},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
fmt.Fprintln(style.Output, p.String("path"))
|
||||
if err := r.Blueprint.Add(p); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.Record(r); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(style.Output, style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), style.Green.Bold("Your project was successfully added."))
|
||||
fmt.Fprintln(style.Output,prefix(style.Green.Bold("Your project was successfully added.")))
|
||||
return nil
|
||||
},
|
||||
Before: before,
|
||||
|
@ -194,7 +138,7 @@ func main() {
|
|||
Questions: []*interact.Question{
|
||||
{
|
||||
Before: func(d interact.Context) error {
|
||||
if _, err := os.Stat(settings.Directory + config); err != nil {
|
||||
if _, err := os.Stat(directory + "/" + config); err != nil {
|
||||
d.Skip()
|
||||
}
|
||||
d.SetDef(false, style.Green.Regular("(n)"))
|
||||
|
@ -214,10 +158,7 @@ func main() {
|
|||
Create: true,
|
||||
},
|
||||
Resources: settings.Resources{
|
||||
Config: config,
|
||||
Outputs: outputs,
|
||||
Logs: logs,
|
||||
Errors: errs,
|
||||
Config: config,
|
||||
},
|
||||
Server: settings.Server{
|
||||
Status: false,
|
||||
|
@ -733,7 +674,7 @@ func main() {
|
|||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts, watcher.Command{Type: "before", Command: val, Changed: true, Startup: true})
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts, watcher.Command{Type: "before", Command: val})
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
|
@ -775,7 +716,7 @@ func main() {
|
|||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts, watcher.Command{Type: "after", Command: val, Changed: true, Startup: true})
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Scripts, watcher.Command{Type: "after", Command: val})
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
|
@ -807,60 +748,6 @@ func main() {
|
|||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d interact.Context) error {
|
||||
d.SetDef(false, style.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: interact.Quest{
|
||||
Options: style.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file output history",
|
||||
},
|
||||
Action: func(d interact.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Streams.FileOut = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d interact.Context) error {
|
||||
d.SetDef(false, style.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: interact.Quest{
|
||||
Options: style.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file logs history",
|
||||
},
|
||||
Action: func(d interact.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Streams.FileLog = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d interact.Context) error {
|
||||
d.SetDef(false, style.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: interact.Quest{
|
||||
Options: style.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file errors history",
|
||||
},
|
||||
Action: func(d interact.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Streams.FileErr = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d interact.Context) error {
|
||||
d.SetDef("", style.Green.Regular("(none)"))
|
||||
|
@ -892,7 +779,7 @@ func main() {
|
|||
},
|
||||
After: func(d interact.Context) error {
|
||||
if val, _ := d.Qns().Get(0).Ans().Bool(); val {
|
||||
actErr = r.Settings.Remove(settings.Directory)
|
||||
actErr = r.Settings.Remove(directory)
|
||||
if actErr != nil {
|
||||
return actErr
|
||||
}
|
||||
|
@ -903,7 +790,7 @@ func main() {
|
|||
if err := r.Record(r); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(style.Output, style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), style.Green.Bold("Your configuration was successful."))
|
||||
fmt.Fprintln(style.Output,prefix(style.Green.Bold("Your configuration was successful.")))
|
||||
return nil
|
||||
},
|
||||
Before: before,
|
||||
|
@ -923,7 +810,7 @@ func main() {
|
|||
if err := r.Record(r); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(style.Output, style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), style.Green.Bold("Your project was successfully removed."))
|
||||
fmt.Fprintln(style.Output,prefix(style.Green.Bold("Your project was successfully removed.")))
|
||||
return nil
|
||||
},
|
||||
Before: before,
|
||||
|
@ -944,10 +831,10 @@ func main() {
|
|||
Aliases: []string{"c"},
|
||||
Description: "Remove realize folder.",
|
||||
Action: func(p *cli.Context) error {
|
||||
if err := r.Settings.Remove(settings.Directory); err != nil {
|
||||
if err := r.Settings.Remove(directory); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(style.Output, style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), style.Green.Bold("Realize folder successfully removed."))
|
||||
fmt.Fprintln(style.Output,prefix(style.Green.Bold("Realize folder successfully removed.")))
|
||||
return nil
|
||||
},
|
||||
Before: before,
|
||||
|
@ -955,7 +842,87 @@ func main() {
|
|||
},
|
||||
}
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(style.Output, style.Red.Bold(err))
|
||||
print(style.Red.Bold(err))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix a given string
|
||||
func prefix(s string) string {
|
||||
if s != "" {
|
||||
return fmt.Sprint(style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), s)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Before is launched before each command
|
||||
func before(*cli.Context) error {
|
||||
// Before of every exec of a cli method
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
return errors.New("$GOPATH isn't set properly")
|
||||
}
|
||||
r = realize{
|
||||
Sync: make(chan string),
|
||||
Settings: settings.Settings{
|
||||
Config: settings.Config{
|
||||
Create: true,
|
||||
},
|
||||
Resources: settings.Resources{
|
||||
Config: config,
|
||||
},
|
||||
Server: settings.Server{
|
||||
Status: false,
|
||||
Open: false,
|
||||
Host: host,
|
||||
Port: port,
|
||||
},
|
||||
},
|
||||
}
|
||||
r.Blueprint = watcher.Blueprint{
|
||||
Settings: &r.Settings,
|
||||
Sync: r.Sync,
|
||||
}
|
||||
r.Server = server.Server{
|
||||
Blueprint: &r.Blueprint,
|
||||
Settings: &r.Settings,
|
||||
Sync: r.Sync,
|
||||
}
|
||||
r.Projects = &r.Blueprint.Projects
|
||||
|
||||
// read if exist
|
||||
r.Read(&r)
|
||||
|
||||
// increase the file limit
|
||||
if r.Config.Flimit != 0 {
|
||||
if err := r.Flimit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for the noconf option
|
||||
func noconf(c *cli.Context, s *settings.Config) {
|
||||
if c.Bool("no-config") {
|
||||
s.Create = false
|
||||
}
|
||||
}
|
||||
|
||||
// Check for polling option
|
||||
func polling(c *cli.Context, s *settings.Legacy) {
|
||||
if c.Bool("legacy") {
|
||||
s.Status = c.Bool("legacy")
|
||||
s.Interval = interval
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a project if there isn't already one
|
||||
func insert(c *cli.Context, b *watcher.Blueprint) error {
|
||||
if len(b.Projects) <= 0 {
|
||||
if err := b.Add(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/tockins/realize/settings"
|
||||
"github.com/tockins/realize/style"
|
||||
"github.com/tockins/realize/watcher"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrefix(t *testing.T) {
|
||||
input := settings.Rand(10)
|
||||
value := fmt.Sprint(style.Yellow.Bold("[")+"REALIZE"+style.Yellow.Bold("]"), input)
|
||||
result := prefix(input)
|
||||
if result == "" {
|
||||
t.Fatal("Expected a string")
|
||||
}
|
||||
if result != value {
|
||||
t.Fatal("Expected", value, "Instead", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBefore(t *testing.T) {
|
||||
context := cli.Context{}
|
||||
if err := before(&context); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoConf(t *testing.T) {
|
||||
settings := settings.Config{Create: true}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("no-config", true, "")
|
||||
params := cli.NewContext(nil, set, nil)
|
||||
noconf(params, &settings)
|
||||
if settings.Create == true {
|
||||
t.Fatal("Expected", false, "Instead", true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPolling(t *testing.T) {
|
||||
settings := settings.Legacy{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("legacy", true, "")
|
||||
params := cli.NewContext(nil, set, nil)
|
||||
polling(params, &settings)
|
||||
if settings.Interval == 0 || settings.Status == false {
|
||||
t.Fatal("Expected status", true, "Instead", false)
|
||||
t.Fatal("Expected interval", interval, "Instead", 0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsert(t *testing.T) {
|
||||
b := watcher.Blueprint{}
|
||||
b.Settings = &settings.Settings{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String("name", settings.Rand(5), "")
|
||||
set.String("path", settings.Rand(5), "")
|
||||
params := cli.NewContext(nil, set, nil)
|
||||
if err := insert(params, &b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(b.Projects) == 0 {
|
||||
t.Error("Expected one project")
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// Open a url in the default browser
|
||||
// OpenURL is used for open an url in the default browser
|
||||
func (s *Server) OpenURL(url string) (io.Writer, error) {
|
||||
if s.Open {
|
||||
open, err := cmd[runtime.GOOS]
|
||||
|
|
|
@ -19,19 +19,19 @@ func (s Settings) Stream(file string) ([]byte, error) {
|
|||
|
||||
// Write a file
|
||||
func (s Settings) Write(name string, data []byte) error {
|
||||
err := ioutil.WriteFile(name, data, Permission)
|
||||
err := ioutil.WriteFile(name, data, permission)
|
||||
return s.Validate(err)
|
||||
}
|
||||
|
||||
// Create a new file and return its pointer
|
||||
func (s Settings) Create(path string, name string) *os.File {
|
||||
var file string
|
||||
if _, err := os.Stat(Directory); err == nil {
|
||||
file = filepath.Join(path, Directory, name)
|
||||
if _, err := os.Stat(directory); err == nil {
|
||||
file = filepath.Join(path, directory, name)
|
||||
} else {
|
||||
file = filepath.Join(path, name)
|
||||
}
|
||||
out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, Permission)
|
||||
out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, permission)
|
||||
s.Validate(err)
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package settings
|
||||
|
||||
import (
|
||||
"github.com/labstack/gommon/random"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -9,7 +8,7 @@ import (
|
|||
|
||||
func TestSettings_Stream(t *testing.T) {
|
||||
s := Settings{}
|
||||
filename := random.String(4)
|
||||
filename := Rand(4)
|
||||
if _, err := s.Stream(filename); err == nil {
|
||||
t.Fatal("Error expected, none found", filename, err)
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@ package settings
|
|||
import (
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// settings const
|
||||
const (
|
||||
Permission = 0775
|
||||
Directory = ".realize/"
|
||||
permission = 0775
|
||||
directory = ".realize"
|
||||
)
|
||||
|
||||
// Settings defines a group of general settings
|
||||
|
@ -52,8 +53,9 @@ type Resources struct {
|
|||
func (s *Settings) Read(out interface{}) error {
|
||||
localConfigPath := s.Resources.Config
|
||||
// backward compatibility
|
||||
if _, err := os.Stat(Directory + s.Resources.Config); err == nil {
|
||||
localConfigPath = Directory + s.Resources.Config
|
||||
path := filepath.Join(directory, s.Resources.Config)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
localConfigPath = path
|
||||
}
|
||||
content, err := s.Stream(localConfigPath)
|
||||
if err == nil {
|
||||
|
@ -70,12 +72,12 @@ func (s *Settings) Record(out interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(Directory); os.IsNotExist(err) {
|
||||
if err = os.Mkdir(Directory, Permission); err != nil {
|
||||
if _, err := os.Stat(directory); os.IsNotExist(err) {
|
||||
if err = os.Mkdir(directory, permission); err != nil {
|
||||
return s.Write(s.Resources.Config, y)
|
||||
}
|
||||
}
|
||||
return s.Write(Directory+s.Resources.Config, y)
|
||||
return s.Write(filepath.Join(directory, s.Resources.Config), y)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -47,5 +47,5 @@ func TestSettings_Record(t *testing.T) {
|
|||
if err := s.Record(a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s.Remove(filepath.Join(Directory, s.Resources.Config))
|
||||
s.Remove(filepath.Join(directory, s.Resources.Config))
|
||||
}
|
||||
|
|
|
@ -2,11 +2,20 @@ package settings
|
|||
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/tockins/realize/style"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
)
|
||||
|
||||
// Wdir return the current working Directory
|
||||
|
@ -47,3 +56,21 @@ func (s Settings) Name(name string, path string) string {
|
|||
func (s Settings) Path(path string) string {
|
||||
return strings.Replace(filepath.Clean(path), "\\", "/", -1)
|
||||
}
|
||||
|
||||
// Rand is used for generate a random string
|
||||
func Rand(n int) string {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
b := make([]byte, n)
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package settings
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/labstack/gommon/random"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -32,8 +31,8 @@ func TestSettings_Validate(t *testing.T) {
|
|||
|
||||
func TestSettings_Name(t *testing.T) {
|
||||
s := Settings{}
|
||||
name := random.String(8)
|
||||
path := random.String(5)
|
||||
name := Rand(8)
|
||||
path := Rand(5)
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -47,7 +46,7 @@ func TestSettings_Name(t *testing.T) {
|
|||
|
||||
func TestSettings_Path(t *testing.T) {
|
||||
s := Settings{}
|
||||
path := random.String(5)
|
||||
path := Rand(5)
|
||||
expected := strings.Replace(filepath.Clean(path), "\\", "/", -1)
|
||||
result := s.Path(path)
|
||||
if result != expected {
|
||||
|
|
|
@ -15,14 +15,17 @@ func (h *Blueprint) Run(p *cli.Context) error {
|
|||
err := h.check()
|
||||
if err == nil {
|
||||
// loop projects
|
||||
wg.Add(len(h.Projects))
|
||||
if p.String("name") != "" {
|
||||
wg.Add(1)
|
||||
} else {
|
||||
wg.Add(len(h.Projects))
|
||||
}
|
||||
for k, element := range h.Projects {
|
||||
if p.String("name") != "" && h.Projects[k].Name != p.String("name") {
|
||||
continue
|
||||
}
|
||||
tools := tools{}
|
||||
if element.Cmds.Fmt {
|
||||
tools.Fmt = tool{
|
||||
h.Projects[k].tools.Fmt = tool{
|
||||
status: &h.Projects[k].Cmds.Fmt,
|
||||
cmd: "gofmt",
|
||||
options: []string{"-s", "-w", "-e"},
|
||||
|
@ -30,7 +33,7 @@ func (h *Blueprint) Run(p *cli.Context) error {
|
|||
}
|
||||
}
|
||||
if element.Cmds.Generate {
|
||||
tools.Generate = tool{
|
||||
h.Projects[k].tools.Generate = tool{
|
||||
status: &h.Projects[k].Cmds.Generate,
|
||||
cmd: "go",
|
||||
options: []string{"generate"},
|
||||
|
@ -38,7 +41,7 @@ func (h *Blueprint) Run(p *cli.Context) error {
|
|||
}
|
||||
}
|
||||
if element.Cmds.Test {
|
||||
tools.Test = tool{
|
||||
h.Projects[k].tools.Test = tool{
|
||||
status: &h.Projects[k].Cmds.Test,
|
||||
cmd: "go",
|
||||
options: []string{"test"},
|
||||
|
@ -46,14 +49,13 @@ func (h *Blueprint) Run(p *cli.Context) error {
|
|||
}
|
||||
}
|
||||
if element.Cmds.Vet {
|
||||
tools.Vet = tool{
|
||||
h.Projects[k].tools.Vet = tool{
|
||||
status: &h.Projects[k].Cmds.Vet,
|
||||
cmd: "go",
|
||||
options: []string{"vet"},
|
||||
name: "Go Vet",
|
||||
}
|
||||
}
|
||||
h.Projects[k].tools = tools
|
||||
h.Projects[k].parent = h
|
||||
h.Projects[k].path = h.Projects[k].Path
|
||||
|
||||
|
@ -127,7 +129,7 @@ func (h *Blueprint) Remove(p *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("no project found")
|
||||
return errors.New("No project found.")
|
||||
}
|
||||
|
||||
// List of all the projects
|
||||
|
@ -189,5 +191,5 @@ func (h *Blueprint) check() error {
|
|||
h.Clean()
|
||||
return nil
|
||||
}
|
||||
return errors.New("There are no projects")
|
||||
return errors.New("There are no projects.")
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
if err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 3), ":", style.Blue.Regular(err.Error()))
|
||||
out := BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Run"}
|
||||
p.print("error", out, msg, "")
|
||||
p.stamp("error", out, msg, "")
|
||||
} else {
|
||||
isErrorText = func(t string) bool {
|
||||
return errRegexp.MatchString(t)
|
||||
|
@ -63,7 +63,7 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
}
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Regular("Ended"))
|
||||
out := BufferOut{Time: time.Now(), Text: "Ended", Type: "Go Run"}
|
||||
p.print("log", out, msg, "")
|
||||
p.stamp("log", out, msg, "")
|
||||
wr.Done()
|
||||
}()
|
||||
|
||||
|
@ -87,10 +87,10 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
msg := fmt.Sprintln(p.pname(p.Name, 3), ":", style.Blue.Regular(text))
|
||||
if isError && !isErrorText(text) {
|
||||
out := BufferOut{Time: time.Now(), Text: text, Type: "Go Run"}
|
||||
p.print("error", out, msg, "")
|
||||
p.stamp("error", out, msg, "")
|
||||
} else {
|
||||
out := BufferOut{Time: time.Now(), Text: text, Type: "Go Run"}
|
||||
p.print("out", out, msg, "")
|
||||
p.stamp("out", out, msg, "")
|
||||
}
|
||||
}
|
||||
close(stop)
|
||||
|
@ -153,6 +153,9 @@ func (p *Project) goInstall() (string, error) {
|
|||
|
||||
// GoTools is used for run go methods such as fmt, test, generate...
|
||||
func (p *Project) goTools(dir string, name string, cmd ...string) (string, error) {
|
||||
if s := filepath.Ext(dir); s != "" && s != ".go" {
|
||||
return "", nil
|
||||
}
|
||||
var out, stderr bytes.Buffer
|
||||
build := exec.Command(name, cmd...)
|
||||
build.Dir = dir
|
||||
|
|
|
@ -90,8 +90,7 @@ type Command struct {
|
|||
Type string `yaml:"type" json:"type"`
|
||||
Command string `yaml:"command" json:"command"`
|
||||
Path string `yaml:"path,omitempty" json:"path,omitempty"`
|
||||
Changed bool `yaml:"changed,omitempty" json:"changed,omitempty"`
|
||||
Startup bool `yaml:"startup,omitempty" json:"startup,omitempty"`
|
||||
Global bool `yaml:"global,omitempty" json:"changed,global"`
|
||||
}
|
||||
|
||||
// Streams is a collection of names and values for the logs functionality
|
||||
|
|
|
@ -72,7 +72,7 @@ func (p *Project) watchByPolling() {
|
|||
// repeat the initial cycle
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", style.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), style.Magenta.Bold(file))
|
||||
out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file}
|
||||
p.print("log", out, msg, "")
|
||||
p.stamp("log", out, msg, "")
|
||||
go p.routines(&wr, channel, watcher, file)
|
||||
}
|
||||
return nil
|
||||
|
@ -84,16 +84,15 @@ func (p *Project) watchByPolling() {
|
|||
if err := filepath.Walk(base, walk); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error()}
|
||||
p.print("error", out, msg, "")
|
||||
p.stamp("error", out, msg, "")
|
||||
}
|
||||
} else {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", base, "path doesn't exist")
|
||||
out = BufferOut{Time: time.Now(), Text: base + " path doesn't exist"}
|
||||
p.print("error", out, msg, "")
|
||||
p.stamp("error", out, msg, "")
|
||||
}
|
||||
select {
|
||||
case <-exit:
|
||||
p.cmd("after", false)
|
||||
return
|
||||
case <-time.After(p.parent.Legacy.Interval / time.Duration(len(p.Watcher.Paths))):
|
||||
}
|
||||
|
@ -138,7 +137,7 @@ func (p *Project) watchByNotify() {
|
|||
// repeat the initial cycle
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", style.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), style.Magenta.Bold(file))
|
||||
out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file}
|
||||
p.print("log", out, msg, "")
|
||||
p.stamp("log", out, msg, "")
|
||||
go p.routines(&wr, channel, watcher, file)
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
}
|
||||
|
@ -147,9 +146,8 @@ func (p *Project) watchByNotify() {
|
|||
case err := <-watcher.Errors:
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error()}
|
||||
p.print("error", out, msg, "")
|
||||
p.stamp("error", out, msg, "")
|
||||
case <-exit:
|
||||
p.cmd("after", false)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +159,7 @@ func (p *Project) watch(watcher watcher) error {
|
|||
wd, _ := os.Getwd()
|
||||
walk := func(path string, info os.FileInfo, err error) error {
|
||||
if !p.ignore(path) {
|
||||
if (info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.") || (inArray(filepath.Ext(path), p.Watcher.Exts)) {
|
||||
if ((info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.")) || (inArray(filepath.Ext(path), p.Watcher.Exts)) {
|
||||
if p.Watcher.Preview {
|
||||
log.Println(p.pname(p.Name, 1), ":", path)
|
||||
}
|
||||
|
@ -201,7 +199,7 @@ func (p *Project) watch(watcher watcher) error {
|
|||
}
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 1), ":", style.Blue.Bold("Watching"), style.Magenta.Bold(files), "file/s", style.Magenta.Bold(folders), "folder/s")
|
||||
out = BufferOut{Time: time.Now(), Text: "Watching " + strconv.FormatInt(files, 10) + " files/s " + strconv.FormatInt(folders, 10) + " folder/s"}
|
||||
p.print("log", out, msg, "")
|
||||
p.stamp("log", out, msg, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -214,11 +212,11 @@ func (p *Project) install() error {
|
|||
if err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold("Go Install"), style.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Install", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
p.stamp("error", out, msg, stream)
|
||||
} else {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", style.Green.Regular("Installed")+" after", style.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out = BufferOut{Time: time.Now(), Text: "Installed after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, stream)
|
||||
p.stamp("log", out, msg, stream)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -237,7 +235,7 @@ func (p *Project) run(channel chan bool, wr *sync.WaitGroup) {
|
|||
case <-runner:
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", style.Green.Regular("Started")+" after", style.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out = BufferOut{Time: time.Now(), Text: "Started after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, "")
|
||||
p.stamp("log", out, msg, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -253,11 +251,11 @@ func (p *Project) build() error {
|
|||
if err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold("Go Build"), style.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Build", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
p.stamp("error", out, msg, stream)
|
||||
} else {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", style.Green.Regular("Built")+" after", style.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out = BufferOut{Time: time.Now(), Text: "Built after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, stream)
|
||||
p.stamp("log", out, msg, stream)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -275,7 +273,7 @@ func (p *Project) tool(path string, tool tool) error {
|
|||
if stream, err := p.goTools(path, tool.cmd, tool.options...); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold(tool.name), style.Red.Regular("there are some errors in"), ":", style.Magenta.Bold(path))
|
||||
out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: tool.name, Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
p.stamp("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -284,29 +282,27 @@ func (p *Project) tool(path string, tool tool) error {
|
|||
}
|
||||
|
||||
// Cmd calls an wrapper for execute the commands after/before
|
||||
func (p *Project) cmd(flag string, changed bool) {
|
||||
func (p *Project) cmd(flag string, global bool) {
|
||||
for _, cmd := range p.Watcher.Scripts {
|
||||
if strings.ToLower(cmd.Type) == flag {
|
||||
if changed && cmd.Changed || !changed && cmd.Startup {
|
||||
errors, logs := p.command(cmd)
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", style.Green.Bold("Command"), style.Green.Bold("\"")+cmd.Command+style.Green.Bold("\""))
|
||||
out = BufferOut{Time: time.Now(), Text: cmd.Command, Type: flag}
|
||||
if logs != "" {
|
||||
p.print("log", out, msg, "")
|
||||
}
|
||||
if errors != "" {
|
||||
p.print("error", out, msg, "")
|
||||
}
|
||||
if logs != "" {
|
||||
msg = fmt.Sprintln(logs)
|
||||
out = BufferOut{Time: time.Now(), Text: logs, Type: flag}
|
||||
p.print("log", out, "", msg)
|
||||
}
|
||||
if errors != "" {
|
||||
msg = fmt.Sprintln(style.Red.Regular(errors))
|
||||
out = BufferOut{Time: time.Now(), Text: errors, Type: flag}
|
||||
p.print("error", out, "", msg)
|
||||
}
|
||||
err, logs := p.command(cmd)
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", style.Green.Bold("Command"), style.Green.Bold("\"")+cmd.Command+style.Green.Bold("\""))
|
||||
out = BufferOut{Time: time.Now(), Text: cmd.Command, Type: flag}
|
||||
if logs != "" {
|
||||
p.stamp("log", out, msg, "")
|
||||
}
|
||||
if err != "" {
|
||||
p.stamp("error", out, msg, "")
|
||||
}
|
||||
if logs != "" {
|
||||
msg = fmt.Sprintln(logs)
|
||||
out = BufferOut{Time: time.Now(), Text: logs, Type: flag}
|
||||
p.stamp("log", out, "", msg)
|
||||
}
|
||||
if err != "" {
|
||||
msg = fmt.Sprintln(style.Red.Regular(err))
|
||||
out = BufferOut{Time: time.Now(), Text: err, Type: flag}
|
||||
p.stamp("error", out, "", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -325,14 +321,13 @@ func (p *Project) ignore(str string) bool {
|
|||
// Routines launches the toolchain run, build, install
|
||||
func (p *Project) routines(wr *sync.WaitGroup, channel chan bool, watcher watcher, file string) {
|
||||
if len(file) > 0 {
|
||||
p.cmd("before", true)
|
||||
p.cmd("before", false)
|
||||
path := filepath.Dir(file)
|
||||
p.tool(file, p.tools.Fmt)
|
||||
p.tool(path, p.tools.Vet)
|
||||
p.tool(path, p.tools.Test)
|
||||
p.tool(path, p.tools.Generate)
|
||||
} else {
|
||||
p.cmd("before", false)
|
||||
p.Fatal(p.watch(watcher))
|
||||
}
|
||||
install := p.install()
|
||||
|
@ -343,7 +338,7 @@ func (p *Project) routines(wr *sync.WaitGroup, channel chan bool, watcher watche
|
|||
}
|
||||
wr.Wait()
|
||||
if len(file) > 0 {
|
||||
p.cmd("after", true)
|
||||
p.cmd("after", false)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -371,7 +366,7 @@ func (p *Project) pname(name string, color int) string {
|
|||
}
|
||||
|
||||
// Print on files, cli, ws
|
||||
func (p *Project) print(t string, o BufferOut, msg string, stream string) {
|
||||
func (p *Project) stamp(t string, o BufferOut, msg string, stream string) {
|
||||
switch t {
|
||||
case "out":
|
||||
p.Buffer.StdOut = append(p.Buffer.StdOut, o)
|
||||
|
|
Loading…
Reference in New Issue