Skip to content

Commit

Permalink
update commandsFile extension mechanism: extends VS includes
Browse files Browse the repository at this point in the history
  • Loading branch information
dreadl0ck committed Feb 18, 2021
1 parent 1cd615f commit 90ed343
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 292 deletions.
221 changes: 68 additions & 153 deletions commandsFile.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -61,8 +60,13 @@ type CommandsFile struct {
// script to call when exiting zeus
ExitHook string `yaml:"exitHook"`

// commandsfile that is extended by this
// commandsFile that is extended by the current commandsFile.
// commands from this file will be executed within the CURRENT zeus directory.
Extends string `yaml:"extends"`

// commandsFile that is extended by the current commandsFile.
// commands from this file will be executed within the ORIGINAL zeus directory.
Includes string `yaml:"includes"`
}

func newCommandsFile() *CommandsFile {
Expand Down Expand Up @@ -104,6 +108,12 @@ func parseCommandsFile(path string, flush bool) (*CommandsFile, error) {
return nil, err
}

// catch attempts to use includes and extends at the same time
// TODO: add support for this in the future
if commandsFile.Extends != "" && commandsFile.Includes != "" {
return nil, errors.New("commandsFile options 'extends' and 'includes' can't be used in combination at the moment")
}

// check if language is supported
_, err = ls.getLang(commandsFile.Language)
if err != nil {
Expand Down Expand Up @@ -232,123 +242,6 @@ func parseCommandsFile(path string, flush bool) (*CommandsFile, error) {
return commandsFile, nil
}

// look for invalid fields in commandsFile
func validateCommandsFile(c []byte) error {

var (
fields = []string{
"description",
"help",
"language",
"arguments",
"dependencies",
"outputs",
"buildNumber",
"async",
"exec",
"globals",
"path",
"commands",
}
parsedFields []string
foundField bool
globalsStarted bool
commandsStarted bool
globalNames []string
commandNames []string
offsetCommandNamesAndGlobals int
)

// iterate over contents line by line
for i, line := range strings.Split(string(c), "\n") {

// determine current section
if strings.Contains(line, "globals:") {
globalsStarted = true
continue
} else if strings.Contains(line, "commands:") {
commandsStarted = true
globalsStarted = false
continue
}

if offsetCommandNamesAndGlobals == 0 {
if globalsStarted || commandsStarted {
offsetCommandNamesAndGlobals = countLeadingSpace(line)
}
}

// validate names of commands and custom global variable names
leadingSpace := countLeadingSpace(line)
if leadingSpace == offsetCommandNamesAndGlobals {

// catch duplicate global variable names
if globalsStarted {
field := extractYAMLField(line)
if field != "" {
for _, name := range globalNames {
if field == name {
printCodeSnippet(string(c), commandsFilePath, i)
return errors.New("line " + strconv.Itoa(i) + ": duplicate global name detected: " + name)
}
}
globalNames = append(globalNames, field)
}
}

// catch duplicate command names
if commandsStarted {
field := extractYAMLField(line)
if field != "" {

for _, name := range commandNames {
if field == name {
printCodeSnippet(string(c), commandsFilePath, i)
return errors.New("line " + strconv.Itoa(i) + ": duplicate command name detected: " + name)
}
}
commandNames = append(commandNames, field)
// next command started - reset parsedFields
parsedFields = []string{}
}
}
continue

} else if leadingSpace > offsetCommandNamesAndGlobals*2 {
// ignore everything that contains a colon inside the 'exec' field
continue
}

// check for unknown and duplicate fields + invalid combinations
field := extractYAMLField(line)
if field != "" {

// check for unknown fields
for _, item := range fields {
if field == strings.TrimSpace(string(item)) {
foundField = true
}
}
if !foundField {
printCodeSnippet(string(c), commandsFilePath, i)
return errors.New("line " + strconv.Itoa(i) + ": unknown field: " + field)
}
foundField = false

// check duplicate fields
for _, f := range parsedFields {
if f == field {
printCodeSnippet(string(c), commandsFilePath, i)
return errors.New("line " + strconv.Itoa(i) + ": duplicate field: " + field)
}
}
parsedFields = append(parsedFields, field)
}
}

return nil
}

// count prefix whitespace characters of a string
func countLeadingSpace(line string) int {
i := 0
Expand Down Expand Up @@ -391,10 +284,16 @@ func watchCommandsFile(path, eventID string) {
cmdFile, err := parseCommandsFile(path, true)
if !shellBusy {
if err != nil {
// flush command map
cmdMap.flush()
g = nil
Log.WithError(err).Error("failed to parse commandsFile")
}
} else {
if err != nil {
// flush command map
cmdMap.flush()
g = nil
// shell is currently busy. store the error to present it to the user once the shell is free again.
lastCommandsFileError = err
} else {
Expand All @@ -403,42 +302,13 @@ func watchCommandsFile(path, eventID string) {
}
}

// handle commandsfile extension
if cmdFile.Extends != "" {

// get current working directory
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

// change into extension directory
p := strings.TrimSuffix(filepath.Dir(cmdFile.Extends), "zeus")
err = os.Chdir(p)
if err != nil {
log.Fatal(err)
}

// check if a CommandsFile for the project exists
// parse and flush it, in order to use it as base for the actual commandsfile of this project
_, err = parseCommandsFile(commandsFilePath, true)
if err != nil {
Log.Error("failed to parse commandsFile: ", err, "\n")
os.Exit(1)
}
if cmdFile != nil {

// move back into actual root directory
err = os.Chdir(wd)
if err != nil {
log.Fatal(err)
}
// handle commandsFile extension
cmdFile.handleExtension()

// check if a CommandsFile for the project exists and collect the commands
cmdFile, err = parseCommandsFile(commandsFilePath, false)
if err != nil {
Log.Error("failed to parse commandsFile: ", err, "\n")
os.Exit(1)
}
// handle commandsFile inclusion
cmdFile.handleInclusion()
}
}))
if err != nil {
Expand Down Expand Up @@ -573,6 +443,51 @@ func (c *CommandsFile) handleExtension() {
log.Fatal(err)
}

// update workingDirs on loaded commands to point to the current directory
for _, cmd := range cmdMap.items {
cmd.workingDir = wd
}

// check if a CommandsFile for the project exists and collect the commands
c, err = parseCommandsFile(commandsFilePath, false)
if err != nil {
Log.Error("failed to parse commandsFile: ", err, "\n")
os.Exit(1)
}
}
}

func (c *CommandsFile) handleInclusion() {
// handle commandsFile inclusion
if c.Includes != "" {

// get current working directory
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

// change into extension directory
p := strings.TrimSuffix(filepath.Dir(c.Includes), "zeus")
err = os.Chdir(p)
if err != nil {
log.Fatal(err)
}

// check if a CommandsFile for the project exists
// parse and flush it, in order to use it as base for the actual commandsFile of this project
_, err = parseCommandsFile(commandsFilePath, true)
if err != nil {
Log.Error("failed to parse commandsFile: ", err, "\n")
os.Exit(1)
}

// move back into actual root directory
err = os.Chdir(wd)
if err != nil {
log.Fatal(err)
}

// check if a CommandsFile for the project exists and collect the commands
c, err = parseCommandsFile(commandsFilePath, false)
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,26 @@ require (
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/daaku/go.zipexe v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1
github.com/desertbit/glue v0.0.0-20190619185959-06de07e1e404
github.com/dreadl0ck/readline v0.0.0-20210203135358-2a7a5106ebf9
github.com/elliotchance/orderedmap v1.4.0
github.com/fsnotify/fsnotify v1.4.9
github.com/gen2brain/beeep v0.0.0-20200526185328-e9c15c258e28
github.com/gopherjs/gopherjs v0.0.0-20210202160940-bed99a852dfe // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/julienschmidt/httprouter v1.3.0
github.com/magefile/mage v1.11.0 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
github.com/onsi/ginkgo v1.11.0 // indirect
github.com/onsi/gomega v1.8.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0
github.com/sirupsen/logrus v1.7.0
github.com/sirupsen/logrus v1.8.0
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v1.6.4
github.com/x-cray/logrus-prefixed-formatter v0.5.2
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
golang.org/x/sys v0.0.0-20210218085108-9555bcde0c6a // indirect
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
gopkg.in/yaml.v2 v2.4.0
)
19 changes: 8 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ github.com/desertbit/glue v0.0.0-20190619185959-06de07e1e404 h1:ssU5AxBiDzI1TMmT
github.com/desertbit/glue v0.0.0-20190619185959-06de07e1e404/go.mod h1:GmhZxaat6anpeRZmbGAvasJMoxyJmzIjQtkNfn1vSEo=
github.com/dreadl0ck/readline v0.0.0-20210203135358-2a7a5106ebf9 h1:8cY+7b5a9BrJo9MvNKbmnPb1hZvLFzup95DkNvlW/9I=
github.com/dreadl0ck/readline v0.0.0-20210203135358-2a7a5106ebf9/go.mod h1:aPoBKlRY5R1G+VNa3P1Wjwh3C9SSRcOIp7+DXKh2PYA=
github.com/elliotchance/orderedmap v1.3.0 h1:k6m77/d0zCXTjsk12nX40TkEBkSICq8T4s6R6bpCqU0=
github.com/elliotchance/orderedmap v1.3.0/go.mod h1:8hdSl6jmveQw8ScByd3AaNHNk51RhbTazdqtTty+NFw=
github.com/elliotchance/orderedmap v1.4.0 h1:wZtfeEONCbx6in1CZyE6bELEt/vFayMvsxqI5SgsR+A=
github.com/elliotchance/orderedmap v1.4.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
Expand Down Expand Up @@ -52,6 +50,10 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
Expand All @@ -71,20 +73,16 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v1.6.3 h1:QdmJJYlDQhMDFrFP8IvVnx66D8mCbaQM4TsxKf7BXzo=
github.com/smartystreets/goconvey v1.6.3/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
Expand Down Expand Up @@ -113,8 +111,8 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210218085108-9555bcde0c6a h1:+Kiu2GijIw0WaCBk1i7AcqqRx8Xg3HIYaheQazXOu8w=
golang.org/x/sys v0.0.0-20210218085108-9555bcde0c6a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
Expand All @@ -131,7 +129,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
Expand Down
Loading

0 comments on commit 90ed343

Please sign in to comment.