Skip to content

Commit

Permalink
feat: deprecated CMD and combine with RUN. close #21
Browse files Browse the repository at this point in the history
  • Loading branch information
axetroy committed Nov 24, 2019
1 parent 6c8e0b8 commit 4924a1e
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 52 deletions.
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ for more detail about command. print `s4 --help`
| COPY | Copy file at remote server. | `COPY data.db data.db.bak` |
| MOVE | Move file at remote server. | `MOVE data.bak data.db` |
| DELETE | Delete files at remote server. | `DELETE file1 file2` |
| RUN | Run command at remote server. | `RUN python ./remote/start.py` |
| CMD | Run command in local server. | `RUN ["npm", "run", "build"]` |
| RUN | Run command at local machine or remote server. | `RUN npm run build`<br/>`RUN ["npm", "run", "build"]` |
<details><summary>CONNECT</summary>
Expand Down Expand Up @@ -108,8 +107,7 @@ VAR GOPATH_LOCAL = $GOPATH:local
VAR GOPATH_REMOTE = $GOPATH:remote
CMD ["echo", "'local GOPATH {{GOPATH_LOCAL}}'"]
RUN echo "remote GOPATH: {{GOPATH_REMOTE}}"
RUN echo "remote GOPATH: {{GOPATH_REMOTE}}, local GOPATH: {{GOPATH_LOCAL}}"
```
### Set stdout from execute the command line
Expand All @@ -125,8 +123,7 @@ VAR NODE_VERSION_LOCAL <= ["node", "-v"]
VAR NODE_VERSION_REMOTE <= node -v
CMD ["echo", "'local version : {{NODE_VERSION_LOCAL}}'"]
RUN echo "remote version: {{NODE_VERSION_REMOTE}}"
RUN echo "remote version: {{NODE_VERSION_REMOTE}}, local version: {{NODE_VERSION_LOCAL}}"
```
```s4
Expand Down Expand Up @@ -199,28 +196,28 @@ eg `DELETE file1 file2`

<details><summary>RUN</summary>

Run command at remote server
Run command at local or remote server

#### Run at remote server

eg `RUN python ./remote/start.py`

It supports multi-line wrap

```s4
# run at remote
RUN npm version \
&& npm run build \
&& npm run test \
&& npm run publish
```

</details>

<details><summary>CMD</summary>

Run command in local
### Run at local machine

eg `RUN ["npm", "run", "build"]`

It supports multi-line wrap
```s4
# run at local machine
RUN ["npm", "run", "build"]
```

</details>

Expand Down
42 changes: 39 additions & 3 deletions core/grammar/tokenizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ type NodeCmd struct {
}

type NodeRun struct {
Command string
Commands []NodeRunCommand
SourceCode string
}

type NodeRunCommand struct {
Command []string
RunInLocal bool
SourceCode string
}

Expand Down Expand Up @@ -118,7 +124,7 @@ var (
validKeywordReg = regexp.MustCompile(strings.Join(Actions, "|"))
keywordRed = regexp.MustCompile("[A-Z]")
emptyStrReg = regexp.MustCompile("\\s")
lineWrapReg = regexp.MustCompile("\\\n")
lineWrapReg = regexp.MustCompile("\\\r?\\\n")
lineBreakChar = "\\"
spaceBlank = " "
)
Expand Down Expand Up @@ -240,6 +246,7 @@ func Tokenizer(input string) ([]Token, error) {

if lastChar == lineBreakChar {
currentIndex++
currentValue = strings.TrimRight(currentValue, "\\")
continue
}
}
Expand Down Expand Up @@ -380,10 +387,29 @@ func Tokenizer(input string) ([]Token, error) {
if valueLength < 1 {
return tokens, fmt.Errorf("`%s` accepts at least one parameter but got `%s`", keyword, valueStr)
}

commands := make([]NodeRunCommand, 0)

cmd := strings.TrimSpace(valueStr)

command := NodeRunCommand{SourceCode: cmd}

if strings.HasPrefix(cmd, "[") && strings.HasSuffix(cmd, "]") {
command.RunInLocal = true
if err := json.Unmarshal([]byte(cmd), &command.Command); err != nil {
return tokens, fmt.Errorf("invalid local command '%s'", cmd)
}
} else {
command.RunInLocal = false
command.Command = trimArrayString(strings.Split(cmd, "&&"))
}

commands = append(commands, command)

tokens = append(tokens, Token{
Key: keyword,
Node: NodeRun{
Command: valueStr,
Commands: commands,
SourceCode: valueStr,
},
})
Expand Down Expand Up @@ -454,3 +480,13 @@ func Tokenizer(input string) ([]Token, error) {

return tokens, nil
}

func trimArrayString(arr []string) []string {
var r = make([]string, 0)

for _, val := range arr {
r = append(r, strings.TrimSpace(val))
}

return r
}
119 changes: 96 additions & 23 deletions core/grammar/tokenizer_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package grammar_test

import (
"github.com/axetroy/s4/core/grammar"
"github.com/axetroy/s4/core/host"
"encoding/json"
"fmt"
"reflect"
"testing"

"github.com/axetroy/s4/core/grammar"
"github.com/axetroy/s4/core/host"
)

func TestTokenizer(t *testing.T) {
Expand All @@ -29,13 +32,19 @@ CMD ["ls", "-lh", "./"]
MOVE data.db data.db.bak
COPY data.db data.db.bak
DELETE file1.txt file2.txt
`,
`,
},
want: []grammar.Token{
{
Key: "RUN",
Node: grammar.NodeRun{
Command: "192.168.0.1",
Commands: []grammar.NodeRunCommand{
{
Command: []string{"192.168.0.1"},
RunInLocal: false,
SourceCode: "192.168.0.1",
},
},
SourceCode: "192.168.0.1",
},
},
Expand Down Expand Up @@ -81,7 +90,13 @@ DELETE file1.txt file2.txt
{
Key: "RUN",
Node: grammar.NodeRun{
Command: "192.168.0.1",
Commands: []grammar.NodeRunCommand{
{
Command: []string{"192.168.0.1"},
RunInLocal: false,
SourceCode: "192.168.0.1",
},
},
SourceCode: "192.168.0.1",
},
},
Expand All @@ -97,7 +112,13 @@ RUN 192.168.0.1`,
{
Key: "RUN",
Node: grammar.NodeRun{
Command: "192.168.0.1",
Commands: []grammar.NodeRunCommand{
{
Command: []string{"192.168.0.1"},
RunInLocal: false,
SourceCode: "192.168.0.1",
},
},
SourceCode: "192.168.0.1",
},
},
Expand All @@ -112,7 +133,13 @@ RUN 192.168.0.1`,
{
Key: "RUN",
Node: grammar.NodeRun{
Command: "192.168.0.1",
Commands: []grammar.NodeRunCommand{
{
Command: []string{"192.168.0.1"},
RunInLocal: false,
SourceCode: "192.168.0.1",
},
},
SourceCode: "192.168.0.1",
},
},
Expand All @@ -131,7 +158,7 @@ RUN 192.168.0.1`,
input: `CONNECT axetroy@192.168.0.1:22
RUN ls -lh
`,
`,
},
want: []grammar.Token{
{
Expand All @@ -146,7 +173,13 @@ RUN ls -lh
{
Key: "RUN",
Node: grammar.NodeRun{
Command: "ls -lh",
Commands: []grammar.NodeRunCommand{
{
Command: []string{"ls -lh"},
RunInLocal: false,
SourceCode: "ls -lh",
},
},
SourceCode: "ls -lh",
},
},
Expand Down Expand Up @@ -280,14 +313,20 @@ RUN ls -lh
RUN yarn \
&& npm run build \
&& env
`,
`,
},
want: []grammar.Token{
{
Key: "RUN",
Node: grammar.NodeRun{
Command: `yarn \ && npm run build \ && env`,
SourceCode: `yarn \ && npm run build \ && env`,
Commands: []grammar.NodeRunCommand{
{
Command: []string{"yarn", "npm run build", "env"},
RunInLocal: false,
SourceCode: "yarn && npm run build && env",
},
},
SourceCode: `yarn && npm run build && env`,
},
},
},
Expand All @@ -304,8 +343,14 @@ RUN yarn \
{
Key: "RUN",
Node: grammar.NodeRun{
Command: `yarn \&& env`,
SourceCode: `yarn \&& env`,
Commands: []grammar.NodeRunCommand{
{
Command: []string{`yarn`, `env`},
RunInLocal: false,
SourceCode: `yarn && env`,
},
},
SourceCode: `yarn && env`,
},
},
},
Expand All @@ -315,8 +360,8 @@ RUN yarn \
name: "parse var literal",
args: args{
input: `
VAR name = axetroy
`,
VAR name = axetroy
`,
},
want: []grammar.Token{
{
Expand All @@ -334,9 +379,9 @@ VAR name = axetroy
name: "parse var env",
args: args{
input: `
VAR remote_home = $HOME:remote
VAR local_home = $HOME:local
`,
VAR remote_home = $HOME:remote
VAR local_home = $HOME:local
`,
},
want: []grammar.Token{
{
Expand Down Expand Up @@ -368,9 +413,9 @@ VAR local_home = $HOME:local
name: "parse var command",
args: args{
input: `
VAR local_home <= ["echo", "$HOME"]
VAR remote_home <= echo $HOME
`,
VAR local_home <= ["echo", "$HOME"]
VAR remote_home <= echo $HOME
`,
},
want: []grammar.Token{
{
Expand Down Expand Up @@ -398,15 +443,43 @@ VAR remote_home <= echo $HOME
},
wantErr: false,
},
{
name: "run local command with RUN",
args: args{
input: `
RUN ["npm", "run", "build"]
`,
},
want: []grammar.Token{
{
Key: "RUN",
Node: grammar.NodeRun{
Commands: []grammar.NodeRunCommand{
{
Command: []string{"npm", "run", "build"},
RunInLocal: true,
SourceCode: `["npm", "run", "build"]`,
},
},
SourceCode: `["npm", "run", "build"]`,
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := grammar.Tokenizer(tt.args.input)
if (err != nil) != tt.wantErr {
t.Errorf("Tokenizer() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("Tokenizer() error = %+v, wantErr %+v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
d1, _ := json.Marshal(got)
d2, _ := json.Marshal(tt.want)
fmt.Println(string(d1))
fmt.Println(string(d2))
t.Errorf("Tokenizer() = \nresult: %+v\nexpect: %+v", got, tt.want)
}
})
Expand Down
Loading

0 comments on commit 4924a1e

Please sign in to comment.