Skip to content

Commit

Permalink
walking the source commands
Browse files Browse the repository at this point in the history
  • Loading branch information
d-led committed Dec 31, 2023
1 parent 13e8deb commit 134a6e7
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 12 deletions.
43 changes: 40 additions & 3 deletions common/script_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import (
)

func ForEachVariableAssignment(key, input string, fn func(string)) {
// parse
r := strings.NewReader(input)
f, err := syntax.NewParser().Parse(r, "")
f, err := parseScript(input)
if err != nil {
return
}
Expand All @@ -25,3 +23,42 @@ func ForEachVariableAssignment(key, input string, fn func(string)) {
return true
})
}

var isSourceCommand = map[string]bool{
".": true,
"source": true,
// eval?
}

func ForEachSourcedScript(input string, fn func(string)) {
f, err := parseScript(input)
if err != nil {
return
}

syntax.Walk(f, func(node syntax.Node) bool {
switch x := node.(type) {
case *syntax.CallExpr:
if len(x.Args) == 2 {
cmd := input[x.Args[0].Pos().Offset():x.Args[0].End().Offset()]
cmd = strings.TrimLeft(cmd, "\\")

arg := input[x.Args[1].Pos().Offset():x.Args[1].End().Offset()]
arg = strings.Trim(arg, "\"'`")

if !isSourceCommand[cmd] {
return true
}

fn(arg)
}
}
return true
})
}

func parseScript(input string) (*syntax.File, error) {
r := strings.NewReader(input)
f, err := syntax.NewParser().Parse(r, "")
return f, err
}
40 changes: 31 additions & 9 deletions common/script_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ import (

func Test_parsing_scrip_assignments(t *testing.T) {
input := `
if [[ true ]]; then
export PATH="/path1:$PATH"
else
export PATH="${PATH}:/path2"
fi
PATH=$PATH:/path3
path=$path:/path4
TEST=$PATH:/path5
`
if [[ true ]]; then
export PATH="/path1:$PATH"
else
export PATH="${PATH}:/path2"
fi
PATH=$PATH:/path3
path=$path:/path4
TEST=$PATH:/path5
`

var seenValues string
ForEachVariableAssignment("PATH", input, func(s string) {
seenValues += s
Expand All @@ -27,3 +28,24 @@ TEST=$PATH:/path5
assert.NotContains(t, seenValues, "/path4")
assert.NotContains(t, seenValues, "/path5")
}

func Test_recursively_walking_sourced_scripts(t *testing.T) {
input := `
[ -s "/test1.sh" ] && \. "/test1.sh"
[ -f /test2 ] && source /test2
if [ "${BASH-no}" != "no" ]; then
[ -r ~/.test3 ] && . '~/.test3'
fi
./test4
`

seenScripts := []string{}
ForEachSourcedScript(input, func(s string) {
seenScripts = append(seenScripts, s)
})

assert.Contains(t, seenScripts, "/test1.sh")
assert.Contains(t, seenScripts, "/test2")
assert.Contains(t, seenScripts, "~/.test3")
assert.NotContains(t, seenScripts, "./test4")
}

0 comments on commit 134a6e7

Please sign in to comment.