output file, code clean
This commit is contained in:
parent
d03f5c5a7f
commit
38bd1f8ba5
30
main.go
30
main.go
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
func main() {
|
||||
|
||||
app := r.Info()
|
||||
app := r.App
|
||||
|
||||
handle := func(err error) error {
|
||||
if err != nil {
|
||||
|
@ -50,8 +50,7 @@ func main() {
|
|||
Name: "run",
|
||||
Usage: "Build and watch file changes",
|
||||
Action: func(p *cli.Context) error {
|
||||
y := r.New(p)
|
||||
return handle(y.Watch())
|
||||
return handle(app.Blueprint.Run())
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
header()
|
||||
|
@ -60,7 +59,7 @@ func main() {
|
|||
},
|
||||
{
|
||||
Name: "fast",
|
||||
Usage: "Build and watch file changes for a single project without any config file",
|
||||
Usage: "Build and watch file changes for a single project without any Configuration file",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "", Usage: "Project base path"},
|
||||
&cli.BoolFlag{Name: "build", Value: false, Usage: "Enables the build"},
|
||||
|
@ -68,11 +67,11 @@ func main() {
|
|||
&cli.BoolFlag{Name: "no-bin", Usage: "Disables the installation"},
|
||||
&cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"},
|
||||
&cli.BoolFlag{Name: "test", Value: false, Usage: "Enable the tests"},
|
||||
&cli.BoolFlag{Name: "config", Value: false, Usage: "Take the defined settings if exist a config file."},
|
||||
&cli.BoolFlag{Name: "Configuration", Value: false, Usage: "Take the defined settings if exist a Configuration file."},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
y := r.New(p)
|
||||
return handle(y.Fast(p))
|
||||
app.Blueprint.Add(p)
|
||||
return handle(app.Blueprint.Fast(p))
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
header()
|
||||
|
@ -81,11 +80,11 @@ func main() {
|
|||
},
|
||||
{
|
||||
Name: "add",
|
||||
Category: "config",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Add another project",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.WorkingDir(), Usage: "Project name"},
|
||||
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: app.Wdir(), Usage: "Project name"},
|
||||
&cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "/", Usage: "Project base path"},
|
||||
&cli.BoolFlag{Name: "build", Value: false, Usage: "Enable the build"},
|
||||
&cli.BoolFlag{Name: "no-run", Usage: "Disables the run"},
|
||||
|
@ -94,8 +93,7 @@ func main() {
|
|||
&cli.BoolFlag{Name: "test", Value: false, Usage: "Enable the tests"},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
y := r.New(p)
|
||||
return handle(y.Add(p))
|
||||
return handle(app.Blueprint.Insert(p))
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
header()
|
||||
|
@ -104,15 +102,14 @@ func main() {
|
|||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Category: "config",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Remove a project",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
y := r.New(p)
|
||||
return handle(y.Remove(p))
|
||||
return handle(app.Blueprint.Remove(p))
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
header()
|
||||
|
@ -121,12 +118,11 @@ func main() {
|
|||
},
|
||||
{
|
||||
Name: "list",
|
||||
Category: "config",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"l"},
|
||||
Usage: "Projects list",
|
||||
Action: func(p *cli.Context) error {
|
||||
y := r.New(p)
|
||||
return handle(y.List())
|
||||
return handle(app.Blueprint.List())
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
header()
|
||||
|
|
|
@ -1,21 +1,12 @@
|
|||
package realize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"log"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Default values and info
|
||||
const (
|
||||
AppName = "Realize"
|
||||
AppVersion = "v1.0"
|
||||
AppDescription = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths"
|
||||
AppFile = "realize.config.yaml"
|
||||
)
|
||||
var App Realize
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
|
@ -46,47 +37,19 @@ var MagentaS = color.New(color.FgMagenta).SprintFunc()
|
|||
// Magenta color bold
|
||||
var Magenta = color.New(color.FgMagenta, color.Bold).SprintFunc()
|
||||
|
||||
// WatcherIgnores is an array of default ignored paths
|
||||
var watcherIgnores = []string{"vendor", "bin"}
|
||||
|
||||
// WatcherExts is an array of default exts
|
||||
var watcherExts = []string{".go"}
|
||||
|
||||
// WatcherPaths is an array of default watched paths
|
||||
var watcherPaths = []string{"/"}
|
||||
|
||||
type logWriter struct{}
|
||||
|
||||
// App struct contains the informations about realize
|
||||
type App struct {
|
||||
Name, Version, Description, Author, Email string
|
||||
}
|
||||
|
||||
// Custom log timestamp
|
||||
// Initialize the application
|
||||
func init() {
|
||||
App = Realize{
|
||||
Name: "Realize",
|
||||
Version: "1.0",
|
||||
Description: "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths",
|
||||
Limit: 10000,
|
||||
}
|
||||
App.Blueprint.files = map[string]string{
|
||||
"config": "r.config.yaml",
|
||||
"output": "r.output.log",
|
||||
}
|
||||
App.limit()
|
||||
log.SetFlags(0)
|
||||
log.SetOutput(new(logWriter))
|
||||
|
||||
// increases the files limit
|
||||
var rLimit syscall.Rlimit
|
||||
rLimit.Max = 10000
|
||||
rLimit.Cur = 10000
|
||||
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
|
||||
if err != nil {
|
||||
fmt.Println(Red("Error Setting Rlimit "), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Info returns the general informations about Realize
|
||||
func Info() *App {
|
||||
return &App{
|
||||
Name: AppName,
|
||||
Version: AppVersion,
|
||||
Description: AppDescription,
|
||||
}
|
||||
}
|
||||
|
||||
// Cewrites the log timestamp
|
||||
func (writer logWriter) Write(bytes []byte) (int, error) {
|
||||
return fmt.Print(YellowS("[") + time.Now().Format("15:04:05") + YellowS("]") + string(bytes))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
package realize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// App struct contains the informations about realize
|
||||
type Realize struct {
|
||||
Name, Description, Author, Email string
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Limit uint64
|
||||
Blueprint Blueprint
|
||||
}
|
||||
|
||||
// Projects struct contains a projects list
|
||||
type Blueprint struct {
|
||||
Projects []Project `yaml:"projects,omitempty"`
|
||||
files map[string]string
|
||||
}
|
||||
|
||||
// Project defines the informations of a single project
|
||||
type Project struct {
|
||||
reload time.Time
|
||||
base string
|
||||
Name string `yaml:"app_name,omitempty"`
|
||||
Path string `yaml:"app_path,omitempty"`
|
||||
Run bool `yaml:"app_run,omitempty"`
|
||||
Bin bool `yaml:"app_bin,omitempty"`
|
||||
Build bool `yaml:"app_build,omitempty"`
|
||||
Fmt bool `yaml:"app_fmt,omitempty"`
|
||||
Test bool `yaml:"app_test,omitempty"`
|
||||
Params []string `yaml:"app_params,omitempty"`
|
||||
Watcher Watcher `yaml:"app_watcher,omitempty"`
|
||||
}
|
||||
|
||||
// Wdir returns the name last element of the working directory path
|
||||
func (r *Realize) Wdir() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(Red(err))
|
||||
}
|
||||
return filepath.Base(dir)
|
||||
}
|
||||
|
||||
// Limit defines the max number of watched files
|
||||
func (r *Realize) limit() {
|
||||
// increases the files limit
|
||||
var rLimit syscall.Rlimit
|
||||
rLimit.Max = r.Limit
|
||||
rLimit.Cur = r.Limit
|
||||
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
|
||||
if err != nil {
|
||||
fmt.Println(Red("Error Setting Rlimit "), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Watch method adds the given paths on the Watcher
|
||||
func (h *Blueprint) Run() error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
// loop projects
|
||||
wg.Add(len(h.Projects))
|
||||
for k := range h.Projects {
|
||||
go h.Projects[k].watching()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Fast method run a project from his working directory without makes a config file
|
||||
func (h *Blueprint) Fast(params *cli.Context) error {
|
||||
fast := h.Projects[0]
|
||||
// Takes the values from config if wd path match with someone else
|
||||
if params.Bool("config") {
|
||||
if err := h.Read(); err == nil {
|
||||
for _, val := range h.Projects {
|
||||
if fast.Path == val.Path {
|
||||
fast = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wg.Add(1)
|
||||
go fast.watching()
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add a new project
|
||||
func (h *Blueprint) Add(params *cli.Context) error {
|
||||
p := Project{
|
||||
Name: nameFlag(params),
|
||||
Path: filepath.Clean(params.String("path")),
|
||||
Build: params.Bool("build"),
|
||||
Bin: boolFlag(params.Bool("no-bin")),
|
||||
Run: boolFlag(params.Bool("no-run")),
|
||||
Fmt: boolFlag(params.Bool("no-fmt")),
|
||||
Test: params.Bool("test"),
|
||||
Params: argsParam(params),
|
||||
Watcher: Watcher{
|
||||
Paths: []string{"/"},
|
||||
Ignore: []string{"vendor"},
|
||||
Exts: []string{".go"},
|
||||
Output: map[string]bool{
|
||||
"cli": true,
|
||||
"file": false,
|
||||
},
|
||||
},
|
||||
}
|
||||
if _, err := duplicates(p, h.Projects); err != nil {
|
||||
return err
|
||||
}
|
||||
h.Projects = append(h.Projects, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clean duplicate projects
|
||||
func (h *Blueprint) Clean() {
|
||||
arr := h.Projects
|
||||
for key, val := range arr {
|
||||
if _, err := duplicates(val, arr[key+1:]); err != nil {
|
||||
h.Projects = append(arr[:key], arr[key+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read, Check and remove duplicates from the config file
|
||||
func (h *Blueprint) Read() error {
|
||||
content, err := read(h.files["config"])
|
||||
if err == nil {
|
||||
err = yaml.Unmarshal(content, h)
|
||||
if err == nil {
|
||||
if len(h.Projects) > 0 {
|
||||
h.Clean()
|
||||
return nil
|
||||
}
|
||||
return errors.New("There are no projects!")
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Create and unmarshal yaml config file
|
||||
func (h *Blueprint) Create() error {
|
||||
y, err := yaml.Marshal(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return write(h.files["config"], y)
|
||||
}
|
||||
|
||||
// Inserts a new project in the list
|
||||
func (h *Blueprint) Insert(params *cli.Context) error {
|
||||
check := h.Read()
|
||||
err := h.Add(params)
|
||||
if err == nil {
|
||||
err = h.Create()
|
||||
if check == nil && err == nil {
|
||||
fmt.Println(Green("Your project was successfully added"))
|
||||
} else {
|
||||
fmt.Println(Green("The config file was successfully created"))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove a project
|
||||
func (h *Blueprint) Remove(params *cli.Context) error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
for key, val := range h.Projects {
|
||||
if params.String("name") == val.Name {
|
||||
h.Projects = append(h.Projects[:key], h.Projects[key+1:]...)
|
||||
err = h.Create()
|
||||
if err == nil {
|
||||
fmt.Println(Green("Your project was successfully removed"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return errors.New("No project found")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// List of all the projects
|
||||
func (h *Blueprint) List() error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
for _, val := range h.Projects {
|
||||
fmt.Println(Blue("|"), Blue(strings.ToUpper(val.Name)))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Base Path"), ":", MagentaS(val.Path))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Run"), ":", MagentaS(val.Run))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Build"), ":", MagentaS(val.Build))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Install"), ":", MagentaS(val.Bin))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Fmt"), ":", MagentaS(val.Fmt))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Test"), ":", MagentaS(val.Test))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Params"), ":", MagentaS(val.Params))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Watcher"), ":")
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("After"), ":", MagentaS(val.Watcher.After))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Before"), ":", MagentaS(val.Watcher.Before))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Extensions"), ":", MagentaS(val.Watcher.Exts))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths"), ":", MagentaS(val.Watcher.Paths))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths ignored"), ":", MagentaS(val.Watcher.Ignore))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Watch preview"), ":", MagentaS(val.Watcher.Preview))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Output"), ":")
|
||||
fmt.Println(MagentaS("|"), "\t\t\t", Yellow("Cli"), ":", MagentaS(val.Watcher.Output["cli"]))
|
||||
fmt.Println(MagentaS("|"), "\t\t\t", Yellow("File"), ":", MagentaS(val.Watcher.Output["file"]))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
package realize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config struct contains the general informations about a project
|
||||
type Config struct {
|
||||
file string
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Projects []Project
|
||||
}
|
||||
|
||||
// New method puts the cli params in the struct
|
||||
func New(params *cli.Context) *Config {
|
||||
return &Config{
|
||||
file: AppFile,
|
||||
Version: AppVersion,
|
||||
Projects: []Project{
|
||||
{
|
||||
Name: nameFlag(params),
|
||||
Path: filepath.Clean(params.String("path")),
|
||||
Build: params.Bool("build"),
|
||||
Bin: boolFlag(params.Bool("no-bin")),
|
||||
Run: boolFlag(params.Bool("no-run")),
|
||||
Fmt: boolFlag(params.Bool("no-fmt")),
|
||||
Test: params.Bool("test"),
|
||||
Params: argsParam(params),
|
||||
Watcher: Watcher{
|
||||
Paths: watcherPaths,
|
||||
Ignore: watcherIgnores,
|
||||
Exts: watcherExts,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// argsParam parse one by one the given argumentes
|
||||
func argsParam(params *cli.Context) []string {
|
||||
argsN := params.NArg()
|
||||
if argsN > 0 {
|
||||
var args []string
|
||||
for i := 0; i <= argsN-1; i++ {
|
||||
args = append(args, params.Args().Get(i))
|
||||
}
|
||||
return args
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NameParam check the project name presence. If empty takes the working directory name
|
||||
func nameFlag(params *cli.Context) string {
|
||||
var name string
|
||||
if params.String("name") == "" && params.String("path") == "" {
|
||||
return WorkingDir()
|
||||
} else if params.String("path") != "/" {
|
||||
name = filepath.Base(params.String("path"))
|
||||
} else {
|
||||
name = params.String("name")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// BoolParam is used to check the presence of a bool flag
|
||||
func boolFlag(b bool) bool {
|
||||
if b {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// WorkingDir returns the last element of the working dir path
|
||||
func WorkingDir() string {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(Red(err))
|
||||
}
|
||||
return filepath.Base(dir)
|
||||
}
|
||||
|
||||
// Duplicates check projects with same name or same combinations of main/path
|
||||
func Duplicates(value Project, arr []Project) (Project, error) {
|
||||
for _, val := range arr {
|
||||
if value.Path == val.Path || value.Name == val.Name {
|
||||
return val, errors.New("There is a duplicate of '" + val.Name + "'. Check your config file!")
|
||||
}
|
||||
}
|
||||
return Project{}, nil
|
||||
}
|
||||
|
||||
// Clean duplicate projects
|
||||
func (h *Config) Clean() {
|
||||
arr := h.Projects
|
||||
for key, val := range arr {
|
||||
if _, err := Duplicates(val, arr[key+1:]); err != nil {
|
||||
h.Projects = append(arr[:key], arr[key+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read, Check and remove duplicates from the config file
|
||||
func (h *Config) Read() error {
|
||||
_, err := os.Stat(h.file)
|
||||
if err == nil {
|
||||
file, err := ioutil.ReadFile(h.file)
|
||||
if err == nil {
|
||||
if len(h.Projects) > 0 {
|
||||
err = yaml.Unmarshal(file, h)
|
||||
if err == nil {
|
||||
h.Clean()
|
||||
}
|
||||
return err
|
||||
}
|
||||
return errors.New("There are no projects")
|
||||
}
|
||||
return h.Create()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Create and unmarshal yaml config file
|
||||
func (h *Config) Create() error {
|
||||
y, err := yaml.Marshal(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(h.file, y, 0655)
|
||||
}
|
||||
|
||||
// Add another project
|
||||
func (h *Config) Add(params *cli.Context) error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
new := Project{
|
||||
Name: nameFlag(params),
|
||||
Path: filepath.Clean(params.String("path")),
|
||||
Build: params.Bool("build"),
|
||||
Bin: boolFlag(params.Bool("no-bin")),
|
||||
Run: boolFlag(params.Bool("no-run")),
|
||||
Fmt: boolFlag(params.Bool("no-fmt")),
|
||||
Test: params.Bool("test"),
|
||||
Params: argsParam(params),
|
||||
Watcher: Watcher{
|
||||
Paths: watcherPaths,
|
||||
Exts: watcherExts,
|
||||
Ignore: watcherIgnores,
|
||||
},
|
||||
}
|
||||
if _, err := Duplicates(new, h.Projects); err != nil {
|
||||
return err
|
||||
}
|
||||
h.Projects = append(h.Projects, new)
|
||||
err = h.Create()
|
||||
if err == nil {
|
||||
fmt.Println(Green("Your project was successfully added"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = h.Create()
|
||||
if err == nil {
|
||||
fmt.Println(Green("The config file was successfully created"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove a project in list
|
||||
func (h *Config) Remove(params *cli.Context) error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
for key, val := range h.Projects {
|
||||
if params.String("name") == val.Name {
|
||||
h.Projects = append(h.Projects[:key], h.Projects[key+1:]...)
|
||||
err = h.Create()
|
||||
if err == nil {
|
||||
fmt.Println(Green("Your project was successfully removed"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return errors.New("No project found")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// List of projects
|
||||
func (h *Config) List() error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
for _, val := range h.Projects {
|
||||
fmt.Println(Blue("|"), Blue(strings.ToUpper(val.Name)))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Base Path"), ":", MagentaS(val.Path))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Run"), ":", MagentaS(val.Run))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Build"), ":", MagentaS(val.Build))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Install"), ":", MagentaS(val.Bin))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Fmt"), ":", MagentaS(val.Fmt))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Test"), ":", MagentaS(val.Test))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Params"), ":", MagentaS(val.Params))
|
||||
fmt.Println(MagentaS("|"), "\t", Yellow("Watcher"), ":")
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("After"), ":", MagentaS(val.Watcher.After))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Before"), ":", MagentaS(val.Watcher.Before))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Extensions"), ":", MagentaS(val.Watcher.Exts))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths"), ":", MagentaS(val.Watcher.Paths))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Paths ignored"), ":", MagentaS(val.Watcher.Ignore))
|
||||
fmt.Println(MagentaS("|"), "\t\t", Yellow("Watch preview"), ":", MagentaS(val.Watcher.Preview))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -12,21 +12,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// The Project struct defines the informations about a project
|
||||
type Project struct {
|
||||
reload time.Time
|
||||
base string
|
||||
Name string `yaml:"app_name,omitempty"`
|
||||
Path string `yaml:"app_path,omitempty"`
|
||||
Run bool `yaml:"app_run,omitempty"`
|
||||
Bin bool `yaml:"app_bin,omitempty"`
|
||||
Build bool `yaml:"app_build,omitempty"`
|
||||
Fmt bool `yaml:"app_fmt,omitempty"`
|
||||
Test bool `yaml:"app_test,omitempty"`
|
||||
Params []string `yaml:"app_params,omitempty"`
|
||||
Watcher Watcher `yaml:"app_watcher,omitempty"`
|
||||
}
|
||||
|
||||
// GoRun is an implementation of the bin execution
|
||||
func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error {
|
||||
|
||||
|
@ -51,7 +36,6 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
|
||||
// Read stdout and stderr in same var
|
||||
outputs := io.MultiReader(stdout, stderr)
|
||||
|
||||
if err != nil {
|
||||
log.Println(Red(err.Error()))
|
||||
return err
|
||||
|
@ -67,8 +51,18 @@ func (p *Project) GoRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
for in.Scan() {
|
||||
select {
|
||||
default:
|
||||
if p.Watcher.Output["cli"] {
|
||||
log.Println(pname(p.Name, 3), ":", BlueS(in.Text()))
|
||||
}
|
||||
if p.Watcher.Output["file"] {
|
||||
path := filepath.Join(p.base, App.Blueprint.files["output"])
|
||||
f := create(path)
|
||||
t := time.Now()
|
||||
if _, err := f.WriteString(t.Format("2006-01-02 15:04:05") + " : " + in.Text() + "\r\n"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(stop)
|
||||
}()
|
|
@ -0,0 +1,130 @@
|
|||
package realize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Read a file given a name and return its byte stream
|
||||
func read(file string) ([]byte, error) {
|
||||
_, err := os.Stat(file)
|
||||
if err == nil {
|
||||
content, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return content, err
|
||||
}
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
// Write a file given a name and a byte stream
|
||||
func write(name string, data []byte) error {
|
||||
err := ioutil.WriteFile(name, data, 0655)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new file and return its pointer
|
||||
func create(file string) *os.File {
|
||||
out, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0655)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// argsParam parse one by one the given argumentes
|
||||
func argsParam(params *cli.Context) []string {
|
||||
argsN := params.NArg()
|
||||
if argsN > 0 {
|
||||
var args []string
|
||||
for i := 0; i <= argsN-1; i++ {
|
||||
args = append(args, params.Args().Get(i))
|
||||
}
|
||||
return args
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NameParam check the project name presence. If empty takes the working directory name
|
||||
func nameFlag(params *cli.Context) string {
|
||||
var name string
|
||||
if params.String("name") == "" && params.String("path") == "" {
|
||||
return App.Wdir()
|
||||
} else if params.String("path") != "/" {
|
||||
name = filepath.Base(params.String("path"))
|
||||
} else {
|
||||
name = params.String("name")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// BoolParam is used to check the presence of a bool flag
|
||||
func boolFlag(b bool) bool {
|
||||
if b {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Duplicates check projects with same name or same combinations of main/path
|
||||
func duplicates(value Project, arr []Project) (Project, error) {
|
||||
for _, val := range arr {
|
||||
if value.Path == val.Path || value.Name == val.Name {
|
||||
return val, errors.New("There is a duplicate of '" + val.Name + "'. Check your config file!")
|
||||
}
|
||||
}
|
||||
return Project{}, nil
|
||||
}
|
||||
|
||||
// check if a string is inArray
|
||||
func inArray(str string, list []string) bool {
|
||||
for _, v := range list {
|
||||
if v == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Defines the colors scheme for the project name
|
||||
func pname(name string, color int) string {
|
||||
switch color {
|
||||
case 1:
|
||||
name = Yellow("[") + strings.ToUpper(name) + Yellow("]")
|
||||
break
|
||||
case 2:
|
||||
name = Yellow("[") + Red(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 3:
|
||||
name = Yellow("[") + Blue(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 4:
|
||||
name = Yellow("[") + Magenta(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 5:
|
||||
name = Yellow("[") + Green(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// Log struct
|
||||
type logWriter struct{}
|
||||
|
||||
// Cewrites the log timestamp
|
||||
func (writer logWriter) Write(bytes []byte) (int, error) {
|
||||
return fmt.Print(YellowS("[") + time.Now().Format("15:04:05") + YellowS("]") + string(bytes))
|
||||
}
|
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -23,40 +22,7 @@ type Watcher struct {
|
|||
Ignore []string `yaml:"ignore_paths,omitempty"`
|
||||
Exts []string `yaml:"exts,omitempty"`
|
||||
Preview bool `yaml:"preview,omitempty"`
|
||||
}
|
||||
|
||||
// Watch method adds the given paths on the Watcher
|
||||
func (h *Config) Watch() error {
|
||||
err := h.Read()
|
||||
if err == nil {
|
||||
// loop projects
|
||||
wg.Add(len(h.Projects))
|
||||
for k := range h.Projects {
|
||||
go h.Projects[k].watching()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Fast method run a project from his working directory without makes a config file
|
||||
func (h *Config) Fast(params *cli.Context) error {
|
||||
fast := h.Projects[0]
|
||||
// Takes the values from config if wd path match with someone else
|
||||
if params.Bool("config") {
|
||||
if err := h.Read(); err == nil {
|
||||
for _, val := range h.Projects {
|
||||
if fast.Path == val.Path {
|
||||
fast = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wg.Add(1)
|
||||
go fast.watching()
|
||||
wg.Wait()
|
||||
return nil
|
||||
Output map[string]bool `yaml:"output,omitempty"`
|
||||
}
|
||||
|
||||
// Watching method is the main core. It manages the livereload and the watching
|
||||
|
@ -84,7 +50,7 @@ func (p *Project) watching() {
|
|||
fmt.Println(pname(p.Name, 1), ":", Red(err.Error()))
|
||||
return
|
||||
}
|
||||
go routines(p, channel, &wr)
|
||||
go p.routines(channel, &wr)
|
||||
p.reload = time.Now().Truncate(time.Second)
|
||||
|
||||
// waiting for an event
|
||||
|
@ -117,7 +83,7 @@ func (p *Project) watching() {
|
|||
if err != nil {
|
||||
log.Fatal(Red(err))
|
||||
} else {
|
||||
go routines(p, channel, &wr)
|
||||
go p.routines(channel, &wr)
|
||||
p.reload = time.Now().Truncate(time.Second)
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +196,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
|
|||
|
||||
if p.Path == "." || p.Path == "/" {
|
||||
p.base = wd
|
||||
p.Path = WorkingDir()
|
||||
p.Path = App.Wdir()
|
||||
} else if filepath.IsAbs(p.Path) {
|
||||
p.base = p.Path
|
||||
} else {
|
||||
|
@ -247,7 +213,7 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
|
|||
return errors.New(base + " path doesn't exist")
|
||||
}
|
||||
}
|
||||
fmt.Println(Red("Watching: "), pname(p.Name, 1), Magenta(files), "file/s", Magenta(folders), "folder/s")
|
||||
fmt.Println(Red("Watching"), ":", pname(p.Name, 1), Magenta(files), "file/s", Magenta(folders), "folder/s")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -262,41 +228,9 @@ func (p *Project) ignore(str string) bool {
|
|||
}
|
||||
|
||||
// Routines launches the following methods: run, build, fmt, install
|
||||
func routines(p *Project, channel chan bool, wr *sync.WaitGroup) {
|
||||
func (p *Project) routines(channel chan bool, wr *sync.WaitGroup) {
|
||||
wr.Add(1)
|
||||
go p.build()
|
||||
go p.install(channel, wr)
|
||||
wr.Wait()
|
||||
}
|
||||
|
||||
// check if a string is inArray
|
||||
func inArray(str string, list []string) bool {
|
||||
for _, v := range list {
|
||||
if v == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// defines the colors scheme for the project name
|
||||
func pname(name string, color int) string {
|
||||
switch color {
|
||||
case 1:
|
||||
name = Yellow("[") + strings.ToUpper(name) + Yellow("]")
|
||||
break
|
||||
case 2:
|
||||
name = Yellow("[") + Red(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 3:
|
||||
name = Yellow("[") + Blue(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 4:
|
||||
name = Yellow("[") + Magenta(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
case 5:
|
||||
name = Yellow("[") + Green(strings.ToUpper(name)) + Yellow("]")
|
||||
break
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue