Merge pull request #106 from tockins/dev

1.5.1
This commit is contained in:
Alessio Pracchia 2017-10-29 15:25:07 +01:00 committed by GitHub
commit e68331b6d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 220 additions and 269 deletions

258
cmd.go
View File

@ -6,6 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
"reflect"
) )
// Tool options customizable, should be moved in Cmd // Tool options customizable, should be moved in Cmd
@ -50,20 +51,11 @@ func (r *realize) clean() {
} }
} }
// Check whether there is a project
func (r *realize) check() error {
if len(r.Schema) > 0 {
r.clean()
return nil
}
return errors.New("there are no projects")
}
// Add a new project // Add a new project
func (r *realize) add(p *cli.Context) error { func (r *realize) add(p *cli.Context) error {
project := Project{ project := Project{
Name: r.Settings.name(p.String("name"), p.String("path")), Name: filepath.Base(filepath.Clean(p.String("path"))),
Path: r.Settings.path(p.String("path")), Path: filepath.Clean(p.String("path")),
Cmds: Cmds{ Cmds: Cmds{
Vet: Cmd{ Vet: Cmd{
Status: p.Bool("vet"), Status: p.Bool("vet"),
@ -88,7 +80,7 @@ func (r *realize) add(p *cli.Context) error {
Args: params(p), Args: params(p),
Watcher: Watch{ Watcher: Watch{
Paths: []string{"/"}, Paths: []string{"/"},
Ignore: []string{"vendor"}, Ignore: []string{".git",".realize","vendor"},
Exts: []string{"go"}, Exts: []string{"go"},
}, },
} }
@ -101,124 +93,132 @@ func (r *realize) add(p *cli.Context) error {
// Run launches the toolchain for each project // Run launches the toolchain for each project
func (r *realize) run(p *cli.Context) error { func (r *realize) run(p *cli.Context) error {
err := r.check() var match bool
if err == nil { // check projects and remove duplicates
// loop projects if len(r.Schema) > 0 {
if p.String("name") != "" { r.clean()
wg.Add(1) }else{
} else { return errors.New("there are no projects")
wg.Add(len(r.Schema))
}
for k, elm := range r.Schema {
// command start using name flag
if p.String("name") != "" && r.Schema[k].Name != p.String("name") {
continue
}
//fields := reflect.Indirect(reflect.ValueOf(&r.Schema[k].Cmds))
//// Loop struct Cmds fields
//for i := 0; i < fields.NumField(); i++ {
// field := fields.Type().Field(i).Name
// if fields.FieldByName(field).Type().Name() == "Cmd" {
// v := fields.FieldByName(field)
// // Loop struct Cmd
// for i := 0; i < v.NumField(); i++ {
// f := v.Field(i)
// if f.IsValid() {
// if f.CanSet() {
// switch f.Kind() {
// case reflect.Bool:
// case reflect.String:
// case reflect.Slice:
// }
// }
// }
// }
// }
//}
if elm.Cmds.Fmt.Status {
if len(elm.Cmds.Fmt.Args) == 0 {
elm.Cmds.Fmt.Args = []string{"-s", "-w", "-e", "./"}
}
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Fmt.Status,
cmd: replace([]string{"gofmt"}, r.Schema[k].Cmds.Fmt.Method),
options: split([]string{}, elm.Cmds.Fmt.Args),
name: "Fmt",
})
}
if elm.Cmds.Generate.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Generate.Status,
cmd: replace([]string{"go", "generate"}, r.Schema[k].Cmds.Generate.Method),
options: split([]string{}, elm.Cmds.Generate.Args),
name: "Generate",
dir: true,
})
}
if elm.Cmds.Test.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Test.Status,
cmd: replace([]string{"go", "test"}, r.Schema[k].Cmds.Test.Method),
options: split([]string{}, elm.Cmds.Test.Args),
name: "Test",
dir: true,
})
}
if elm.Cmds.Vet.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Vet.Status,
cmd: replace([]string{"go", "vet"}, r.Schema[k].Cmds.Vet.Method),
options: split([]string{}, elm.Cmds.Vet.Args),
name: "Vet",
dir: true,
})
}
// default settings
r.Schema[k].Cmds.Install = Cmd{
Status: elm.Cmds.Install.Status,
Args: append([]string{}, elm.Cmds.Install.Args...),
method: replace([]string{"go", "install"}, r.Schema[k].Cmds.Install.Method),
name: "Install",
startTxt: "Installing...",
endTxt: "Installed",
}
r.Schema[k].Cmds.Build = Cmd{
Status: elm.Cmds.Build.Status,
Args: append([]string{}, elm.Cmds.Build.Args...),
method: replace([]string{"go", "build"}, r.Schema[k].Cmds.Build.Method),
name: "Build",
startTxt: "Building...",
endTxt: "Built",
}
r.Schema[k].parent = r
r.Schema[k].path = r.Schema[k].Path
// env variables
for key, item := range r.Schema[k].Environment {
if err := os.Setenv(key, item); err != nil {
r.Schema[k].Buffer.StdErr = append(r.Schema[k].Buffer.StdErr, BufferOut{Time: time.Now(), Text: err.Error(), Type: "Env error", Stream: ""})
}
}
// base path of the project
wd, err := os.Getwd()
if err != nil {
return err
}
if elm.path == "." || elm.path == "/" {
r.Schema[k].base = wd
r.Schema[k].path = elm.wdir()
} else if filepath.IsAbs(elm.path) {
r.Schema[k].base = elm.path
} else {
r.Schema[k].base = filepath.Join(wd, elm.path)
}
go r.Schema[k].watch()
}
wg.Wait()
return nil
} }
// set gobin
err := os.Setenv("GOBIN", filepath.Join(os.Getenv("GOPATH"), "bin"))
if err != nil {
return err
}
// loop projects
if p.String("name") != "" {
wg.Add(1)
} else {
wg.Add(len(r.Schema))
}
for k, elm := range r.Schema {
// command start using name flag
if p.String("name") != "" && r.Schema[k].Name != p.String("name") {
continue
}
// validate project path, if invalid get wdir or clean current
if !filepath.IsAbs(elm.Path){
r.Schema[k].Path = wdir()
}else{
r.Schema[k].Path = filepath.Clean(elm.Path)
}
// env variables
for key, item := range r.Schema[k].Environment {
if err := os.Setenv(key, item); err != nil {
r.Schema[k].Buffer.StdErr = append(r.Schema[k].Buffer.StdErr, BufferOut{Time: time.Now(), Text: err.Error(), Type: "Env error", Stream: ""})
}
}
// get basepath name
r.Schema[k].name = filepath.Base(r.Schema[k].Path)
fields := reflect.Indirect(reflect.ValueOf(&r.Schema[k].Cmds))
// Loop struct Cmds fields
for i := 0; i < fields.NumField(); i++ {
field := fields.Type().Field(i).Name
if fields.FieldByName(field).Type().Name() == "Cmd" {
v := fields.FieldByName(field)
// Loop struct Cmd
for i := 0; i < v.NumField(); i++ {
//f := v.Type().Field(i).Name
//fmt.Println(f)
//if f.IsValid() {
// if f.CanSet() {
// fmt.Println(f.)
// //switch f.Kind() {
// //case reflect.Bool:
// //case reflect.String:
// //case reflect.Slice:
// //}
// }
//}
}
}
}
if elm.Cmds.Fmt.Status {
if len(elm.Cmds.Fmt.Args) == 0 {
elm.Cmds.Fmt.Args = []string{"-s", "-w", "-e", "./"}
}
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Fmt.Status,
cmd: replace([]string{"gofmt"}, r.Schema[k].Cmds.Fmt.Method),
options: split([]string{}, elm.Cmds.Fmt.Args),
name: "Fmt",
})
}
if elm.Cmds.Generate.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Generate.Status,
cmd: replace([]string{"go", "generate"}, r.Schema[k].Cmds.Generate.Method),
options: split([]string{}, elm.Cmds.Generate.Args),
name: "Generate",
dir: true,
})
}
if elm.Cmds.Test.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Test.Status,
cmd: replace([]string{"go", "test"}, r.Schema[k].Cmds.Test.Method),
options: split([]string{}, elm.Cmds.Test.Args),
name: "Test",
dir: true,
})
}
if elm.Cmds.Vet.Status {
r.Schema[k].tools = append(r.Schema[k].tools, tool{
status: elm.Cmds.Vet.Status,
cmd: replace([]string{"go", "vet"}, r.Schema[k].Cmds.Vet.Method),
options: split([]string{}, elm.Cmds.Vet.Args),
name: "Vet",
dir: true,
})
}
// default settings
r.Schema[k].Cmds.Install = Cmd{
Status: elm.Cmds.Install.Status,
Args: append([]string{}, elm.Cmds.Install.Args...),
method: replace([]string{"go", "install"}, r.Schema[k].Cmds.Install.Method),
name: "Install",
startTxt: "Installing...",
endTxt: "Installed",
}
r.Schema[k].Cmds.Build = Cmd{
Status: elm.Cmds.Build.Status,
Args: append([]string{}, elm.Cmds.Build.Args...),
method: replace([]string{"go", "build"}, r.Schema[k].Cmds.Build.Method),
name: "Build",
startTxt: "Building...",
endTxt: "Built",
}
r.Schema[k].parent = r
match = true
go r.Schema[k].watch()
}
if !match {
return errors.New("there is no project with the given name")
}
wg.Wait()
return err return err
} }

View File

@ -8,6 +8,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"time" "time"
"path/filepath"
) )
type loggerT struct{} type loggerT struct{}
@ -39,19 +40,6 @@ func TestRealize_Clean(t *testing.T) {
} }
func TestRealize_Check(t *testing.T) {
r := realize{}
err := r.check()
if err == nil {
t.Error("There is no project, error expected")
}
r.Schema = append(r.Schema, Project{Name: "test0"})
err = r.check()
if err != nil {
t.Error("There is a project, error unexpected", err)
}
}
func TestRealize_Add(t *testing.T) { func TestRealize_Add(t *testing.T) {
r := realize{} r := realize{}
// add all flags, test with expected // add all flags, test with expected
@ -63,13 +51,13 @@ func TestRealize_Add(t *testing.T) {
set.Bool("run", false, "") set.Bool("run", false, "")
set.Bool("build", false, "") set.Bool("build", false, "")
set.Bool("generate", false, "") set.Bool("generate", false, "")
set.String("path", "", "") set.String("path", wdir(), "")
c := cli.NewContext(nil, set, nil) c := cli.NewContext(nil, set, nil)
set.Parse([]string{"--path=test_path", "--fmt", "--install", "--run", "--build", "--generate", "--test", "--vet"}) set.Parse([]string{"--fmt", "--install", "--run", "--build", "--generate", "--test", "--vet"})
r.add(c) r.add(c)
expected := Project{ expected := Project{
Name: "test_path", Name: filepath.Base(wdir()),
Path: "test_path", Path: wdir(),
Cmds: Cmds{ Cmds: Cmds{
Fmt: Cmd{ Fmt: Cmd{
Status: true, Status: true,
@ -93,7 +81,7 @@ func TestRealize_Add(t *testing.T) {
}, },
Watcher: Watch{ Watcher: Watch{
Paths: []string{"/"}, Paths: []string{"/"},
Ignore: []string{"vendor"}, Ignore: []string{".git",".realize","vendor"},
Exts: []string{"go"}, Exts: []string{"go"},
}, },
} }

42
exec.go
View File

@ -12,6 +12,7 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/pkg/errors"
) )
// GoCompile is used for compile a project // GoCompile is used for compile a project
@ -19,16 +20,9 @@ func (p *Project) goCompile(stop <-chan bool, method []string, args []string) (s
var out bytes.Buffer var out bytes.Buffer
var stderr bytes.Buffer var stderr bytes.Buffer
done := make(chan error) done := make(chan error)
err := os.Setenv("GOBIN", filepath.Join(getEnvPath("GOPATH"), "bin"))
if err != nil {
return "", err
}
args = append(method, args...) args = append(method, args...)
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...)
if _, err := os.Stat(filepath.Join(p.base, p.path)); err == nil { cmd.Dir = p.Path
p.path = filepath.Join(p.base, p.path)
}
cmd.Dir = p.path
cmd.Stdout = &out cmd.Stdout = &out
cmd.Stderr = &stderr cmd.Stderr = &stderr
// Start command // Start command
@ -53,6 +47,8 @@ func (p *Project) goCompile(stop <-chan bool, method []string, args []string) (s
func (p *Project) goRun(stop <-chan bool, runner chan bool) { func (p *Project) goRun(stop <-chan bool, runner chan bool) {
var build *exec.Cmd var build *exec.Cmd
var args []string var args []string
// custom error pattern
isErrorText := func(string) bool { isErrorText := func(string) bool {
return false return false
} }
@ -67,29 +63,33 @@ func (p *Project) goRun(stop <-chan bool, runner chan bool) {
} }
} }
// add additional arguments
for _, arg := range p.Args { for _, arg := range p.Args {
a := strings.FieldsFunc(arg, func(i rune) bool { a := strings.FieldsFunc(arg, func(i rune) bool {
return i == '"' || i == '=' || i == '\'' return i == '"' || i == '=' || i == '\''
}) })
args = append(args, a...) args = append(args, a...)
} }
if _, err := os.Stat(filepath.Join(getEnvPath("GOBIN"), filepath.Base(p.base))); err == nil {
build = exec.Command(filepath.Join(getEnvPath("GOBIN"), filepath.Base(p.base)), args...) gobin := os.Getenv("GOBIN")
} else if _, err := os.Stat(filepath.Join(getEnvPath("GOBIN"), filepath.Base(p.base)) + extWindows); err == nil { path := filepath.Join(gobin, p.name)
build = exec.Command(filepath.Join(getEnvPath("GOBIN"), filepath.Base(p.base))+extWindows, args...) if _, err := os.Stat(path); err == nil {
build = exec.Command(path, args...)
} else if _, err := os.Stat(path + extWindows); err == nil {
build = exec.Command(path+extWindows, args...)
} else { } else {
path := filepath.Join(p.base, filepath.Base(p.base)) path := filepath.Join(p.Path, p.name)
if _, err = os.Stat(path); err == nil { if _, err = os.Stat(path); err == nil {
build = exec.Command(path, args...) build = exec.Command(path, args...)
} else if _, err = os.Stat(path + extWindows); err == nil { } else if _, err = os.Stat(path + extWindows); err == nil {
build = exec.Command(path+extWindows, args...) build = exec.Command(path+extWindows, args...)
} else { } else {
p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Can't run a not compiled project"}) p.err(errors.New("Build not found"))
p.fatal(nil, "Can't run a not compiled project", ":") return
} }
} }
defer func() { defer func() {
if err := build.Process.Kill(); err != nil { if err := build.Process.Kill(); err != nil {
p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Failed to stop: " + err.Error()}) p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Failed to stop: " + err.Error()})
@ -100,6 +100,7 @@ func (p *Project) goRun(stop <-chan bool, runner chan bool) {
p.stamp("log", out, msg, "") p.stamp("log", out, msg, "")
}() }()
// scan project stream
stdout, err := build.StdoutPipe() stdout, err := build.StdoutPipe()
stderr, err := build.StderrPipe() stderr, err := build.StderrPipe()
if err != nil { if err != nil {
@ -149,12 +150,13 @@ func (p *Project) command(stop <-chan bool, cmd Command) (string, string) {
done := make(chan error) done := make(chan error)
args := strings.Split(strings.Replace(strings.Replace(cmd.Command, "'", "", -1), "\"", "", -1), " ") args := strings.Split(strings.Replace(strings.Replace(cmd.Command, "'", "", -1), "\"", "", -1), " ")
exec := exec.Command(args[0], args[1:]...) exec := exec.Command(args[0], args[1:]...)
exec.Dir = p.base exec.Dir = p.Path
// make cmd path
if cmd.Path != "" { if cmd.Path != "" {
if strings.Contains(cmd.Path, p.base) { if strings.Contains(cmd.Path, p.Path) {
exec.Dir = cmd.Path exec.Dir = cmd.Path
} else { } else {
exec.Dir = filepath.Join(p.base, cmd.Path) exec.Dir = filepath.Join(p.Path, cmd.Path)
} }
} }
exec.Stdout = &stdout exec.Stdout = &stdout
@ -187,7 +189,7 @@ func (p *Project) goTool(wg *sync.WaitGroup, stop <-chan bool, result chan<- too
if strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "") { if strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "") {
if strings.HasSuffix(path, ".go") { if strings.HasSuffix(path, ".go") {
tool.options = append(tool.options, path) tool.options = append(tool.options, path)
path = p.base path = p.Path
} }
if s := ext(path); s == "" || s == "go" { if s := ext(path); s == "" || s == "go" {
var out, stderr bytes.Buffer var out, stderr bytes.Buffer

View File

@ -5,15 +5,17 @@ import (
"fmt" "fmt"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/tockins/interact" "github.com/tockins/interact"
"go/build"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"log" "log"
"os" "os"
"path/filepath"
"strconv" "strconv"
"time" "time"
) )
const ( const (
version = "1.5.0" version = "1.5.1"
) )
// New realize instance // New realize instance
@ -52,7 +54,7 @@ func main() {
Aliases: []string{"r"}, Aliases: []string{"r"},
Description: "Start a toolchain on a project or a list of projects. If not exist a config file it creates a new one", Description: "Start a toolchain on a project or a list of projects. If not exist a config file it creates a new one",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path"}, &cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: wdir(), Usage: "Project base path"},
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: "", Usage: "Run a project by its name"}, &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: "", Usage: "Run a project by its name"},
&cli.BoolFlag{Name: "fmt", Aliases: []string{"f"}, Value: false, Usage: "Enable go fmt"}, &cli.BoolFlag{Name: "fmt", Aliases: []string{"f"}, Value: false, Usage: "Enable go fmt"},
&cli.BoolFlag{Name: "vet", Aliases: []string{"v"}, Value: false, Usage: "Enable go vet"}, &cli.BoolFlag{Name: "vet", Aliases: []string{"v"}, Value: false, Usage: "Enable go vet"},
@ -68,7 +70,7 @@ func main() {
if err := r.insert(p); err != nil { if err := r.insert(p); err != nil {
return err return err
} }
if !p.Bool("no-config") { if !p.Bool("no-config") && p.String("name") == ""{
if err := r.Settings.record(r); err != nil { if err := r.Settings.record(r); err != nil {
return err return err
} }
@ -86,7 +88,7 @@ func main() {
Aliases: []string{"a"}, Aliases: []string{"a"},
Description: "Add a project to an existing config file or create a new one", Description: "Add a project to an existing config file or create a new one",
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path"}, &cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: wdir(), Usage: "Project base path"},
&cli.BoolFlag{Name: "fmt", Aliases: []string{"f"}, Value: false, Usage: "Enable go fmt"}, &cli.BoolFlag{Name: "fmt", Aliases: []string{"f"}, Value: false, Usage: "Enable go fmt"},
&cli.BoolFlag{Name: "vet", Aliases: []string{"v"}, Value: false, Usage: "Enable go vet"}, &cli.BoolFlag{Name: "vet", Aliases: []string{"v"}, Value: false, Usage: "Enable go vet"},
&cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test"}, &cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test"},
@ -102,7 +104,7 @@ func main() {
if err := r.Settings.record(r); err != nil { if err := r.Settings.record(r); err != nil {
return err return err
} }
fmt.Fprintln(output, prefix(green.bold("Your project was successfully added"))) log.Println(prefix(green.bold("Your project was successfully added")))
return nil return nil
}, },
Before: before, Before: before,
@ -110,13 +112,13 @@ func main() {
{ {
Name: "init", Name: "init",
Category: "Configuration", Category: "Configuration",
Aliases: []string{"a"}, Aliases: []string{"i"},
Description: "Define a new config file with all options step by step", Description: "Define a new config file with all options step by step",
Action: func(p *cli.Context) (actErr error) { Action: func(p *cli.Context) (actErr error) {
interact.Run(&interact.Interact{ interact.Run(&interact.Interact{
Before: func(context interact.Context) error { Before: func(context interact.Context) error {
context.SetErr(red.bold("INVALID INPUT")) context.SetErr(red.bold("INVALID INPUT"))
context.SetPrfx(color.Output, yellow.bold("[")+"REALIZE"+yellow.bold("]")) context.SetPrfx(color.Output, yellow.regular("[") + time.Now().Format("15:04:05") + yellow.regular("]") + yellow.bold("[")+"REALIZE"+yellow.bold("]"))
return nil return nil
}, },
Questions: []*interact.Question{ Questions: []*interact.Question{
@ -343,7 +345,7 @@ func main() {
Subs: []*interact.Question{ Subs: []*interact.Question{
{ {
Before: func(d interact.Context) error { Before: func(d interact.Context) error {
d.SetDef(r.Settings.wdir(), green.regular("("+r.Settings.wdir()+")")) d.SetDef(wdir(), green.regular("("+wdir()+")"))
return nil return nil
}, },
Quest: interact.Quest{ Quest: interact.Quest{
@ -361,7 +363,7 @@ func main() {
}, },
{ {
Before: func(d interact.Context) error { Before: func(d interact.Context) error {
dir, _ := os.Getwd() dir := wdir()
d.SetDef(dir, green.regular("("+dir+")")) d.SetDef(dir, green.regular("("+dir+")"))
return nil return nil
}, },
@ -374,7 +376,7 @@ func main() {
if err != nil { if err != nil {
return d.Err() return d.Err()
} }
r.Schema[len(r.Schema)-1].Path = r.Settings.path(val) r.Schema[len(r.Schema)-1].Path = filepath.Clean(val)
return nil return nil
}, },
}, },
@ -1045,7 +1047,7 @@ func main() {
if err := r.Settings.record(r); err != nil { if err := r.Settings.record(r); err != nil {
return err return err
} }
fmt.Fprintln(output, prefix(green.bold(" Your configuration was successful"))) log.Println(prefix(green.bold("Your configuration was successful")))
return nil return nil
}, },
Before: before, Before: before,
@ -1065,7 +1067,7 @@ func main() {
if err := r.Settings.record(r); err != nil { if err := r.Settings.record(r); err != nil {
return err return err
} }
fmt.Fprintln(output, prefix(green.bold("Your project was successfully removed"))) log.Println(prefix(green.bold("Your project was successfully removed")))
return nil return nil
}, },
Before: before, Before: before,
@ -1079,7 +1081,17 @@ func main() {
if err := r.Settings.del(directory); err != nil { if err := r.Settings.del(directory); err != nil {
return err return err
} }
fmt.Fprintln(output, prefix(green.bold("Realize folder successfully removed"))) log.Println(prefix(green.bold("Realize folder successfully removed")))
return nil
},
Before: before,
},
{
Name: "version",
Aliases: []string{"v"},
Description: "Realize version",
Action: func(p *cli.Context) error {
log.Println(prefix(green.bold(version)))
return nil return nil
}, },
Before: before, Before: before,
@ -1087,7 +1099,7 @@ func main() {
}, },
} }
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
fmt.Fprintln(output, prefix(red.bold(err))) log.Println(prefix(red.bold(err)))
os.Exit(1) os.Exit(1)
} }
} }
@ -1115,7 +1127,7 @@ func new() realize {
// Prefix a given string // Prefix a given string
func prefix(s string) string { func prefix(s string) string {
if s != "" { if s != "" {
return fmt.Sprint(yellow.bold("["), "REALIZE", yellow.bold("]"), s) return fmt.Sprint(yellow.bold("["), "REALIZE", yellow.bold("]"), " : ", s)
} }
return "" return ""
} }
@ -1126,10 +1138,13 @@ func before(*cli.Context) error {
log.SetFlags(0) log.SetFlags(0)
log.SetOutput(logWriter{}) log.SetOutput(logWriter{})
// Before of every exec of a cli method // Before of every exec of a cli method
gopath := os.Getenv("GOPATH") gopath := build.Default.GOPATH
if gopath == "" { if gopath == "" {
return errors.New("$GOPATH isn't set properly") return errors.New("$GOPATH isn't set properly")
} }
if err := os.Setenv("GOPATH", gopath); err != nil {
return err
}
// new realize instance // new realize instance
r = new() r = new()
// read if exist // read if exist
@ -1145,5 +1160,5 @@ func before(*cli.Context) error {
// Rewrite the layout of the log timestamp // Rewrite the layout of the log timestamp
func (w logWriter) Write(bytes []byte) (int, error) { func (w logWriter) Write(bytes []byte) (int, error) {
return fmt.Fprint(output, yellow.regular("["), time.Now().Format("15:04:05"), yellow.regular("]")+string(bytes)) return fmt.Fprint(output, yellow.regular("["), time.Now().Format("15:04:05"), yellow.regular("]"), string(bytes))
} }

View File

@ -9,7 +9,7 @@ import (
func TestPrefix(t *testing.T) { func TestPrefix(t *testing.T) {
input := random(10) input := random(10)
value := fmt.Sprint(yellow.bold("[")+"REALIZE"+yellow.bold("]"), input) value := fmt.Sprint(yellow.bold("["), "REALIZE", yellow.bold("]"), " : ", input)
result := prefix(input) result := prefix(input)
if result == "" { if result == "" {
t.Fatal("Expected a string") t.Fatal("Expected a string")
@ -28,7 +28,6 @@ func TestBefore(t *testing.T) {
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
r := new() r := new()
t.Log(reflect.TypeOf(r).String())
if reflect.TypeOf(r).String() != "main.realize" { if reflect.TypeOf(r).String() != "main.realize" {
t.Error("Expected a realize struct") t.Error("Expected a realize struct")
} }

View File

@ -7,7 +7,6 @@ import (
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"syscall" "syscall"
"time" "time"
) )
@ -77,13 +76,6 @@ func random(n int) string {
return string(b) return string(b)
} }
// Wdir return the current working directory
func (s Settings) wdir() string {
dir, err := os.Getwd()
s.validate(err)
return filepath.Base(dir)
}
// Flimit defines the max number of watched files // Flimit defines the max number of watched files
func (s *Settings) flimit() error { func (s *Settings) flimit() error {
var rLimit syscall.Rlimit var rLimit syscall.Rlimit
@ -102,11 +94,6 @@ func (s *Settings) del(d string) error {
return err return err
} }
// Path cleaner
func (s Settings) path(path string) string {
return strings.Replace(filepath.Clean(path), "\\", "/", -1)
}
// Validate checks a fatal error // Validate checks a fatal error
func (s Settings) validate(err error) error { func (s Settings) validate(err error) error {
if err != nil { if err != nil {
@ -171,16 +158,6 @@ func (s Settings) write(name string, data []byte) error {
return s.validate(err) return s.validate(err)
} }
// Name return the project name or the path of the working dir
func (s Settings) name(name string, path string) string {
if name == "" && path == "" {
return s.wdir()
} else if path != "/" {
return filepath.Base(path)
}
return name
}
// Create a new file and return its pointer // Create a new file and return its pointer
func (s Settings) create(path string, name string) *os.File { func (s Settings) create(path string, name string) *os.File {
var file string var file string

View File

@ -5,7 +5,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
) )
@ -100,18 +99,6 @@ func TestSettings_Record(t *testing.T) {
s.del(filepath.Join(directory, s.file)) s.del(filepath.Join(directory, s.file))
} }
func TestSettings_Wdir(t *testing.T) {
s := Settings{}
expected, err := os.Getwd()
if err != nil {
t.Error(err)
}
result := s.wdir()
if result != filepath.Base(expected) {
t.Error("Expected", filepath.Base(expected), "instead", result)
}
}
func TestSettings_Validate(t *testing.T) { func TestSettings_Validate(t *testing.T) {
s := Settings{} s := Settings{}
input := errors.New("") input := errors.New("")
@ -121,28 +108,7 @@ func TestSettings_Validate(t *testing.T) {
} }
} }
func TestSettings_Name(t *testing.T) { func TestSettings_Fatal(t *testing.T){
s := Settings{} s := Settings{}
name := random(8) s.fatal(nil,"test")
path := random(5) }
dir, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
result := s.name(name, path)
if result != dir && result != filepath.Base(path) {
t.Fatal("Expected", dir, "or", filepath.Base(path), "instead", result)
}
}
func TestSettings_Path(t *testing.T) {
s := Settings{}
path := random(5)
expected := strings.Replace(filepath.Clean(path), "\\", "/", -1)
result := s.path(path)
if result != expected {
t.Fatal("Expected", expected, "instead", result)
}
}

View File

@ -4,19 +4,10 @@ import (
"errors" "errors"
"gopkg.in/urfave/cli.v2" "gopkg.in/urfave/cli.v2"
"os" "os"
"path/filepath"
"strings" "strings"
"log"
) )
// getEnvPath returns the first path found in env or empty string
func getEnvPath(env string) string {
path := filepath.SplitList(os.Getenv(env))
if len(path) == 0 {
return ""
}
return path[0]
}
// Array check if a string is in given array // Array check if a string is in given array
func array(str string, list []string) bool { func array(str string, list []string) bool {
for _, v := range list { for _, v := range list {
@ -83,3 +74,12 @@ func replace(a []string, b string) []string {
} }
return a return a
} }
// Wdir return current working directory
func wdir() string {
dir, err := os.Getwd()
if err != nil {
log.Fatal(prefix(err.Error()))
}
return dir
}

View File

@ -53,10 +53,13 @@ func TestInArray(t *testing.T) {
} }
} }
func TestGetEnvPath(t *testing.T) { func TestWdir(t *testing.T) {
expected := filepath.SplitList(os.Getenv("GOPATH"))[0] expected, err := os.Getwd()
result := getEnvPath("GOPATH") if err != nil {
if expected != result { t.Error(err)
t.Fatal("Expected", expected, "instead", result) }
result := wdir()
if result != expected {
t.Error("Expected", filepath.Base(expected), "instead", result)
} }
} }

View File

@ -55,7 +55,7 @@ type Project struct {
watcher FileWatcher watcher FileWatcher
init bool init bool
files, folders int64 files, folders int64
base, path, lastFile string name, lastFile string
tools []tool tools []tool
paths []string paths []string
lastTime time.Time lastTime time.Time
@ -98,7 +98,7 @@ func (p *Project) watch() {
p.cmd(stop, "before", true) p.cmd(stop, "before", true)
// indexing files and dirs // indexing files and dirs
for _, dir := range p.Watcher.Paths { for _, dir := range p.Watcher.Paths {
base := filepath.Join(p.base, dir) base := filepath.Join(p.Path, dir)
if _, err := os.Stat(base); err == nil { if _, err := os.Stat(base); err == nil {
if err := filepath.Walk(base, p.walk); err == nil { if err := filepath.Walk(base, p.walk); err == nil {
p.tool(stop, base) p.tool(stop, base)
@ -312,7 +312,8 @@ func (p *Project) changed(event fsnotify.Event, stop chan bool) {
// Watch the files tree of a project // Watch the files tree of a project
func (p *Project) walk(path string, info os.FileInfo, err error) error { func (p *Project) walk(path string, info os.FileInfo, err error) error {
for _, v := range p.Watcher.Ignore { for _, v := range p.Watcher.Ignore {
if strings.Contains(path, filepath.Join(p.base, v)) { s := append([]string{p.Path},strings.Split(v,string(os.PathSeparator))...)
if strings.Contains(path, filepath.Join(s...)) {
return nil return nil
} }
} }
@ -338,7 +339,7 @@ func (p *Project) stamp(t string, o BufferOut, msg string, stream string) {
case "out": case "out":
p.Buffer.StdOut = append(p.Buffer.StdOut, o) p.Buffer.StdOut = append(p.Buffer.StdOut, o)
if p.Files.Outputs.Status { if p.Files.Outputs.Status {
f := p.create(p.base, p.Files.Outputs.Name) f := p.create(p.Path, p.Files.Outputs.Name)
t := time.Now() t := time.Now()
s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"} s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"}
if _, err := f.WriteString(strings.Join(s, " ")); err != nil { if _, err := f.WriteString(strings.Join(s, " ")); err != nil {
@ -348,7 +349,7 @@ func (p *Project) stamp(t string, o BufferOut, msg string, stream string) {
case "log": case "log":
p.Buffer.StdLog = append(p.Buffer.StdLog, o) p.Buffer.StdLog = append(p.Buffer.StdLog, o)
if p.Files.Logs.Status { if p.Files.Logs.Status {
f := p.create(p.base, p.Files.Logs.Name) f := p.create(p.Path, p.Files.Logs.Name)
t := time.Now() t := time.Now()
s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"} s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"}
if stream != "" { if stream != "" {
@ -361,7 +362,7 @@ func (p *Project) stamp(t string, o BufferOut, msg string, stream string) {
case "error": case "error":
p.Buffer.StdErr = append(p.Buffer.StdErr, o) p.Buffer.StdErr = append(p.Buffer.StdErr, o)
if p.Files.Errors.Status { if p.Files.Errors.Status {
f := p.create(p.base, p.Files.Errors.Name) f := p.create(p.Path, p.Files.Errors.Name)
t := time.Now() t := time.Now()
s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Type, o.Text, o.Path, "\r\n"} s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Type, o.Text, o.Path, "\r\n"}
if stream != "" { if stream != "" {
@ -407,7 +408,7 @@ func (p *Project) routines(stop <-chan bool, watcher FileWatcher, path string) {
p.init = true p.init = true
} }
// prevent errors using realize without config with only run flag // prevent errors using realize without config with only run flag
if !p.Cmds.Install.Status && !p.Cmds.Build.Status { if p.Cmds.Run && !p.Cmds.Install.Status && !p.Cmds.Build.Status {
p.Cmds.Install.Status = true p.Cmds.Install.Status = true
} }
if !done { if !done {

View File

@ -29,7 +29,7 @@ func TestWalk(t *testing.T) {
Ignore: []string{"vendor"}, Ignore: []string{"vendor"},
Exts: []string{"go"}, Exts: []string{"go"},
}, },
base: "/go/project", Path: "/go/project",
watcher: &fileWatcherMock{}, watcher: &fileWatcherMock{},
init: true, init: true,
} }