Skip to content

Commit 755be79

Browse files
John Howardcrosbymichael
authored andcommitted
Move directive out of globals
Signed-off-by: John Howard <jhoward@microsoft.com> Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
1 parent 4e3d6e3 commit 755be79

File tree

9 files changed

+103
-74
lines changed

9 files changed

+103
-74
lines changed

builder/dockerfile/builder.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type Builder struct {
7171
disableCommit bool
7272
cacheBusted bool
7373
allowedBuildArgs map[string]bool // list of build-time args that are allowed for expansion/substitution and passing to commands in 'run'.
74+
directive parser.Directive
7475

7576
// TODO: remove once docker.Commit can receive a tag
7677
id string
@@ -130,9 +131,15 @@ func NewBuilder(clientCtx context.Context, config *types.ImageBuildOptions, back
130131
tmpContainers: map[string]struct{}{},
131132
id: stringid.GenerateNonCryptoID(),
132133
allowedBuildArgs: make(map[string]bool),
134+
directive: parser.Directive{
135+
EscapeSeen: false,
136+
LookingForDirectives: true,
137+
},
133138
}
139+
parser.SetEscapeToken(parser.DefaultEscapeToken, &b.directive) // Assume the default token for escape
140+
134141
if dockerfile != nil {
135-
b.dockerfile, err = parser.Parse(dockerfile)
142+
b.dockerfile, err = parser.Parse(dockerfile, &b.directive)
136143
if err != nil {
137144
return nil, err
138145
}
@@ -218,7 +225,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri
218225
for k, v := range b.options.Labels {
219226
line += fmt.Sprintf("%q=%q ", k, v)
220227
}
221-
_, node, err := parser.ParseLine(line)
228+
_, node, err := parser.ParseLine(line, &b.directive)
222229
if err != nil {
223230
return "", err
224231
}
@@ -291,7 +298,12 @@ func (b *Builder) Cancel() {
291298
//
292299
// TODO: Remove?
293300
func BuildFromConfig(config *container.Config, changes []string) (*container.Config, error) {
294-
ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")))
301+
b, err := NewBuilder(context.Background(), nil, nil, nil, nil)
302+
if err != nil {
303+
return nil, err
304+
}
305+
306+
ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")), &b.directive)
295307
if err != nil {
296308
return nil, err
297309
}
@@ -303,10 +315,6 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
303315
}
304316
}
305317

306-
b, err := NewBuilder(context.Background(), nil, nil, nil, nil)
307-
if err != nil {
308-
return nil, err
309-
}
310318
b.runConfig = config
311319
b.Stdout = ioutil.Discard
312320
b.Stderr = ioutil.Discard

builder/dockerfile/evaluator_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ func executeTestCase(t *testing.T, testCase dispatchTestCase) {
171171
}()
172172

173173
r := strings.NewReader(testCase.dockerfile)
174-
n, err := parser.Parse(r)
174+
d := parser.Directive{}
175+
parser.SetEscapeToken(parser.DefaultEscapeToken, &d)
176+
n, err := parser.Parse(r, &d)
175177

176178
if err != nil {
177179
t.Fatalf("Error when parsing Dockerfile: %s", err)

builder/dockerfile/internals.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
427427

428428
// parse the ONBUILD triggers by invoking the parser
429429
for _, step := range onBuildTriggers {
430-
ast, err := parser.Parse(strings.NewReader(step))
430+
ast, err := parser.Parse(strings.NewReader(step), &b.directive)
431431
if err != nil {
432432
return err
433433
}
@@ -648,7 +648,7 @@ func (b *Builder) parseDockerfile() error {
648648
return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.options.Dockerfile)
649649
}
650650
}
651-
b.dockerfile, err = parser.Parse(f)
651+
b.dockerfile, err = parser.Parse(f, &b.directive)
652652
if err != nil {
653653
return err
654654
}

builder/dockerfile/parser/dumper/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ func main() {
2222
panic(err)
2323
}
2424

25-
ast, err := parser.Parse(f)
25+
d := parser.Directive{LookingForDirectives: true}
26+
parser.SetEscapeToken(parser.DefaultEscapeToken, &d)
27+
28+
ast, err := parser.Parse(f, &d)
2629
if err != nil {
2730
panic(err)
2831
} else {

builder/dockerfile/parser/json_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ var validJSONArraysOfStrings = map[string][]string{
2828

2929
func TestJSONArraysOfStrings(t *testing.T) {
3030
for json, expected := range validJSONArraysOfStrings {
31-
if node, _, err := parseJSON(json); err != nil {
31+
d := Directive{}
32+
SetEscapeToken(DefaultEscapeToken, &d)
33+
34+
if node, _, err := parseJSON(json, &d); err != nil {
3235
t.Fatalf("%q should be a valid JSON array of strings, but wasn't! (err: %q)", json, err)
3336
} else {
3437
i := 0
@@ -48,7 +51,10 @@ func TestJSONArraysOfStrings(t *testing.T) {
4851
}
4952
}
5053
for _, json := range invalidJSONArraysOfStrings {
51-
if _, _, err := parseJSON(json); err != errDockerfileNotStringArray {
54+
d := Directive{}
55+
SetEscapeToken(DefaultEscapeToken, &d)
56+
57+
if _, _, err := parseJSON(json, &d); err != errDockerfileNotStringArray {
5258
t.Fatalf("%q should be an invalid JSON array of strings, but wasn't!", json)
5359
}
5460
}

builder/dockerfile/parser/line_parsers.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var (
2121

2222
// ignore the current argument. This will still leave a command parsed, but
2323
// will not incorporate the arguments into the ast.
24-
func parseIgnore(rest string) (*Node, map[string]bool, error) {
24+
func parseIgnore(rest string, d *Directive) (*Node, map[string]bool, error) {
2525
return &Node{}, nil, nil
2626
}
2727

@@ -30,12 +30,12 @@ func parseIgnore(rest string) (*Node, map[string]bool, error) {
3030
//
3131
// ONBUILD RUN foo bar -> (onbuild (run foo bar))
3232
//
33-
func parseSubCommand(rest string) (*Node, map[string]bool, error) {
33+
func parseSubCommand(rest string, d *Directive) (*Node, map[string]bool, error) {
3434
if rest == "" {
3535
return nil, nil, nil
3636
}
3737

38-
_, child, err := ParseLine(rest)
38+
_, child, err := ParseLine(rest, d)
3939
if err != nil {
4040
return nil, nil, err
4141
}
@@ -46,7 +46,7 @@ func parseSubCommand(rest string) (*Node, map[string]bool, error) {
4646
// helper to parse words (i.e space delimited or quoted strings) in a statement.
4747
// The quotes are preserved as part of this function and they are stripped later
4848
// as part of processWords().
49-
func parseWords(rest string) []string {
49+
func parseWords(rest string, d *Directive) []string {
5050
const (
5151
inSpaces = iota // looking for start of a word
5252
inWord
@@ -96,7 +96,7 @@ func parseWords(rest string) []string {
9696
blankOK = true
9797
phase = inQuote
9898
}
99-
if ch == tokenEscape {
99+
if ch == d.EscapeToken {
100100
if pos+chWidth == len(rest) {
101101
continue // just skip an escape token at end of line
102102
}
@@ -115,7 +115,7 @@ func parseWords(rest string) []string {
115115
phase = inWord
116116
}
117117
// The escape token is special except for ' quotes - can't escape anything for '
118-
if ch == tokenEscape && quote != '\'' {
118+
if ch == d.EscapeToken && quote != '\'' {
119119
if pos+chWidth == len(rest) {
120120
phase = inWord
121121
continue // just skip the escape token at end
@@ -133,14 +133,14 @@ func parseWords(rest string) []string {
133133

134134
// parse environment like statements. Note that this does *not* handle
135135
// variable interpolation, which will be handled in the evaluator.
136-
func parseNameVal(rest string, key string) (*Node, map[string]bool, error) {
136+
func parseNameVal(rest string, key string, d *Directive) (*Node, map[string]bool, error) {
137137
// This is kind of tricky because we need to support the old
138138
// variant: KEY name value
139139
// as well as the new one: KEY name=value ...
140140
// The trigger to know which one is being used will be whether we hit
141141
// a space or = first. space ==> old, "=" ==> new
142142

143-
words := parseWords(rest)
143+
words := parseWords(rest, d)
144144
if len(words) == 0 {
145145
return nil, nil, nil
146146
}
@@ -187,12 +187,12 @@ func parseNameVal(rest string, key string) (*Node, map[string]bool, error) {
187187
return rootnode, nil, nil
188188
}
189189

190-
func parseEnv(rest string) (*Node, map[string]bool, error) {
191-
return parseNameVal(rest, "ENV")
190+
func parseEnv(rest string, d *Directive) (*Node, map[string]bool, error) {
191+
return parseNameVal(rest, "ENV", d)
192192
}
193193

194-
func parseLabel(rest string) (*Node, map[string]bool, error) {
195-
return parseNameVal(rest, "LABEL")
194+
func parseLabel(rest string, d *Directive) (*Node, map[string]bool, error) {
195+
return parseNameVal(rest, "LABEL", d)
196196
}
197197

198198
// parses a statement containing one or more keyword definition(s) and/or
@@ -203,8 +203,8 @@ func parseLabel(rest string) (*Node, map[string]bool, error) {
203203
// In addition, a keyword definition alone is of the form `keyword` like `name1`
204204
// above. And the assignments `name2=` and `name3=""` are equivalent and
205205
// assign an empty value to the respective keywords.
206-
func parseNameOrNameVal(rest string) (*Node, map[string]bool, error) {
207-
words := parseWords(rest)
206+
func parseNameOrNameVal(rest string, d *Directive) (*Node, map[string]bool, error) {
207+
words := parseWords(rest, d)
208208
if len(words) == 0 {
209209
return nil, nil, nil
210210
}
@@ -229,7 +229,7 @@ func parseNameOrNameVal(rest string) (*Node, map[string]bool, error) {
229229

230230
// parses a whitespace-delimited set of arguments. The result is effectively a
231231
// linked list of string arguments.
232-
func parseStringsWhitespaceDelimited(rest string) (*Node, map[string]bool, error) {
232+
func parseStringsWhitespaceDelimited(rest string, d *Directive) (*Node, map[string]bool, error) {
233233
if rest == "" {
234234
return nil, nil, nil
235235
}
@@ -253,7 +253,7 @@ func parseStringsWhitespaceDelimited(rest string) (*Node, map[string]bool, error
253253
}
254254

255255
// parsestring just wraps the string in quotes and returns a working node.
256-
func parseString(rest string) (*Node, map[string]bool, error) {
256+
func parseString(rest string, d *Directive) (*Node, map[string]bool, error) {
257257
if rest == "" {
258258
return nil, nil, nil
259259
}
@@ -263,7 +263,7 @@ func parseString(rest string) (*Node, map[string]bool, error) {
263263
}
264264

265265
// parseJSON converts JSON arrays to an AST.
266-
func parseJSON(rest string) (*Node, map[string]bool, error) {
266+
func parseJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
267267
rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
268268
if !strings.HasPrefix(rest, "[") {
269269
return nil, nil, fmt.Errorf(`Error parsing "%s" as a JSON array`, rest)
@@ -296,12 +296,12 @@ func parseJSON(rest string) (*Node, map[string]bool, error) {
296296
// parseMaybeJSON determines if the argument appears to be a JSON array. If
297297
// so, passes to parseJSON; if not, quotes the result and returns a single
298298
// node.
299-
func parseMaybeJSON(rest string) (*Node, map[string]bool, error) {
299+
func parseMaybeJSON(rest string, d *Directive) (*Node, map[string]bool, error) {
300300
if rest == "" {
301301
return nil, nil, nil
302302
}
303303

304-
node, attrs, err := parseJSON(rest)
304+
node, attrs, err := parseJSON(rest, d)
305305

306306
if err == nil {
307307
return node, attrs, nil
@@ -318,8 +318,8 @@ func parseMaybeJSON(rest string) (*Node, map[string]bool, error) {
318318
// parseMaybeJSONToList determines if the argument appears to be a JSON array. If
319319
// so, passes to parseJSON; if not, attempts to parse it as a whitespace
320320
// delimited string.
321-
func parseMaybeJSONToList(rest string) (*Node, map[string]bool, error) {
322-
node, attrs, err := parseJSON(rest)
321+
func parseMaybeJSONToList(rest string, d *Directive) (*Node, map[string]bool, error) {
322+
node, attrs, err := parseJSON(rest, d)
323323

324324
if err == nil {
325325
return node, attrs, nil
@@ -328,11 +328,11 @@ func parseMaybeJSONToList(rest string) (*Node, map[string]bool, error) {
328328
return nil, nil, err
329329
}
330330

331-
return parseStringsWhitespaceDelimited(rest)
331+
return parseStringsWhitespaceDelimited(rest, d)
332332
}
333333

334334
// The HEALTHCHECK command is like parseMaybeJSON, but has an extra type argument.
335-
func parseHealthConfig(rest string) (*Node, map[string]bool, error) {
335+
func parseHealthConfig(rest string, d *Directive) (*Node, map[string]bool, error) {
336336
// Find end of first argument
337337
var sep int
338338
for ; sep < len(rest); sep++ {
@@ -352,7 +352,7 @@ func parseHealthConfig(rest string) (*Node, map[string]bool, error) {
352352
}
353353

354354
typ := rest[:sep]
355-
cmd, attrs, err := parseMaybeJSON(rest[next:])
355+
cmd, attrs, err := parseMaybeJSON(rest[next:], d)
356356
if err != nil {
357357
return nil, nil, err
358358
}

0 commit comments

Comments
 (0)