Merge pull request #2602 from tonistiigi/env-matches

shell: add function to detect what env were used
master
Tõnis Tiigi 2022-02-08 10:10:42 -08:00 committed by GitHub
commit e8f5f523aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 2 deletions

View File

@ -56,12 +56,20 @@ func (s *Lex) ProcessWordWithMap(word string, env map[string]string) (string, er
return word, err
}
// ProcessWordWithMatches will use the 'env' list of environment variables,
// replace any env var references in 'word' and return the env that were used.
func (s *Lex) ProcessWordWithMatches(word string, env map[string]string) (string, map[string]struct{}, error) {
sw := s.init(word, env)
word, _, err := sw.process(word)
return word, sw.matches, err
}
func (s *Lex) ProcessWordsWithMap(word string, env map[string]string) ([]string, error) {
_, words, err := s.process(word, env)
return words, err
}
func (s *Lex) process(word string, env map[string]string) (string, []string, error) {
func (s *Lex) init(word string, env map[string]string) *shellWord {
sw := &shellWord{
envs: env,
escapeToken: s.escapeToken,
@ -69,8 +77,14 @@ func (s *Lex) process(word string, env map[string]string) (string, []string, err
skipProcessQuotes: s.SkipProcessQuotes,
rawQuotes: s.RawQuotes,
rawEscapes: s.RawEscapes,
matches: make(map[string]struct{}),
}
sw.scanner.Init(strings.NewReader(word))
return sw
}
func (s *Lex) process(word string, env map[string]string) (string, []string, error) {
sw := s.init(word, env)
return sw.process(word)
}
@ -82,6 +96,7 @@ type shellWord struct {
rawEscapes bool
skipUnsetEnv bool
skipProcessQuotes bool
matches map[string]struct{}
}
func (sw *shellWord) process(source string) (string, []string, error) {
@ -456,6 +471,7 @@ func isSpecialParam(char rune) bool {
func (sw *shellWord) getEnv(name string) (string, bool) {
for key, value := range sw.envs {
if EqualEnvKeys(name, key) {
sw.matches[name] = struct{}{}
return value, true
}
}

View File

@ -185,7 +185,7 @@ func TestShellParser4Words(t *testing.T) {
}
func TestGetEnv(t *testing.T) {
sw := &shellWord{envs: nil}
sw := &shellWord{envs: nil, matches: make(map[string]struct{})}
getEnv := func(name string) string {
value, _ := sw.getEnv(name)
@ -225,3 +225,26 @@ func TestGetEnv(t *testing.T) {
t.Fatal("8 - 'car' should map to 'bike'")
}
}
func TestProcessWithMatches(t *testing.T) {
shlex := NewLex('\\')
w, matches, err := shlex.ProcessWordWithMatches("foo ${BAR} ${UNUSED}", map[string]string{
"ANOTHER": "bar",
"BAR": "baz",
})
require.NoError(t, err)
require.Equal(t, "foo baz ", w)
require.Equal(t, 1, len(matches))
_, ok := matches["BAR"]
require.True(t, ok)
w, matches, err = shlex.ProcessWordWithMatches("foo ${BAR:-abc} ${UNUSED}", map[string]string{
"ANOTHER": "bar",
})
require.NoError(t, err)
require.Equal(t, "foo abc ", w)
require.Equal(t, 0, len(matches))
}