From b21045f101c69dab9d31208e12683cff0fda21f8 Mon Sep 17 00:00:00 2001 From: Mitsuru Kariya Date: Fri, 12 Jul 2024 02:35:41 +0900 Subject: [PATCH] Restore env replacement process of ARG's variable names Up to 1.7.1, variable names in ARG command could also use environment replacement, but in commit 47a52a17b remove the replacement process, so the replacement for variable names is no longer available in 1.8.0. This PR restore this. In addition, remove the Expand method of ArgCommand because it was no longer used. Signed-off-by: Mitsuru Kariya --- frontend/dockerfile/dockerfile2llb/convert.go | 58 ++++++++++--------- frontend/dockerfile/instructions/commands.go | 19 ------ 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index e88ae7b36218..f209c9278589 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -877,9 +877,7 @@ func (e *envsFromState) Keys() []string { func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error { var err error - // ARG command value could be ignored, so defer handling the expansion error - _, isArg := cmd.Command.(*instructions.ArgCommand) - if ex, ok := cmd.Command.(instructions.SupportsSingleWordExpansion); ok && !isArg { + if ex, ok := cmd.Command.(instructions.SupportsSingleWordExpansion); ok { err := ex.Expand(func(word string) (string, error) { env := getEnv(d.state) newword, unmatched, err := opt.shlex.ProcessWord(word, env) @@ -1723,53 +1721,61 @@ func dispatchShell(d *dispatchState, c *instructions.ShellCommand) error { } func dispatchArg(d *dispatchState, c *instructions.ArgCommand, opt *dispatchOpt) error { + expand := func(word string) (string, error) { + env, err := d.state.Env(context.TODO()) + if err != nil { + return "", err + } + + newword, unmatched, err := opt.shlex.ProcessWord(word, env) + reportUnmatchedVariables(c, d.buildArgs, env, unmatched, opt) + return newword, err + } + commitStrs := make([]string, 0, len(c.Args)) for _, arg := range c.Args { - validateNoSecretKey("ARG", arg.Key, c.Location(), opt.lint) - _, hasValue := opt.buildArgValues[arg.Key] - hasDefault := arg.Value != nil + key, err := expand(arg.Key) + if err != nil { + return err + } + validateNoSecretKey("ARG", key, c.Location(), opt.lint) skipArgInfo := false // skip the arg info if the arg is inherited from global scope - if !hasDefault && !hasValue { - for _, ma := range opt.metaArgs { - if ma.Key == arg.Key { - arg.Value = ma.Value - skipArgInfo = true - hasDefault = false - } - } - } - if hasValue { - v := opt.buildArgValues[arg.Key] + if v, ok := opt.buildArgValues[key]; ok { arg.Value = &v - } else if hasDefault { - env := getEnv(d.state) - v, unmatched, err := opt.shlex.ProcessWord(*arg.Value, env) - reportUnmatchedVariables(c, d.buildArgs, env, unmatched, opt) + } else if arg.Value != nil { + v, err := expand(*arg.Value) if err != nil { return err } arg.Value = &v + } else { + for _, ma := range opt.metaArgs { + if ma.Key == key { + arg.Value = ma.Value + skipArgInfo = true + } + } } ai := argInfo{definition: arg, location: c.Location()} if arg.Value != nil { - if _, ok := nonEnvArgs[arg.Key]; !ok { - d.state = d.state.AddEnv(arg.Key, *arg.Value) + if _, ok := nonEnvArgs[key]; !ok { + d.state = d.state.AddEnv(key, *arg.Value) } ai.value = *arg.Value } if !skipArgInfo { - d.outline.allArgs[arg.Key] = ai + d.outline.allArgs[key] = ai } - d.outline.usedArgs[arg.Key] = struct{}{} + d.outline.usedArgs[key] = struct{}{} d.buildArgs = append(d.buildArgs, arg) - commitStr := arg.Key + commitStr := key if arg.Value != nil { commitStr += "=" + *arg.Value } diff --git a/frontend/dockerfile/instructions/commands.go b/frontend/dockerfile/instructions/commands.go index c0e7abe7f787..dfd7d08a8b28 100644 --- a/frontend/dockerfile/instructions/commands.go +++ b/frontend/dockerfile/instructions/commands.go @@ -456,25 +456,6 @@ type ArgCommand struct { Args []KeyValuePairOptional } -func (c *ArgCommand) Expand(expander SingleWordExpander) error { - for i, v := range c.Args { - p, err := expander(v.Key) - if err != nil { - return err - } - v.Key = p - if v.Value != nil { - p, err = expander(*v.Value) - if err != nil { - return err - } - v.Value = &p - } - c.Args[i] = v - } - return nil -} - // ShellCommand sets a custom shell to use. // // SHELL bash -e -c