2017-10-08 21:09:45 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"gopkg.in/urfave/cli.v2"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2017-10-16 19:57:09 +00:00
|
|
|
// Tool options customizable, should be moved in Cmd
|
2017-10-08 21:09:45 +00:00
|
|
|
type tool struct {
|
|
|
|
dir bool
|
|
|
|
status bool
|
|
|
|
name string
|
|
|
|
err string
|
2017-10-16 13:21:34 +00:00
|
|
|
cmd []string
|
2017-10-08 21:09:45 +00:00
|
|
|
options []string
|
|
|
|
}
|
|
|
|
|
2017-10-17 09:56:19 +00:00
|
|
|
// Cmds list of go commands
|
2017-10-08 21:09:45 +00:00
|
|
|
type Cmds struct {
|
|
|
|
Vet Cmd `yaml:"vet,omitempty" json:"vet,omitempty"`
|
|
|
|
Fmt Cmd `yaml:"fmt,omitempty" json:"fmt,omitempty"`
|
|
|
|
Test Cmd `yaml:"test,omitempty" json:"test,omitempty"`
|
|
|
|
Generate Cmd `yaml:"generate,omitempty" json:"generate,omitempty"`
|
2017-10-16 13:21:34 +00:00
|
|
|
Install Cmd `yaml:"install,omitempty" json:"install,omitempty"`
|
2017-10-08 21:09:45 +00:00
|
|
|
Build Cmd `yaml:"build,omitempty" json:"build,omitempty"`
|
|
|
|
Run bool `yaml:"run,omitempty" json:"run,omitempty"`
|
|
|
|
}
|
|
|
|
|
2017-10-17 09:56:19 +00:00
|
|
|
// Cmd single command fields and options
|
2017-10-08 21:09:45 +00:00
|
|
|
type Cmd struct {
|
|
|
|
Status bool `yaml:"status,omitempty" json:"status,omitempty"`
|
2017-10-16 13:21:34 +00:00
|
|
|
Method string `yaml:"method,omitempty" json:"method,omitempty"`
|
2017-10-08 21:09:45 +00:00
|
|
|
Args []string `yaml:"args,omitempty" json:"args,omitempty"`
|
2017-10-15 20:21:29 +00:00
|
|
|
method []string
|
2017-10-16 19:57:09 +00:00
|
|
|
tool bool
|
2017-10-08 21:09:45 +00:00
|
|
|
name, startTxt, endTxt string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean duplicate projects
|
|
|
|
func (r *realize) clean() {
|
|
|
|
arr := r.Schema
|
|
|
|
for key, val := range arr {
|
|
|
|
if _, err := duplicates(val, arr[key+1:]); err != nil {
|
|
|
|
r.Schema = append(arr[:key], arr[key+1:]...)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
func (r *realize) add(p *cli.Context) error {
|
|
|
|
project := Project{
|
2017-10-22 16:44:44 +00:00
|
|
|
Name: filepath.Base(filepath.Clean(p.String("path"))),
|
|
|
|
Path: filepath.Clean(p.String("path")),
|
2017-10-08 21:09:45 +00:00
|
|
|
Cmds: Cmds{
|
|
|
|
Vet: Cmd{
|
|
|
|
Status: p.Bool("vet"),
|
|
|
|
},
|
|
|
|
Fmt: Cmd{
|
|
|
|
Status: p.Bool("fmt"),
|
|
|
|
},
|
|
|
|
Test: Cmd{
|
|
|
|
Status: p.Bool("test"),
|
|
|
|
},
|
|
|
|
Generate: Cmd{
|
|
|
|
Status: p.Bool("generate"),
|
|
|
|
},
|
|
|
|
Build: Cmd{
|
|
|
|
Status: p.Bool("build"),
|
|
|
|
},
|
|
|
|
Install: Cmd{
|
|
|
|
Status: p.Bool("install"),
|
|
|
|
},
|
|
|
|
Run: p.Bool("run"),
|
|
|
|
},
|
|
|
|
Args: params(p),
|
|
|
|
Watcher: Watch{
|
|
|
|
Paths: []string{"/"},
|
|
|
|
Ignore: []string{"vendor"},
|
|
|
|
Exts: []string{"go"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if _, err := duplicates(project, r.Schema); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.Schema = append(r.Schema, project)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run launches the toolchain for each project
|
|
|
|
func (r *realize) run(p *cli.Context) error {
|
2017-10-22 16:44:44 +00:00
|
|
|
var match bool
|
2017-10-08 21:09:45 +00:00
|
|
|
err := r.check()
|
|
|
|
if err == nil {
|
|
|
|
// loop projects
|
|
|
|
if p.String("name") != "" {
|
|
|
|
wg.Add(1)
|
|
|
|
} else {
|
|
|
|
wg.Add(len(r.Schema))
|
|
|
|
}
|
|
|
|
for k, elm := range r.Schema {
|
2017-10-16 19:57:09 +00:00
|
|
|
// command start using name flag
|
2017-10-08 21:09:45 +00:00
|
|
|
if p.String("name") != "" && r.Schema[k].Name != p.String("name") {
|
|
|
|
continue
|
|
|
|
}
|
2017-10-16 19:57:09 +00:00
|
|
|
//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:
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//}
|
2017-10-08 21:09:45 +00:00
|
|
|
if elm.Cmds.Fmt.Status {
|
|
|
|
if len(elm.Cmds.Fmt.Args) == 0 {
|
2017-10-16 20:21:58 +00:00
|
|
|
elm.Cmds.Fmt.Args = []string{"-s", "-w", "-e", "./"}
|
2017-10-08 21:09:45 +00:00
|
|
|
}
|
|
|
|
r.Schema[k].tools = append(r.Schema[k].tools, tool{
|
|
|
|
status: elm.Cmds.Fmt.Status,
|
2017-10-16 13:21:34 +00:00
|
|
|
cmd: replace([]string{"gofmt"}, r.Schema[k].Cmds.Fmt.Method),
|
2017-10-08 21:09:45 +00:00
|
|
|
options: split([]string{}, elm.Cmds.Fmt.Args),
|
2017-10-16 13:21:34 +00:00
|
|
|
name: "Fmt",
|
2017-10-08 21:09:45 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
if elm.Cmds.Generate.Status {
|
|
|
|
r.Schema[k].tools = append(r.Schema[k].tools, tool{
|
|
|
|
status: elm.Cmds.Generate.Status,
|
2017-10-16 13:21:34 +00:00
|
|
|
cmd: replace([]string{"go", "generate"}, r.Schema[k].Cmds.Generate.Method),
|
|
|
|
options: split([]string{}, elm.Cmds.Generate.Args),
|
|
|
|
name: "Generate",
|
2017-10-08 21:09:45 +00:00
|
|
|
dir: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if elm.Cmds.Test.Status {
|
|
|
|
r.Schema[k].tools = append(r.Schema[k].tools, tool{
|
|
|
|
status: elm.Cmds.Test.Status,
|
2017-10-16 13:21:34 +00:00
|
|
|
cmd: replace([]string{"go", "test"}, r.Schema[k].Cmds.Test.Method),
|
|
|
|
options: split([]string{}, elm.Cmds.Test.Args),
|
|
|
|
name: "Test",
|
2017-10-08 21:09:45 +00:00
|
|
|
dir: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if elm.Cmds.Vet.Status {
|
|
|
|
r.Schema[k].tools = append(r.Schema[k].tools, tool{
|
|
|
|
status: elm.Cmds.Vet.Status,
|
2017-10-16 13:21:34 +00:00
|
|
|
cmd: replace([]string{"go", "vet"}, r.Schema[k].Cmds.Vet.Method),
|
|
|
|
options: split([]string{}, elm.Cmds.Vet.Args),
|
|
|
|
name: "Vet",
|
2017-10-08 21:09:45 +00:00
|
|
|
dir: true,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// default settings
|
|
|
|
r.Schema[k].Cmds.Install = Cmd{
|
|
|
|
Status: elm.Cmds.Install.Status,
|
2017-10-15 20:21:29 +00:00
|
|
|
Args: append([]string{}, elm.Cmds.Install.Args...),
|
2017-10-16 13:21:34 +00:00
|
|
|
method: replace([]string{"go", "install"}, r.Schema[k].Cmds.Install.Method),
|
|
|
|
name: "Install",
|
2017-10-12 14:28:25 +00:00
|
|
|
startTxt: "Installing...",
|
2017-10-08 21:09:45 +00:00
|
|
|
endTxt: "Installed",
|
|
|
|
}
|
|
|
|
r.Schema[k].Cmds.Build = Cmd{
|
|
|
|
Status: elm.Cmds.Build.Status,
|
2017-10-15 20:21:29 +00:00
|
|
|
Args: append([]string{}, elm.Cmds.Build.Args...),
|
2017-10-16 13:21:34 +00:00
|
|
|
method: replace([]string{"go", "build"}, r.Schema[k].Cmds.Build.Method),
|
|
|
|
name: "Build",
|
2017-10-16 19:57:09 +00:00
|
|
|
startTxt: "Building...",
|
2017-10-08 21:09:45 +00:00
|
|
|
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)
|
|
|
|
}
|
2017-10-22 16:44:44 +00:00
|
|
|
match = true
|
2017-10-08 21:09:45 +00:00
|
|
|
go r.Schema[k].watch()
|
|
|
|
}
|
2017-10-22 16:44:44 +00:00
|
|
|
if !match {
|
|
|
|
return errors.New("there is no project with the given name")
|
|
|
|
}
|
2017-10-08 21:09:45 +00:00
|
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove a project
|
|
|
|
func (r *realize) remove(p *cli.Context) error {
|
|
|
|
for key, val := range r.Schema {
|
|
|
|
if p.String("name") == val.Name {
|
|
|
|
r.Schema = append(r.Schema[:key], r.Schema[key+1:]...)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("no project found")
|
|
|
|
}
|
|
|
|
|
2017-10-15 20:21:29 +00:00
|
|
|
// Insert current project if there isn't already one
|
2017-10-08 21:09:45 +00:00
|
|
|
func (r *realize) insert(c *cli.Context) error {
|
2017-10-12 14:28:25 +00:00
|
|
|
if c.Bool("no-config") {
|
2017-10-08 21:09:45 +00:00
|
|
|
r.Schema = []Project{}
|
|
|
|
}
|
|
|
|
if len(r.Schema) <= 0 {
|
|
|
|
if err := r.add(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|