Преглед изворни кода

Fix builder from being over-aggressive on ${}

`${SOME_VAR%pattern}` was turning into `SOME_VAL%pattern}` which the shell would then balk at.

I've updated the `TOKEN_ENV_INTERPOLATION` regex to account for this (ie, if `${` is used, it _must_ also match the closing `}`), and renamed the variable to not be exported (since it's not used outside the function following it).

I also added comments for the bits of `tokenEnvInterpolation` so they're easier to follow. :smile:

Signed-off-by: Andrew Page <admwiggin@gmail.com>
Tianon Gravi пре 10 година
родитељ
комит
24189b2c36
2 измењених фајлова са 37 додато и 2 уклоњено
  1. 7 2
      builder/support.go
  2. 30 0
      integration-cli/docker_cli_build_test.go

+ 7 - 2
builder/support.go

@@ -6,12 +6,17 @@ import (
 )
 )
 
 
 var (
 var (
-	TOKEN_ENV_INTERPOLATION = regexp.MustCompile(`(\\\\+|[^\\]|\b|\A)\$({?)([[:alnum:]_]+)(}?)`)
+	// `\\\\+|[^\\]|\b|\A` - match any number of "\\" (ie, properly-escaped backslashes), or a single non-backslash character, or a word boundary, or beginning-of-line
+	// `\$` - match literal $
+	// `[[:alnum:]_]+` - match things like `$SOME_VAR`
+	// `{[[:alnum:]_]+}` - match things like `${SOME_VAR}`
+	tokenEnvInterpolation = regexp.MustCompile(`(\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
+	// this intentionally punts on more exotic interpolations like ${SOME_VAR%suffix} and lets the shell handle those directly
 )
 )
 
 
 // handle environment replacement. Used in dispatcher.
 // handle environment replacement. Used in dispatcher.
 func (b *Builder) replaceEnv(str string) string {
 func (b *Builder) replaceEnv(str string) string {
-	for _, match := range TOKEN_ENV_INTERPOLATION.FindAllString(str, -1) {
+	for _, match := range tokenEnvInterpolation.FindAllString(str, -1) {
 		match = match[strings.Index(match, "$"):]
 		match = match[strings.Index(match, "$"):]
 		matchKey := strings.Trim(match, "${}")
 		matchKey := strings.Trim(match, "${}")
 
 

+ 30 - 0
integration-cli/docker_cli_build_test.go

@@ -2710,3 +2710,33 @@ func TestBuildRunShEntrypoint(t *testing.T) {
 
 
 	logDone("build - entrypoint with /bin/echo running successfully")
 	logDone("build - entrypoint with /bin/echo running successfully")
 }
 }
+
+func TestBuildExoticShellInterpolation(t *testing.T) {
+	name := "testbuildexoticshellinterpolation"
+	defer deleteImages(name)
+
+	_, err := buildImage(name, `
+		FROM busybox
+
+		ENV SOME_VAR a.b.c
+
+		RUN [ "$SOME_VAR"       = 'a.b.c' ]
+		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
+		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
+		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
+		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
+		RUN [ "${SOME_VAR##*.}" = 'c'     ]
+		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
+		RUN [ "${#SOME_VAR}"    = '5'     ]
+
+		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
+		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
+		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
+		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
+	`, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	logDone("build - exotic shell interpolation")
+}