commit
b1d3486324
|
@ -6,4 +6,10 @@ go:
|
|||
- tip
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- go get ./...
|
||||
|
||||
script:
|
||||
- go install .
|
328
README.md
328
README.md
|
@ -17,176 +17,206 @@ A Go build system with file watchers, output streams and live reload. Run, build
|
|||
#### Features
|
||||
|
||||
- Highly customizable
|
||||
- Config your project Step by Step
|
||||
- Build, Install, Test, Fmt, Generate and Run at the same time
|
||||
- Live reload on file changes (re-build, re-install...)
|
||||
- Watch custom paths and specific file extensions
|
||||
- Watch by FsNotify or by polling
|
||||
- Support for multiple projects
|
||||
- Output streams and error logs (Watch them in console or save them on a file)
|
||||
- Web Panel (Watch all projects, edit the config settings, download each type of log)
|
||||
- Output streams and error logs (support for save on a file)
|
||||
- Web Panel (projects list, config settings, logs)
|
||||
|
||||
#### Installation and usage
|
||||
#### Wiki
|
||||
|
||||
- Run this to get/install:
|
||||
- [Getting Started](#installation-and-usage)
|
||||
- [Run cmd](#run) - Run a project
|
||||
- [Add cmd](#add) - Add a new project
|
||||
- [Init cmd](#init) - Make a custom config step by step
|
||||
- [Remove cmd](#remove) - Remove a project
|
||||
- [List cmd](#list) - List the projects
|
||||
- [Config sample](#config-sample)
|
||||
- [Support](#support)
|
||||
|
||||
```
|
||||
$ go get github.com/tockins/realize
|
||||
```
|
||||
|
||||
- From project/projects root execute:
|
||||
|
||||
```
|
||||
$ realize add
|
||||
```
|
||||
|
||||
It will create a realize.yaml file if it doesn't exist already and adds the working directory as project.
|
||||
|
||||
Otherwise if a config file already exists it adds the working project to the existing config file.
|
||||
|
||||
The Add command supports the following custom parameters:
|
||||
|
||||
```
|
||||
--name="Project Name" -> Name, if not specified takes the working directory name
|
||||
--path="server" -> Custom Path, if not specified takes the working directory name
|
||||
--build -> Enables the build
|
||||
--test -> Enables the tests
|
||||
--no-bin -> Disables the installation
|
||||
--no-run -> Disables the run
|
||||
--no-fmt -> Disables the fmt (go fmt)
|
||||
--no-server -> Disables the web panel (default port 5001)
|
||||
--open -> Open the web panel in a new browser window
|
||||
```
|
||||
Examples:
|
||||
|
||||
```
|
||||
$ realize add
|
||||
|
||||
$ realize add --path="mypath"
|
||||
|
||||
$ realize add --name="My Project" --build
|
||||
|
||||
$ realize add --name="My Project" --path="/projects/package" --build
|
||||
|
||||
$ realize add --name="My Project" --path="projects/package" --build --no-run
|
||||
|
||||
$ realize add --path="/Users/alessio/go/src/github.com/tockins/realize-examples/coin/"
|
||||
```
|
||||
|
||||
If you want, you can specify additional arguments for your project.
|
||||
|
||||
**The additional arguments must go after the options of "Realize"**
|
||||
|
||||
```
|
||||
$ realize add --path="/print/printer" --no-run yourParams --yourFlags // correct
|
||||
|
||||
$ realize add yourParams --yourFlags --path="/print/printer" --no-run // wrong
|
||||
```
|
||||
|
||||
- Remove a project by its name
|
||||
|
||||
```
|
||||
$ realize remove --name="Project Name"
|
||||
```
|
||||
- Lists all projects
|
||||
|
||||
```
|
||||
$ realize list
|
||||
```
|
||||
- Build, Run and watch file changes. Realize will re-build and re-run your projects on each change.
|
||||
- ##### Installation
|
||||
Run this to get/install:
|
||||
```
|
||||
$ go get github.com/tockins/realize
|
||||
```
|
||||
#### Commands
|
||||
|
||||
- ##### Run
|
||||
From project/projects root execute:
|
||||
```
|
||||
$ realize run
|
||||
```
|
||||
|
||||
Run can also launch a project from its working directory with or without make a config file (--no-config option).
|
||||
It supports the following custom parameters:
|
||||
|
||||
It will create a realize.yaml file if it doesn't exist already, adds the working directory as project and run the pipeline.
|
||||
|
||||
The Run command supports the following custom parameters:
|
||||
|
||||
```
|
||||
--path="server" -> Custom Path, if not specified takes the working directory name
|
||||
--build -> Enables the build
|
||||
--test -> Enables the tests
|
||||
--config -> Take the defined settings if exist a config file
|
||||
--no-bin -> Disables the installation
|
||||
--no-run -> Disables the run
|
||||
--no-fmt -> Disables the fmt (go fmt)
|
||||
--no-server -> Disables the web panel (port :5000)
|
||||
--no-config -> Doesn't create any configuration files
|
||||
--open -> Open the web panel in a new browser window
|
||||
```
|
||||
And additional arguments as the "add" command.
|
||||
--path="realize/server" -> Custom Path, if not specified takes the working directory name
|
||||
--build -> Enable go build
|
||||
--no-run -> Disable go run
|
||||
--no-install -> Disable go install
|
||||
--no-config -> Ignore an existing config / skip the creation of a new one
|
||||
--server -> Enable the web server
|
||||
--legacy -> Enable legacy watch instead of Fsnotify watch
|
||||
--generate -> Enable go generate
|
||||
--test -> Enable go test
|
||||
```
|
||||
Examples:
|
||||
|
||||
```
|
||||
$ realize run --no-run yourParams --yourFlags // correct
|
||||
|
||||
$ realize run yourParams --yourFlags --no-run // wrong
|
||||
|
||||
$ realize run
|
||||
$ realize run --path="mypath"
|
||||
$ realize run --name="My Project" --build
|
||||
$ realize run --path="realize" --no-run --no-config
|
||||
$ realize run --path="/Users/alessio/go/src/github.com/tockins/realize-examples/coin/"
|
||||
```
|
||||
```
|
||||
|
||||
If you want, you can specify additional arguments for your project.
|
||||
|
||||
**The additional arguments must go after the params**
|
||||
|
||||
**Run can run a project from its working directory without make a config file (--no-config).**
|
||||
|
||||
```
|
||||
$ realize run --path="/print/printer" --no-run yourParams --yourFlags // right
|
||||
$ realize run yourParams --yourFlags --path="/print/printer" --no-run // wrong
|
||||
```
|
||||
- ##### Add
|
||||
Add a project to an existing config file or create a new one without run the pipeline.
|
||||
|
||||
"Add" supports the same parameters of the "Run" command.
|
||||
|
||||
```
|
||||
$ realize add
|
||||
```
|
||||
|
||||
#### Color reference
|
||||
- ##### Init
|
||||
Like add, but with this command you can create a configuration step by step and customize each option.
|
||||
|
||||
**Init is the only command that supports a complete customization of all the options supported**
|
||||
|
||||
```
|
||||
$ realize init
|
||||
```
|
||||
|
||||
- Blue: outputs of the project
|
||||
- Red: errors
|
||||
- Magenta: times or changed files
|
||||
- Green: successfully completed action
|
||||
- ##### Remove
|
||||
Remove a project by its name
|
||||
```
|
||||
$ realize remove --name="myname"
|
||||
```
|
||||
|
||||
- ##### List
|
||||
Projects list in cli
|
||||
```
|
||||
$ realize list
|
||||
```
|
||||
|
||||
- #### Color reference
|
||||
- Blue: outputs of the project
|
||||
- Red: errors
|
||||
- Magenta: times or changed files
|
||||
- Green: successfully completed action
|
||||
|
||||
|
||||
#### Config file example
|
||||
|
||||
- For more examples check [Realize Examples](https://github.com/tockins/realize-examples)
|
||||
|
||||
```
|
||||
settings:
|
||||
resources:
|
||||
output: outputs.log // name of the output file
|
||||
log: logs.log // name of the log file (errors included)
|
||||
server:
|
||||
enable: true // enables the web server
|
||||
open: false // opens the web server in a new tab
|
||||
host: localhost // web server host
|
||||
port: 5000 // wev server port
|
||||
config:
|
||||
flimit: 0 // increases the maximum number of open files - supported only on linux or os x, sudo required
|
||||
projects:
|
||||
- name: printer // project name
|
||||
path: / // project path
|
||||
run: true // enables go run (require bin)
|
||||
bin: true // enables go install
|
||||
generate: false // enables go generate
|
||||
build: false // enables go build
|
||||
fmt: true // enables go fmt
|
||||
test: false // enables go test
|
||||
params: [] // array of additionals params. the project will be launched with these parameters
|
||||
watcher:
|
||||
before: [] // custom commands launched before the execution of the project
|
||||
after: [] // custom commands launched after the execution of the project
|
||||
paths: // paths to observe for live reload
|
||||
- /
|
||||
ignore_paths: // paths to ignore
|
||||
- vendor
|
||||
exts: // file extensions to observe for live reload
|
||||
- .go
|
||||
preview: true // prints the observed files on startup
|
||||
cli:
|
||||
streams: true // prints the output streams of the project in the cli
|
||||
file:
|
||||
streams: false // saves the output stream of the project in a file
|
||||
logs: false // saves the logs of the project in a file
|
||||
errors: false // saves the errors of the project in a file
|
||||
```
|
||||
|
||||
#### Next features, in progress...
|
||||
|
||||
- [ ] Web panel - edit settings (full support)
|
||||
- [ ] Web panel - logs download
|
||||
- [ ] Schedule - reload a project after a specific time
|
||||
- [ ] Easy dependencies - automatically resolve the project dependencies
|
||||
- [ ] Import license - retrieve the license for each imported library
|
||||
- [ ] Tests
|
||||
- #### Config sample
|
||||
|
||||
For more examples check [Realize Examples](https://github.com/tockins/realize-examples)
|
||||
|
||||
```
|
||||
settings:
|
||||
legacy:
|
||||
status: true // legacy watch status
|
||||
interval: 10s // polling interval
|
||||
resources: // files names related to streams
|
||||
outputs: outputs.log
|
||||
logs: logs.log
|
||||
errors: errors.log
|
||||
server:
|
||||
status: true // server status
|
||||
open: false // auto open in browser on start
|
||||
host: localhost // server host
|
||||
port: 5001 // server port
|
||||
projects:
|
||||
- name: realize
|
||||
path: . // project path
|
||||
fmt: true
|
||||
generate: false
|
||||
test: false
|
||||
bin: true
|
||||
build: false
|
||||
run: false
|
||||
params: // additional params
|
||||
- --myarg
|
||||
watcher:
|
||||
preview: false // wached files preview
|
||||
paths: // paths to watch
|
||||
- /
|
||||
ignore_paths: // paths to ignore
|
||||
- vendor
|
||||
exts: // exts to watch
|
||||
- .go
|
||||
scripts: // custom commands after/before
|
||||
- type: after // type after/before
|
||||
command: go run mycmd after // command
|
||||
path: "" // run from a custom path or from the working dir
|
||||
streams: // enable/disable streams
|
||||
cli_out: true
|
||||
file_out: false
|
||||
file_log: false
|
||||
file_err: false
|
||||
|
||||
```
|
||||
This is the configuration used for develop realize
|
||||
|
||||
```
|
||||
settings:
|
||||
resources:
|
||||
outputs: outputs.log
|
||||
logs: logs.log
|
||||
errors: errors.log
|
||||
server:
|
||||
status: false
|
||||
open: false
|
||||
host: localhost
|
||||
port: 5001
|
||||
projects:
|
||||
- name: realize
|
||||
path: /Users/alessio/go/src/github.com/tockins/realize
|
||||
fmt: true
|
||||
generate: false
|
||||
test: false
|
||||
bin: true
|
||||
build: false
|
||||
run: false
|
||||
watcher:
|
||||
preview: false
|
||||
paths:
|
||||
- /
|
||||
ignore_paths:
|
||||
- server/assets
|
||||
exts:
|
||||
- .go
|
||||
scripts:
|
||||
- type: before
|
||||
command: go-bindata -pkg="server" assets/...
|
||||
path: server
|
||||
- type: after
|
||||
command: go-bindata -pkg="server" assets/...
|
||||
path: server
|
||||
streams:
|
||||
cli_out: true
|
||||
file_out: false
|
||||
file_log: false
|
||||
file_err: false
|
||||
```
|
||||
|
||||
|
||||
#### Contacts
|
||||
|
||||
###### Support us and suggest an improvement
|
||||
- Start the project
|
||||
- Chat with us [Gitter](https://gitter.im/tockins/realize)
|
||||
|
||||
- [Alessio Pracchia](https://www.linkedin.com/in/alessio-pracchia-38a70673)
|
||||
- [Daniele Conventi](https://www.linkedin.com/in/conventi)
|
||||
- Suggest a new [Feature](https://github.com/tockins/realize/issues/new)
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
{
|
||||
"memo": "0dae7877c338a668c3b0b2c64112895cd2076b90c0792ca2a0edf22fb10d14d2",
|
||||
"projects": [
|
||||
{
|
||||
"name": "github.com/dgrijalva/jwt-go",
|
||||
"version": "v3.0.0",
|
||||
"revision": "d2709f9f1f31ebcda9651b03077758c1f3a0018c",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/fatih/color",
|
||||
"version": "v1.4.1",
|
||||
"revision": "9131ab34cf20d2f6d83fdc67168a5430d1c7dc23",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/fsnotify/fsnotify",
|
||||
"branch": "master",
|
||||
"revision": "4da3e2cfbabc9f751898f250b49f2439785783a1",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/labstack/echo",
|
||||
"version": "v3.0.3",
|
||||
"revision": "8d504c1b699c757b267255c53b3e5219f9974abc",
|
||||
"packages": [
|
||||
".",
|
||||
"middleware"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/labstack/gommon",
|
||||
"version": "v0.2.0",
|
||||
"revision": "9cedb429ffbe71a32a3ae7c65fd109cb7ae07804",
|
||||
"packages": [
|
||||
"bytes",
|
||||
"color",
|
||||
"log",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/mattn/go-colorable",
|
||||
"version": "v0.0.7",
|
||||
"revision": "d228849504861217f796da67fae4f6e347643f15",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/mattn/go-isatty",
|
||||
"version": "v0.0.2",
|
||||
"revision": "fc9e8d8ef48496124e79ae0df75490096eccf6fe",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/tockins/interact",
|
||||
"branch": "master",
|
||||
"revision": "7dfb115b4849a7d87b2b8368a076959c2bf56e35",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/tylerb/graceful",
|
||||
"version": "v1.2.15",
|
||||
"revision": "4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/valyala/bytebufferpool",
|
||||
"branch": "master",
|
||||
"revision": "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "github.com/valyala/fasttemplate",
|
||||
"branch": "master",
|
||||
"revision": "dcecefd839c4193db0d35b88ec65b4c12d360ab0",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "golang.org/x/crypto",
|
||||
"branch": "master",
|
||||
"revision": "3cb07270c9455e8ad27956a70891c962d121a228",
|
||||
"packages": [
|
||||
"acme",
|
||||
"acme/autocert"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "golang.org/x/net",
|
||||
"branch": "master",
|
||||
"revision": "ffcf1bedda3b04ebb15a168a59800a73d6dc0f4d",
|
||||
"packages": [
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
"websocket"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "golang.org/x/sys",
|
||||
"branch": "master",
|
||||
"revision": "9a7256cb28ed514b4e1e5f68959914c4c28a92e0",
|
||||
"packages": [
|
||||
"unix"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gopkg.in/urfave/cli.v2",
|
||||
"branch": "v2",
|
||||
"revision": "04b2f4ff79cf1fd71e138bafc67df8bbdb5b81c2",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gopkg.in/yaml.v2",
|
||||
"branch": "v2",
|
||||
"revision": "a3f3340b5840cee44f372bddb5880fcbc419b46a",
|
||||
"packages": [
|
||||
"."
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"github.com/fatih/color": {
|
||||
"branch": "master"
|
||||
},
|
||||
"github.com/fsnotify/fsnotify": {
|
||||
"branch": "master"
|
||||
},
|
||||
"github.com/labstack/echo": {
|
||||
"version": "^3.0.3"
|
||||
},
|
||||
"github.com/tockins/interact": {
|
||||
"branch": "master"
|
||||
},
|
||||
"golang.org/x/net": {
|
||||
"branch": "master"
|
||||
},
|
||||
"gopkg.in/urfave/cli.v2": {
|
||||
"branch": "v2"
|
||||
},
|
||||
"gopkg.in/yaml.v2": {
|
||||
"branch": "v2"
|
||||
}
|
||||
}
|
||||
}
|
825
realize.go
825
realize.go
|
@ -3,25 +3,27 @@ package main
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
i "github.com/tockins/interact"
|
||||
s "github.com/tockins/realize/server"
|
||||
c "github.com/tockins/realize/settings"
|
||||
w "github.com/tockins/realize/watcher"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
name = "Realize"
|
||||
version = "1.2.1"
|
||||
version = "1.3"
|
||||
description = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths"
|
||||
config = "realize.yaml"
|
||||
streams = "streams.log"
|
||||
outputs = "outputs.log"
|
||||
errs = "errors.log"
|
||||
logs = "logs.log"
|
||||
host = "localhost"
|
||||
port = 5001
|
||||
server = true
|
||||
open = false
|
||||
interval = 200
|
||||
)
|
||||
|
||||
var r realize
|
||||
|
@ -45,19 +47,19 @@ func init() {
|
|||
Sync: make(chan string),
|
||||
Settings: c.Settings{
|
||||
Config: c.Config{
|
||||
Flimit: 0,
|
||||
Create: true,
|
||||
},
|
||||
Resources: c.Resources{
|
||||
Config: config,
|
||||
Streams: streams,
|
||||
Outputs: outputs,
|
||||
Logs: logs,
|
||||
Errors: errs,
|
||||
},
|
||||
Server: c.Server{
|
||||
Enabled: server,
|
||||
Open: open,
|
||||
Host: host,
|
||||
Port: port,
|
||||
Status: false,
|
||||
Open: false,
|
||||
Host: host,
|
||||
Port: port,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -83,8 +85,6 @@ func init() {
|
|||
|
||||
// Before of every exec of a cli method
|
||||
func before() error {
|
||||
fmt.Println(r.Blue.Bold(name) + " - " + r.Blue.Bold(version))
|
||||
fmt.Println(r.Blue.Regular(description) + "\n")
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
return handle(errors.New("$GOPATH isn't set up properly"))
|
||||
|
@ -103,59 +103,49 @@ func handle(err error) error {
|
|||
|
||||
// Cli commands
|
||||
func main() {
|
||||
c := &cli.App{
|
||||
app := &cli.App{
|
||||
Name: r.Name,
|
||||
Version: r.Version,
|
||||
Authors: []*cli.Author{
|
||||
{
|
||||
Name: "Alessio Pracchia",
|
||||
Email: "pracchia@hastegit",
|
||||
Email: "pracchia@hastega.it",
|
||||
},
|
||||
{
|
||||
Name: "Daniele Conventi",
|
||||
Email: "conventi@hastegit",
|
||||
Email: "conventi@hastega.it",
|
||||
},
|
||||
},
|
||||
Usage: r.Description,
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "run",
|
||||
Usage: "Build and watch file changes. Can be used even with a single project or without the config file",
|
||||
Name: "run",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Run a toolchain on a project or a list of projects. If not exist a config file it creates a new one.",
|
||||
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"},
|
||||
&cli.BoolFlag{Name: "no-run", Usage: "Disables the run"},
|
||||
&cli.BoolFlag{Name: "no-bin", Usage: "Disables the installation"},
|
||||
&cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"},
|
||||
&cli.BoolFlag{Name: "no-server", Usage: "Disables the web panel"},
|
||||
&cli.BoolFlag{Name: "no-config", Value: false, Usage: "Uses the config settings"},
|
||||
&cli.BoolFlag{Name: "open", Usage: "Automatically opens the web panel"},
|
||||
&cli.IntFlag{Name: "port", Usage: "Sets the web panel port"},
|
||||
&cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"},
|
||||
&cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path."},
|
||||
&cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test."},
|
||||
&cli.BoolFlag{Name: "generate", Aliases: []string{"g"}, Value: false, Usage: "Enable go generate."},
|
||||
&cli.BoolFlag{Name: "build", Aliases: []string{"b"}, Value: false, Usage: "Enable go build."},
|
||||
&cli.BoolFlag{Name: "legacy", Aliases: []string{"l"}, Value: false, Usage: "Watch by polling instead of Watch by fsnotify."},
|
||||
&cli.BoolFlag{Name: "server", Aliases: []string{"s"}, Value: false, Usage: "Enable server and open into the default browser."},
|
||||
&cli.BoolFlag{Name: "no-run", Aliases: []string{"nr"}, Value: false, Usage: "Disable go run"},
|
||||
&cli.BoolFlag{Name: "no-install", Aliases: []string{"ni"}, Value: false, Usage: "Disable go install"},
|
||||
&cli.BoolFlag{Name: "no-config", Aliases: []string{"nc"}, Value: false, Usage: "Ignore existing configurations."},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
if p.Bool("no-config") {
|
||||
r.Settings = c.Settings{
|
||||
Config: c.Config{
|
||||
Flimit: 0,
|
||||
},
|
||||
Resources: c.Resources{
|
||||
Config: config,
|
||||
Streams: streams,
|
||||
Logs: logs,
|
||||
Errors: errs,
|
||||
},
|
||||
Server: c.Server{
|
||||
Enabled: server,
|
||||
Open: open,
|
||||
Host: host,
|
||||
Port: port,
|
||||
},
|
||||
if p.Bool("legacy") {
|
||||
r.Config.Legacy = c.Legacy{
|
||||
Status: p.Bool("legacy"),
|
||||
Interval: interval,
|
||||
}
|
||||
r.Blueprint.Projects = r.Blueprint.Projects[:0]
|
||||
r.Blueprint.Add(p)
|
||||
} else if len(r.Blueprint.Projects) <= 0 {
|
||||
r.Blueprint.Add(p)
|
||||
}
|
||||
if p.Bool("no-config") || len(r.Blueprint.Projects) <= 0 {
|
||||
if p.Bool("no-config") {
|
||||
r.Config.Create = false
|
||||
}
|
||||
r.Blueprint.Projects = []w.Project{}
|
||||
handle(r.Blueprint.Add(p))
|
||||
}
|
||||
handle(r.Server.Start(p))
|
||||
handle(r.Blueprint.Run())
|
||||
|
@ -170,20 +160,717 @@ func main() {
|
|||
Name: "add",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Add another project",
|
||||
Usage: "Add a project to an existing config file or create a new one.",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.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"},
|
||||
&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: "Enables the tests"},
|
||||
&cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path."},
|
||||
&cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test."},
|
||||
&cli.BoolFlag{Name: "generate", Aliases: []string{"g"}, Value: false, Usage: "Enable go generate."},
|
||||
&cli.BoolFlag{Name: "build", Aliases: []string{"b"}, Value: false, Usage: "Enable go build."},
|
||||
&cli.BoolFlag{Name: "legacy", Aliases: []string{"l"}, Value: false, Usage: "Watch by polling instead of Watch by fsnotify."},
|
||||
&cli.BoolFlag{Name: "server", Aliases: []string{"s"}, Value: false, Usage: "Enable server and open into the default browser."},
|
||||
&cli.BoolFlag{Name: "no-run", Aliases: []string{"nr"}, Value: false, Usage: "Disable go run"},
|
||||
&cli.BoolFlag{Name: "no-fmt", Aliases: []string{"nf"}, Value: false, Usage: "Disable go fmt."},
|
||||
&cli.BoolFlag{Name: "no-install", Aliases: []string{"ni"}, Value: false, Usage: "Disable go install"},
|
||||
&cli.BoolFlag{Name: "no-config", Aliases: []string{"nc"}, Value: false, Usage: "Ignore existing configurations."},
|
||||
},
|
||||
Action: func(p *cli.Context) (err error) {
|
||||
handle(r.Blueprint.Insert(p))
|
||||
fmt.Println(p.String("path"))
|
||||
handle(r.Blueprint.Add(p))
|
||||
handle(r.Record(r))
|
||||
fmt.Println(r.Green.Bold("Your project was successfully added"))
|
||||
fmt.Println(r.Yellow.Bold("[")+"REALIZE"+r.Yellow.Bold("]"), r.Green.Bold("Your project was successfully added."))
|
||||
return nil
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
return before()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "init",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Define a new config file with all options step by step",
|
||||
Action: func(p *cli.Context) (err error) {
|
||||
i.Run(&i.Interact{
|
||||
Before: func(context i.Context) error {
|
||||
context.SetErr(r.Red.Bold("INVALID INPUT"))
|
||||
context.SetPrfx(color.Output, r.Yellow.Bold("[")+"REALIZE"+r.Yellow.Bold("]"))
|
||||
return nil
|
||||
},
|
||||
Questions: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
if _, err := os.Stat(".realize/" + config); err != nil {
|
||||
d.Skip()
|
||||
}
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Would you want to overwrite the existing " + r.Colors.Magenta.Bold("Realize") + " config?",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
} else if val {
|
||||
r.Settings = c.Settings{
|
||||
Config: c.Config{
|
||||
Create: true,
|
||||
},
|
||||
Resources: c.Resources{
|
||||
Config: config,
|
||||
Outputs: outputs,
|
||||
Logs: logs,
|
||||
Errors: errs,
|
||||
},
|
||||
Server: c.Server{
|
||||
Status: false,
|
||||
Open: false,
|
||||
Host: host,
|
||||
Port: port,
|
||||
},
|
||||
}
|
||||
r.Blueprint.Projects = r.Blueprint.Projects[len(r.Blueprint.Projects):]
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Would you want to customize the " + r.Colors.Magenta.Bold("settings") + "?",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(0, r.Green.Regular("(os default)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[int]"),
|
||||
Msg: "Max number of open files (root required)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Int()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Config.Flimit = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable legacy watch by polling",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(1, r.Green.Regular("(1s)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[seconds]"),
|
||||
Msg: "Set polling interval in seconds",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Int()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Config.Legacy.Interval = time.Duration(val * 1000000000)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Config.Legacy.Status = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable web server",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(5001, r.Green.Regular("(5001)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[int]"),
|
||||
Msg: "Server port",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Int()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Server.Port = int(val)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef("localhost", r.Green.Regular("(localhost)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Server host",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Server.Host = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Open in the current browser",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Server.Open = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Server.Status = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(true, r.Green.Regular("(y)"))
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Would you want to " + r.Colors.Magenta.Regular("add a new project") + "? (insert '!' to stop)",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
if val {
|
||||
r.Blueprint.Add(p)
|
||||
}
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(r.Settings.Wdir(), r.Green.Regular("("+r.Settings.Wdir()+")"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Project name",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Name = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
dir, _ := os.Getwd()
|
||||
d.SetDef(dir, r.Green.Regular("("+dir+")"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Project path",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Path = r.Settings.Path(val)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(true, r.Green.Regular("(y)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go fmt",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Fmt = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go test",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Test = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go generate",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Generate = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(true, r.Green.Regular("(y)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go install",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Bin = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go build",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Build = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(true, r.Green.Regular("(y)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable go run",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Run = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Customize the watched paths",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
if val {
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Paths = r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Paths[:len(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Paths)-1]
|
||||
}
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Insert a path to watch (insert '!' to stop)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Paths = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Paths, val)
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Customize the ignored paths",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
if val {
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Ignore = r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Ignore[:len(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Ignore)-1]
|
||||
}
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Insert a path to ignore (insert '!' to stop)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Ignore = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Ignore, val)
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Add additionals arguments",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Insert an argument (insert '!' to stop)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Params = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Params, val)
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Add 'before' custom commands",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Insert a command (insert '!' to stop)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
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, w.Command{Type: "before", Command: val})
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Add 'after' custom commands",
|
||||
Resolve: func(d i.Context) bool {
|
||||
val, _ := d.Ans().Bool()
|
||||
return val
|
||||
},
|
||||
},
|
||||
Subs: []*i.Question{
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetEnd("!")
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[string]"),
|
||||
Msg: "Insert a command (insert '!' to stop)",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().String()
|
||||
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, w.Command{Type: "after", Command: val})
|
||||
d.Reload()
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
_, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable watcher files preview",
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
val, err := d.Ans().Bool()
|
||||
if err != nil {
|
||||
return d.Err()
|
||||
}
|
||||
r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Watcher.Preview = val
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Before: func(d i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file output history",
|
||||
},
|
||||
Action: func(d i.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 i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file logs history",
|
||||
},
|
||||
Action: func(d i.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 i.Context) error {
|
||||
d.SetDef(false, r.Green.Regular("(n)"))
|
||||
return nil
|
||||
},
|
||||
Quest: i.Quest{
|
||||
Options: r.Yellow.Regular("[y/n]"),
|
||||
Msg: "Enable file errors history",
|
||||
},
|
||||
Action: func(d i.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
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(d i.Context) interface{} {
|
||||
if val, err := d.Ans().Bool(); err != nil {
|
||||
return d.Err()
|
||||
} else if val {
|
||||
d.Reload()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
After: func(d i.Context) error {
|
||||
if val, _ := d.Qns().Get(0).Ans().Bool(); val {
|
||||
err = r.Settings.Remove()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
handle(r.Record(r))
|
||||
fmt.Println(r.Yellow.Bold("[")+"REALIZE"+r.Yellow.Bold("]"), r.Green.Bold("Your configuration was successful."))
|
||||
return nil
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
|
@ -194,14 +881,14 @@ func main() {
|
|||
Name: "remove",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Remove a project",
|
||||
Usage: "Remove a project from a realize configuration.",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""},
|
||||
},
|
||||
Action: func(p *cli.Context) error {
|
||||
handle(r.Blueprint.Remove(p))
|
||||
handle(r.Record(r))
|
||||
fmt.Println(r.Green.Bold("Your project was successfully removed."))
|
||||
fmt.Println(r.Yellow.Bold("[")+"REALIZE"+r.Yellow.Bold("]"), r.Green.Bold("Your project was successfully removed."))
|
||||
return nil
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
|
@ -212,7 +899,7 @@ func main() {
|
|||
Name: "list",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"l"},
|
||||
Usage: "Projects list",
|
||||
Usage: "Print projects list.",
|
||||
Action: func(p *cli.Context) error {
|
||||
return handle(r.Blueprint.List())
|
||||
},
|
||||
|
@ -220,7 +907,21 @@ func main() {
|
|||
return before()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "clean",
|
||||
Category: "Configuration",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Remove realize folder.",
|
||||
Action: func(p *cli.Context) error {
|
||||
handle(r.Settings.Remove())
|
||||
fmt.Println(r.Yellow.Bold("[")+"REALIZE"+r.Yellow.Bold("]"), r.Green.Bold("Realize folder successfully removed."))
|
||||
return nil
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
return before()
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.Run(os.Args)
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -48,12 +48,11 @@ func render(c echo.Context, path string, mime int) error {
|
|||
|
||||
// Start the web server
|
||||
func (s *Server) Start(p *cli.Context) (err error) {
|
||||
if p.Int("port") != 0 {
|
||||
s.Settings.Server.Port = p.Int("port")
|
||||
}
|
||||
if !p.Bool("no-server") && s.Enabled {
|
||||
if s.Server.Status || p.Bool("server") {
|
||||
e := echo.New()
|
||||
e.Use(middleware.Gzip())
|
||||
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
|
||||
Level: 2,
|
||||
}))
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
// web panel
|
||||
|
@ -95,8 +94,6 @@ func (s *Server) Start(p *cli.Context) (err error) {
|
|||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.Server.Enabled = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import "syscall"
|
|||
// Flimit defines the max number of watched files
|
||||
func (s *Settings) Flimit() {
|
||||
var rLimit syscall.Rlimit
|
||||
rLimit.Max = s.Config.Flimit
|
||||
rLimit.Cur = s.Config.Flimit
|
||||
rLimit.Max = uint64(s.Config.Flimit)
|
||||
rLimit.Cur = uint64(s.Config.Flimit)
|
||||
err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
|
||||
if err != nil {
|
||||
s.Fatal(err, "Error setting rlimit")
|
||||
|
|
|
@ -3,33 +3,42 @@ package settings
|
|||
import (
|
||||
"gopkg.in/yaml.v2"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Settings defines a group of general settings
|
||||
type Settings struct {
|
||||
Colors `yaml:"-"`
|
||||
Config `yaml:",inline" json:"config"`
|
||||
Resources `yaml:"resources" json:"resources"`
|
||||
Server `yaml:"server" json:"server"`
|
||||
Config `yaml:"config" json:"config"`
|
||||
Server `yaml:"server,omitempty" json:"server,omitempty"`
|
||||
}
|
||||
|
||||
// Config defines structural options
|
||||
type Config struct {
|
||||
Flimit uint64 `yaml:"flimit" json:"flimit"`
|
||||
Create bool `yaml:"-" json:"-"`
|
||||
Flimit int64 `yaml:"flimit,omitempty" json:"flimit,omitempty"`
|
||||
Legacy `yaml:"legacy,omitempty" json:"legacy,omitempty"`
|
||||
}
|
||||
|
||||
// Legacy configuration
|
||||
type Legacy struct {
|
||||
Status bool `yaml:"status" json:"status"`
|
||||
Interval time.Duration `yaml:"interval" json:"interval"`
|
||||
}
|
||||
|
||||
// Server settings, used for the web panel
|
||||
type Server struct {
|
||||
Enabled bool `yaml:"enable" json:"enable"`
|
||||
Open bool `yaml:"open" json:"open"`
|
||||
Host string `yaml:"host" json:"host"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
Status bool `yaml:"status" json:"status"`
|
||||
Open bool `yaml:"open" json:"open"`
|
||||
Host string `yaml:"host" json:"host"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
}
|
||||
|
||||
// Resources defines the files generated by realize
|
||||
type Resources struct {
|
||||
Config string `yaml:"-" json:"-"`
|
||||
Streams string `yaml:"streams" json:"output"`
|
||||
Outputs string `yaml:"outputs" json:"outputs"`
|
||||
Logs string `yaml:"logs" json:"log"`
|
||||
Errors string `yaml:"errors" json:"error"`
|
||||
}
|
||||
|
@ -50,14 +59,25 @@ func (s *Settings) Read(out interface{}) error {
|
|||
|
||||
// Record create and unmarshal the yaml config file
|
||||
func (s *Settings) Record(out interface{}) error {
|
||||
y, err := yaml.Marshal(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(".realize/"); os.IsNotExist(err) {
|
||||
if err = os.Mkdir(".realize/", 0770); err != nil {
|
||||
return s.Write(s.Resources.Config, y)
|
||||
if s.Config.Create {
|
||||
y, err := yaml.Marshal(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(".realize/"); os.IsNotExist(err) {
|
||||
if err = os.Mkdir(".realize/", 0770); err != nil {
|
||||
return s.Write(s.Resources.Config, y)
|
||||
}
|
||||
}
|
||||
return s.Write(".realize/"+s.Resources.Config, y)
|
||||
}
|
||||
return s.Write(".realize/"+s.Resources.Config, y)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove realize folder
|
||||
func (s *Settings) Remove() error {
|
||||
if _, err := os.Stat(".realize/"); !os.IsNotExist(err) {
|
||||
return os.RemoveAll(".realize/")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Wdir return the current working directory
|
||||
|
@ -23,8 +24,24 @@ func (s Settings) Validate(err error) error {
|
|||
|
||||
// Fatal prints a fatal error with its additional messages
|
||||
func (s Settings) Fatal(err error, msg ...interface{}) {
|
||||
if len(msg) > 0 {
|
||||
if len(msg) > 0 && err != nil {
|
||||
log.Fatalln(s.Red.Regular(msg...), err.Error())
|
||||
} else if err != nil {
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Path cleaner
|
||||
func (s Settings) Path(path string) string {
|
||||
return strings.Replace(filepath.Clean(path), "\\", "/", -1)
|
||||
}
|
||||
|
|
119
watcher/cmd.go
119
watcher/cmd.go
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/urfave/cli.v2"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -16,7 +15,12 @@ func (h *Blueprint) Run() error {
|
|||
wg.Add(len(h.Projects))
|
||||
for k := range h.Projects {
|
||||
h.Projects[k].parent = h
|
||||
go h.Projects[k].watching()
|
||||
h.Projects[k].path = h.Projects[k].Path
|
||||
if h.Legacy.Status {
|
||||
go h.Projects[k].watchByPolling()
|
||||
} else {
|
||||
go h.Projects[k].watchByNotify()
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
|
@ -27,27 +31,27 @@ func (h *Blueprint) Run() error {
|
|||
// Add a new project
|
||||
func (h *Blueprint) Add(p *cli.Context) error {
|
||||
project := Project{
|
||||
Name: h.name(p),
|
||||
Path: filepath.Clean(p.String("path")),
|
||||
Build: p.Bool("build"),
|
||||
Bin: !p.Bool("no-bin"),
|
||||
Run: !p.Bool("no-run"),
|
||||
Fmt: !p.Bool("no-fmt"),
|
||||
Test: p.Bool("test"),
|
||||
Params: argsParam(p),
|
||||
Name: h.Name(p.String("name"), p.String("path")),
|
||||
Path: h.Path(p.String("path")),
|
||||
Fmt: !p.Bool("no-fmt"),
|
||||
Generate: p.Bool("generate"),
|
||||
Test: p.Bool("test"),
|
||||
Build: p.Bool("build"),
|
||||
Bin: !p.Bool("no-bin"),
|
||||
Run: !p.Bool("no-run"),
|
||||
Params: argsParam(p),
|
||||
Watcher: Watcher{
|
||||
Paths: []string{"/"},
|
||||
Ignore: []string{"vendor"},
|
||||
Exts: []string{".go"},
|
||||
Preview: false,
|
||||
Preview: p.Bool("preview"),
|
||||
Scripts: []Command{},
|
||||
},
|
||||
Cli: Cli{
|
||||
Streams: true,
|
||||
},
|
||||
File: File{
|
||||
Streams: false,
|
||||
Logs: false,
|
||||
Errors: false,
|
||||
Streams: Streams{
|
||||
CliOut: true,
|
||||
FileOut: false,
|
||||
FileLog: false,
|
||||
FileErr: false,
|
||||
},
|
||||
}
|
||||
if _, err := duplicates(project, h.Projects); err != nil {
|
||||
|
@ -68,12 +72,6 @@ func (h *Blueprint) Clean() {
|
|||
}
|
||||
}
|
||||
|
||||
// Insert a new project in projects list
|
||||
func (h *Blueprint) Insert(p *cli.Context) error {
|
||||
err := h.Add(p)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove a project
|
||||
func (h *Blueprint) Remove(p *cli.Context) error {
|
||||
for key, val := range h.Projects {
|
||||
|
@ -90,39 +88,49 @@ func (h *Blueprint) List() error {
|
|||
err := h.check()
|
||||
if err == nil {
|
||||
for _, val := range h.Projects {
|
||||
fmt.Println(h.Blue.Bold("|"), h.Blue.Bold(strings.ToUpper(val.Name)))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Base Path"), ":", h.Magenta.Regular(val.Path))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Fmt"), ":", h.Magenta.Regular(val.Fmt))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Test"), ":", h.Magenta.Regular(val.Test))
|
||||
fmt.Println(h.Blue.Bold("[") + strings.ToUpper(val.Name) + h.Blue.Bold("]"))
|
||||
name := h.Magenta.Bold("[") + strings.ToUpper(val.Name) + h.Magenta.Bold("]")
|
||||
|
||||
fmt.Println(name, h.Yellow.Regular("Base Path"), ":", h.Magenta.Regular(val.Path))
|
||||
fmt.Println(name, h.Yellow.Regular("Fmt"), ":", h.Magenta.Regular(val.Fmt))
|
||||
fmt.Println(name, h.Yellow.Regular("Generate"), ":", h.Magenta.Regular(val.Generate))
|
||||
fmt.Println(name, h.Yellow.Regular("Test"), ":", h.Magenta.Regular(val.Test))
|
||||
fmt.Println(name, h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin))
|
||||
fmt.Println(name, h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build))
|
||||
fmt.Println(name, h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run))
|
||||
if len(val.Params) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Params"), ":", h.Magenta.Regular(val.Params))
|
||||
}
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Watcher"), ":")
|
||||
if len(val.Watcher.After) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("After"), ":", h.Magenta.Regular(val.Watcher.After))
|
||||
}
|
||||
if len(val.Watcher.Before) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Before"), ":", h.Magenta.Regular(val.Watcher.Before))
|
||||
fmt.Println(name, h.Yellow.Regular("Params"), ":", h.Magenta.Regular(val.Params))
|
||||
}
|
||||
fmt.Println(name, h.Yellow.Regular("Watcher"), ":")
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Preview"), ":", h.Magenta.Regular(val.Watcher.Preview))
|
||||
if len(val.Watcher.Exts) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Extensions"), ":", h.Magenta.Regular(val.Watcher.Exts))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Extensions"), ":", h.Magenta.Regular(val.Watcher.Exts))
|
||||
}
|
||||
if len(val.Watcher.Paths) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Paths"), ":", h.Magenta.Regular(val.Watcher.Paths))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Paths"), ":", h.Magenta.Regular(val.Watcher.Paths))
|
||||
}
|
||||
if len(val.Watcher.Ignore) > 0 {
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Ignored paths"), ":", h.Magenta.Regular(val.Watcher.Ignore))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Ignored paths"), ":", h.Magenta.Regular(val.Watcher.Ignore))
|
||||
}
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Files preview"), ":", h.Magenta.Regular(val.Watcher.Preview))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Cli"), ":")
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Streams"), ":", h.Magenta.Regular(val.Cli.Streams))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("File"), ":")
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Streams"), ":", h.Magenta.Regular(val.File.Streams))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Logs"), ":", h.Magenta.Regular(val.File.Logs))
|
||||
fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Errors"), ":", h.Magenta.Regular(val.File.Errors))
|
||||
if len(val.Watcher.Scripts) > 0 {
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Scripts"), ":")
|
||||
for _, v := range val.Watcher.Scripts {
|
||||
if v.Command != "" {
|
||||
fmt.Println(name, "\t\t", h.Magenta.Regular("-"), h.Yellow.Regular("Command"), ":", h.Magenta.Regular(v.Command))
|
||||
if v.Path != "" {
|
||||
fmt.Println(name, "\t\t", h.Yellow.Regular("Path"), ":", h.Magenta.Regular(v.Path))
|
||||
}
|
||||
if v.Type != "" {
|
||||
fmt.Println(name, "\t\t", h.Yellow.Regular("Type"), ":", h.Magenta.Regular(v.Type))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(name, h.Yellow.Regular("Streams"), ":")
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("Cli Out"), ":", h.Magenta.Regular(val.Streams.CliOut))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("File Out"), ":", h.Magenta.Regular(val.Streams.FileOut))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("File Log"), ":", h.Magenta.Regular(val.Streams.FileLog))
|
||||
fmt.Println(name, "\t", h.Yellow.Regular("File Err"), ":", h.Magenta.Regular(val.Streams.FileErr))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -137,16 +145,3 @@ func (h *Blueprint) check() error {
|
|||
}
|
||||
return errors.New("There are no projects. The config file is empty.")
|
||||
}
|
||||
|
||||
// NameParam check the project name presence. If empty takes the working directory name
|
||||
func (h *Blueprint) name(p *cli.Context) string {
|
||||
var name string
|
||||
if p.String("name") == "" && p.String("path") == "" {
|
||||
return h.Wdir()
|
||||
} else if p.String("path") != "/" {
|
||||
name = filepath.Base(p.String("path"))
|
||||
} else {
|
||||
name = p.String("name")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup)
|
|||
} else {
|
||||
if _, err := os.Stat(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))); err == nil {
|
||||
build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)), params...)
|
||||
} else if _, err := os.Stat(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)) + ".exe"); err == nil {
|
||||
build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))+".exe", params...)
|
||||
} else {
|
||||
p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Can't run a not compiled project"})
|
||||
p.Fatal(err, "Can't run a not compiled project", ":")
|
||||
|
@ -139,14 +141,21 @@ func (p *Project) goTools(dir string, name string, cmd ...string) (string, error
|
|||
return "", nil
|
||||
}
|
||||
|
||||
// Cmds exec a list of defined commands
|
||||
func (p *Project) afterBefore(command string) (errors string, logs string) {
|
||||
// Exec an additional command from a defined path if specified
|
||||
func (p *Project) command(cmd Command) (errors string, logs string) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
command = strings.Replace(strings.Replace(command, "'", "", -1), "\"", "", -1)
|
||||
command := strings.Replace(strings.Replace(cmd.Command, "'", "", -1), "\"", "", -1)
|
||||
c := strings.Split(command, " ")
|
||||
build := exec.Command(c[0], c[1:]...)
|
||||
build.Dir = p.base
|
||||
if cmd.Path != "" {
|
||||
if strings.Contains(cmd.Path, p.base) {
|
||||
build.Dir = cmd.Path
|
||||
} else {
|
||||
build.Dir = filepath.Join(p.base, cmd.Path)
|
||||
}
|
||||
}
|
||||
build.Stdout = &stdout
|
||||
build.Stderr = &stderr
|
||||
err := build.Run()
|
||||
|
|
|
@ -9,6 +9,16 @@ import (
|
|||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Watcher interface used by polling/fsnotify watching
|
||||
type watcher interface {
|
||||
Add(path string) error
|
||||
}
|
||||
|
||||
// Polling watcher
|
||||
type pollWatcher struct {
|
||||
paths map[string]bool
|
||||
}
|
||||
|
||||
// Log struct
|
||||
type logWriter struct {
|
||||
c.Colors
|
||||
|
@ -29,15 +39,14 @@ type Project struct {
|
|||
Name string `yaml:"name" json:"name"`
|
||||
Path string `yaml:"path" json:"path"`
|
||||
Fmt bool `yaml:"fmt" json:"fmt"`
|
||||
Test bool `yaml:"test" json:"test"`
|
||||
Generate bool `yaml:"generate" json:"generate"`
|
||||
Test bool `yaml:"test" json:"test"`
|
||||
Bin bool `yaml:"bin" json:"bin"`
|
||||
Build bool `yaml:"build" json:"build"`
|
||||
Run bool `yaml:"run" json:"run"`
|
||||
Params []string `yaml:"params" json:"params"`
|
||||
Params []string `yaml:"params,omitempty" json:"params,omitempty"`
|
||||
Watcher Watcher `yaml:"watcher" json:"watcher"`
|
||||
Cli Cli `yaml:"cli" json:"cli"`
|
||||
File File `yaml:"file" json:"file"`
|
||||
Streams Streams `yaml:"streams" json:"streams"`
|
||||
Buffer Buffer `yaml:"-" json:"buffer"`
|
||||
parent *Blueprint
|
||||
path string
|
||||
|
@ -45,25 +54,26 @@ type Project struct {
|
|||
|
||||
// Watcher struct defines the livereload's logic
|
||||
type Watcher struct {
|
||||
// different before and after on re-run?
|
||||
Before []string `yaml:"before" json:"before"`
|
||||
After []string `yaml:"after" json:"after"`
|
||||
Paths []string `yaml:"paths" json:"paths"`
|
||||
Ignore []string `yaml:"ignore_paths" json:"ignore"`
|
||||
Exts []string `yaml:"exts" json:"exts"`
|
||||
Preview bool `yaml:"preview" json:"preview"`
|
||||
Preview bool `yaml:"preview" json:"preview"`
|
||||
Paths []string `yaml:"paths" json:"paths"`
|
||||
Ignore []string `yaml:"ignore_paths" json:"ignore"`
|
||||
Exts []string `yaml:"exts" json:"exts"`
|
||||
Scripts []Command `yaml:"scripts,omitempty" json:"scripts,omitempty"`
|
||||
}
|
||||
|
||||
// Cli output status, enables or disables
|
||||
type Cli struct {
|
||||
Streams bool `yaml:"streams" json:"streams"`
|
||||
// Command options
|
||||
type Command struct {
|
||||
Type string `yaml:"type" json:"type"`
|
||||
Command string `yaml:"command" json:"command"`
|
||||
Path string `yaml:"path" json:"path"`
|
||||
}
|
||||
|
||||
// File determinates the status of each log files (streams, logs, errors)
|
||||
type File struct {
|
||||
Streams bool `yaml:"streams" json:"streams"`
|
||||
Logs bool `yaml:"logs" json:"logs"`
|
||||
Errors bool `yaml:"errors" json:"errors"`
|
||||
// Streams is a collection of names and values for the logs functionality
|
||||
type Streams struct {
|
||||
CliOut bool `yaml:"cli_out" json:"cli_out"`
|
||||
FileOut bool `yaml:"file_out" json:"file_out"`
|
||||
FileLog bool `yaml:"file_log" json:"file_log"`
|
||||
FileErr bool `yaml:"file_err" json:"file_err"`
|
||||
}
|
||||
|
||||
// Buffer define an array buffer for each log files
|
||||
|
|
|
@ -23,8 +23,8 @@ func argsParam(params *cli.Context) []string {
|
|||
// 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!")
|
||||
if value.Path == val.Path {
|
||||
return val, errors.New("There is already a project for '" + val.Path + "'. Check your config file!")
|
||||
}
|
||||
}
|
||||
return Project{}, nil
|
||||
|
|
|
@ -16,28 +16,113 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Watching method is the main core. It manages the livereload and the watching
|
||||
func (p *Project) watching() {
|
||||
var msg string
|
||||
var out BufferOut
|
||||
|
||||
func (w *pollWatcher) Add(path string) error {
|
||||
if w.paths == nil {
|
||||
w.paths = map[string]bool{}
|
||||
}
|
||||
w.paths[path] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *pollWatcher) isWatching(path string) bool {
|
||||
a, b := w.paths[path]
|
||||
return a && b
|
||||
}
|
||||
|
||||
// Watch the project by polling
|
||||
func (p *Project) watchByPolling() {
|
||||
var wr sync.WaitGroup
|
||||
var watcher *fsnotify.Watcher
|
||||
channel, exit := make(chan bool, 1), make(chan bool, 1)
|
||||
p.path = p.Path
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
var watcher = new(pollWatcher)
|
||||
channel, exit := make(chan bool, 1), make(chan os.Signal, 2)
|
||||
signal.Notify(exit, os.Interrupt, syscall.SIGTERM)
|
||||
defer func() {
|
||||
p.cmd("after")
|
||||
wg.Done()
|
||||
}()
|
||||
if err != nil {
|
||||
log.Fatalln(p.pname(p.Name, 2), ":", p.Red.Bold(err.Error()))
|
||||
return
|
||||
}
|
||||
p.cmd(exit)
|
||||
if p.walks(watcher) != nil {
|
||||
log.Fatalln(p.pname(p.Name, 2), ":", p.Red.Bold(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
p.cmd("before")
|
||||
p.Fatal(p.watch(watcher))
|
||||
go p.routines(channel, &wr)
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
walk := func(changed string, info os.FileInfo, err error) error {
|
||||
var ext string
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !watcher.isWatching(changed) {
|
||||
return nil
|
||||
} else if !info.ModTime().Truncate(time.Second).After(p.LastChangedOn) {
|
||||
return nil
|
||||
}
|
||||
if index := strings.Index(filepath.Ext(changed), "_"); index == -1 {
|
||||
ext = filepath.Ext(changed)
|
||||
} else {
|
||||
ext = filepath.Ext(changed)[0:index]
|
||||
}
|
||||
i := strings.Index(changed, filepath.Ext(changed))
|
||||
file := changed[:i] + ext
|
||||
path := filepath.Dir(changed[:i])
|
||||
if changed[:i] != "" && inArray(ext, p.Watcher.Exts) {
|
||||
if p.Run {
|
||||
close(channel)
|
||||
channel = make(chan bool)
|
||||
}
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
// repeat the initial cycle
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file))
|
||||
out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file}
|
||||
p.print("log", out, msg, "")
|
||||
|
||||
p.cmd("change")
|
||||
p.fmt(file)
|
||||
p.test(path)
|
||||
p.generate(path)
|
||||
go p.routines(channel, &wr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
for _, dir := range p.Watcher.Paths {
|
||||
base := filepath.Join(p.base, dir)
|
||||
if _, err := os.Stat(base); err == nil {
|
||||
if err := filepath.Walk(base, walk); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error()}
|
||||
p.print("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, "")
|
||||
}
|
||||
select {
|
||||
case <-exit:
|
||||
return
|
||||
case <-time.After(p.parent.Legacy.Interval / time.Duration(len(p.Watcher.Paths))):
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Watch the project by fsnotify
|
||||
func (p *Project) watchByNotify() {
|
||||
var wr sync.WaitGroup
|
||||
var watcher *fsnotify.Watcher
|
||||
channel, exit := make(chan bool, 1), make(chan os.Signal, 2)
|
||||
signal.Notify(exit, os.Interrupt, syscall.SIGTERM)
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
p.Fatal(err)
|
||||
defer func() {
|
||||
p.cmd("after")
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
p.cmd("before")
|
||||
p.Fatal(p.watch(watcher))
|
||||
go p.routines(channel, &wr)
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
// waiting for an event
|
||||
for {
|
||||
select {
|
||||
case event := <-watcher.Events:
|
||||
|
@ -56,176 +141,36 @@ func (p *Project) watching() {
|
|||
file := event.Name[:i] + ext
|
||||
path := filepath.Dir(event.Name[:i])
|
||||
if event.Name[:i] != "" && inArray(ext, p.Watcher.Exts) {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file))
|
||||
out := BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file}
|
||||
p.print("log", out, msg, "")
|
||||
// stop and run again
|
||||
if p.Run {
|
||||
close(channel)
|
||||
channel = make(chan bool)
|
||||
}
|
||||
// handle multiple errors, need a better way
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
// repeat the initial cycle
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file))
|
||||
out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file}
|
||||
p.print("log", out, msg, "")
|
||||
|
||||
p.cmd("change")
|
||||
p.fmt(file)
|
||||
p.test(path)
|
||||
p.generate(path)
|
||||
go p.routines(channel, &wr)
|
||||
p.LastChangedOn = time.Now().Truncate(time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
log.Println(p.Red.Bold(err.Error()))
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error()}
|
||||
p.print("error", out, msg, "")
|
||||
case <-exit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Install calls an implementation of "go install"
|
||||
func (p *Project) install() error {
|
||||
if p.Bin {
|
||||
start := time.Now()
|
||||
log.Println(p.pname(p.Name, 1), ":", "Installing..")
|
||||
stream, err := p.goInstall()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Install"), p.Red.Regular(err.Error()))
|
||||
out := BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Install", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
} else {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Installed")+" after", p.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)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Install calls an implementation of "go run"
|
||||
func (p *Project) run(channel chan bool, wr *sync.WaitGroup) {
|
||||
if p.Run {
|
||||
start := time.Now()
|
||||
runner := make(chan bool, 1)
|
||||
log.Println(p.pname(p.Name, 1), ":", "Running..")
|
||||
go p.goRun(channel, runner, wr)
|
||||
for {
|
||||
select {
|
||||
case <-runner:
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Has been run")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out := BufferOut{Time: time.Now(), Text: "Has been run after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build calls an implementation of the "go build"
|
||||
func (p *Project) build() error {
|
||||
if p.Build {
|
||||
start := time.Now()
|
||||
log.Println(p.pname(p.Name, 1), ":", "Building..")
|
||||
stream, err := p.goBuild()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Build"), p.Red.Regular(err.Error()))
|
||||
out := BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Build", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
} else {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Builded")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out := BufferOut{Time: time.Now(), Text: "Builded after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, stream)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fmt calls an implementation of the "go fmt"
|
||||
func (p *Project) fmt(path string) error {
|
||||
if p.Fmt && strings.HasSuffix(path, ".go") {
|
||||
if stream, err := p.goTools(p.base, "gofmt", "-s", "-w", "-e", path); err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Fmt"), p.Red.Regular("there are some errors in"), ":", p.Magenta.Bold(path))
|
||||
out := BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Fmt", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generate calls an implementation of the "go generate"
|
||||
func (p *Project) generate(path string) error {
|
||||
if p.Generate {
|
||||
if stream, err := p.goTools(path, "go", "generate"); err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Generate"), p.Red.Regular("there are some errors in"), ":", p.Magenta.Bold(path))
|
||||
out := BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Generate", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test calls an implementation of the "go test"
|
||||
func (p *Project) test(path string) error {
|
||||
if p.Test {
|
||||
if stream, err := p.goTools(path, "go", "test"); err != nil {
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Test"), p.Red.Regular("there are some errors in "), ":", p.Magenta.Bold(path))
|
||||
out := BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Test", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cmd calls an wrapper for execute the commands after/before
|
||||
func (p *Project) cmd(exit chan bool) {
|
||||
c := make(chan os.Signal, 2)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
cast := func(commands []string) {
|
||||
for _, command := range commands {
|
||||
errors, logs := p.afterBefore(command)
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Bold("Command"), p.Green.Bold("\"")+command+p.Green.Bold("\""))
|
||||
out := BufferOut{Time: time.Now(), Text: command, Type: "After/Before"}
|
||||
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: "After/Before"}
|
||||
p.print("log", out, "", msg)
|
||||
}
|
||||
if errors != "" {
|
||||
msg = fmt.Sprintln(p.Red.Regular(errors))
|
||||
out = BufferOut{Time: time.Now(), Text: errors, Type: "After/Before"}
|
||||
p.print("error", out, "", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(p.Watcher.Before) > 0 {
|
||||
cast(p.Watcher.Before)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
if len(p.Watcher.After) > 0 {
|
||||
cast(p.Watcher.After)
|
||||
}
|
||||
close(exit)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Walks the file tree of a project
|
||||
func (p *Project) walks(watcher *fsnotify.Watcher) error {
|
||||
// Watch the files tree of a project
|
||||
func (p *Project) watch(watcher watcher) error {
|
||||
var files, folders int64
|
||||
wd, _ := os.Getwd()
|
||||
walk := func(path string, info os.FileInfo, err error) error {
|
||||
|
@ -249,7 +194,6 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.path == "." || p.path == "/" {
|
||||
p.base = wd
|
||||
p.path = p.Wdir()
|
||||
|
@ -268,12 +212,137 @@ func (p *Project) walks(watcher *fsnotify.Watcher) error {
|
|||
return errors.New(base + " path doesn't exist")
|
||||
}
|
||||
}
|
||||
msg := fmt.Sprintln(p.pname(p.Name, 1), ":", p.Blue.Bold("Watching"), p.Magenta.Bold(files), "file/s", p.Magenta.Bold(folders), "folder/s")
|
||||
out := BufferOut{Time: time.Now(), Text: "Watching " + strconv.FormatInt(files, 10) + " files/s " + strconv.FormatInt(folders, 10) + " folder/s"}
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 1), ":", p.Blue.Bold("Watching"), p.Magenta.Bold(files), "file/s", p.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, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Install calls an implementation of "go install"
|
||||
func (p *Project) install() error {
|
||||
if p.Bin {
|
||||
start := time.Now()
|
||||
log.Println(p.pname(p.Name, 1), ":", "Installing..")
|
||||
stream, err := p.goInstall()
|
||||
if err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Install"), p.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Install", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
} else {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Installed")+" after", p.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)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Install calls an implementation of "go run"
|
||||
func (p *Project) run(channel chan bool, wr *sync.WaitGroup) {
|
||||
if p.Run {
|
||||
start := time.Now()
|
||||
runner := make(chan bool, 1)
|
||||
log.Println(p.pname(p.Name, 1), ":", "Running..")
|
||||
go p.goRun(channel, runner, wr)
|
||||
for {
|
||||
select {
|
||||
case <-runner:
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Has been run")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out = BufferOut{Time: time.Now(), Text: "Has been run after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build calls an implementation of the "go build"
|
||||
func (p *Project) build() error {
|
||||
if p.Build {
|
||||
start := time.Now()
|
||||
log.Println(p.pname(p.Name, 1), ":", "Building..")
|
||||
stream, err := p.goBuild()
|
||||
if err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Build"), p.Red.Regular(err.Error()))
|
||||
out = BufferOut{Time: time.Now(), Text: err.Error(), Type: "Go Build", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
} else {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Regular("Builded")+" after", p.Magenta.Regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
|
||||
out = BufferOut{Time: time.Now(), Text: "Builded after " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
|
||||
p.print("log", out, msg, stream)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fmt calls an implementation of the "go fmt"
|
||||
func (p *Project) fmt(path string) error {
|
||||
if p.Fmt && strings.HasSuffix(path, ".go") {
|
||||
if stream, err := p.goTools(p.base, "gofmt", "-s", "-w", "-e", path); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Fmt"), p.Red.Regular("there are some errors in"), ":", p.Magenta.Bold(path))
|
||||
out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Fmt", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generate calls an implementation of the "go generate"
|
||||
func (p *Project) generate(path string) error {
|
||||
if p.Generate {
|
||||
if stream, err := p.goTools(path, "go", "generate"); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Generate"), p.Red.Regular("there are some errors in"), ":", p.Magenta.Bold(path))
|
||||
out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Generate", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test calls an implementation of the "go test"
|
||||
func (p *Project) test(path string) error {
|
||||
if p.Test {
|
||||
if stream, err := p.goTools(path, "go", "test"); err != nil {
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", p.Red.Bold("Go Test"), p.Red.Regular("there are some errors in "), ":", p.Magenta.Bold(path))
|
||||
out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Test", Stream: stream}
|
||||
p.print("error", out, msg, stream)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cmd calls an wrapper for execute the commands after/before
|
||||
func (p *Project) cmd(flag string) {
|
||||
for _, cmd := range p.Watcher.Scripts {
|
||||
if strings.ToLower(cmd.Type) == flag {
|
||||
errors, logs := p.command(cmd)
|
||||
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Bold("Command"), p.Green.Bold("\"")+cmd.Command+p.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(p.Red.Regular(errors))
|
||||
out = BufferOut{Time: time.Now(), Text: errors, Type: flag}
|
||||
p.print("error", out, "", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore and validate a path
|
||||
func (p *Project) ignore(str string) bool {
|
||||
for _, v := range p.Watcher.Ignore {
|
||||
|
@ -322,20 +391,20 @@ func (p *Project) print(t string, o BufferOut, msg string, stream string) {
|
|||
switch t {
|
||||
case "out":
|
||||
p.Buffer.StdOut = append(p.Buffer.StdOut, o)
|
||||
if p.File.Streams {
|
||||
f := p.Create(p.base, p.parent.Resources.Streams)
|
||||
if p.Streams.FileOut {
|
||||
f := p.Create(p.base, p.parent.Resources.Outputs)
|
||||
t := time.Now()
|
||||
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 {
|
||||
p.Fatal(err, "")
|
||||
}
|
||||
}
|
||||
if msg != "" && p.Cli.Streams {
|
||||
if msg != "" && p.Streams.CliOut {
|
||||
log.Print(msg)
|
||||
}
|
||||
case "log":
|
||||
p.Buffer.StdLog = append(p.Buffer.StdLog, o)
|
||||
if p.File.Logs {
|
||||
if p.Streams.FileLog {
|
||||
f := p.Create(p.base, p.parent.Resources.Logs)
|
||||
t := time.Now()
|
||||
s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"}
|
||||
|
@ -351,7 +420,7 @@ func (p *Project) print(t string, o BufferOut, msg string, stream string) {
|
|||
}
|
||||
case "error":
|
||||
p.Buffer.StdErr = append(p.Buffer.StdErr, o)
|
||||
if p.File.Errors {
|
||||
if p.Streams.FileErr {
|
||||
f := p.Create(p.base, p.parent.Resources.Errors)
|
||||
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"}
|
||||
|
|
Loading…
Reference in New Issue