@@ -44,7 +44,7 @@ func FormatNode(ast *ExtendedNode, c *Config) (string, bool) {
44
44
command .Arg : formatBasic ,
45
45
command .Cmd : formatCmd ,
46
46
command .Copy : formatSpaceSeparated ,
47
- command .Entrypoint : formatCmd ,
47
+ command .Entrypoint : formatEntrypoint ,
48
48
command .Env : formatEnv ,
49
49
command .Expose : formatSpaceSeparated ,
50
50
command .From : formatSpaceSeparated ,
@@ -341,10 +341,7 @@ func formatRun(n *ExtendedNode, c *Config) string {
341
341
flags := n .Node .Flags
342
342
343
343
var content string
344
- if len (n .Node .Heredocs ) > 1 {
345
- // Not implemented yet
346
- panic ("Multiple Heredocs not implemented yet" )
347
- } else if len (n .Node .Heredocs ) == 1 {
344
+ if len (n .Node .Heredocs ) >= 1 {
348
345
content = n .Node .Heredocs [0 ].Content
349
346
hereDoc = true
350
347
// TODO: check if doc.FileDescriptor == 0?
@@ -373,7 +370,8 @@ func formatRun(n *ExtendedNode, c *Config) string {
373
370
} else {
374
371
content = formatShell (content , hereDoc , c )
375
372
if hereDoc {
376
- content = "<<" + n .Node .Heredocs [0 ].Name + "\n " + content + n .Node .Heredocs [0 ].Name + "\n "
373
+ n .Node .Heredocs [0 ].Content = content
374
+ content , _ = GetHeredoc (n )
377
375
}
378
376
}
379
377
@@ -384,12 +382,33 @@ func formatRun(n *ExtendedNode, c *Config) string {
384
382
return strings .ToUpper (n .Value ) + " " + content
385
383
}
386
384
385
+ func GetHeredoc (n * ExtendedNode ) (string , bool ) {
386
+ if len (n .Node .Heredocs ) == 0 {
387
+ return "" , false
388
+ }
389
+
390
+ printAST (n , 0 )
391
+ args := []string {}
392
+ cur := n .Next
393
+ for cur != nil {
394
+ if cur .Node .Value != "" {
395
+ args = append (args , cur .Node .Value )
396
+ }
397
+ cur = cur .Next
398
+ }
399
+
400
+ content := strings .Join (args , " " ) + "\n " + n .Node .Heredocs [0 ].Content + n .Node .Heredocs [0 ].Name + "\n "
401
+ return content , true
402
+ }
387
403
func formatBasic (n * ExtendedNode , c * Config ) string {
388
404
// Uppercases the command, and indent the following lines
389
405
originalTrimmed := strings .TrimLeft (n .OriginalMultiline , " \t " )
390
406
391
- parts := regexp .MustCompile (" " ).Split (originalTrimmed , 2 )
392
- return IndentFollowingLines (strings .ToUpper (n .Value )+ " " + parts [1 ], c .IndentSize )
407
+ value , success := GetHeredoc (n )
408
+ if ! success {
409
+ value = regexp .MustCompile (" " ).Split (originalTrimmed , 2 )[1 ]
410
+ }
411
+ return IndentFollowingLines (strings .ToUpper (n .Value )+ " " + value , c .IndentSize )
393
412
}
394
413
395
414
// Marshal is a UTF-8 friendly marshaler. Go's json.Marshal is not UTF-8
@@ -407,47 +426,99 @@ func Marshal(i interface{}) ([]byte, error) {
407
426
return bytes .TrimRight (buffer .Bytes (), "\n " ), err
408
427
}
409
428
410
- func getCmd (n * ExtendedNode ) []string {
429
+ func getCmd (n * ExtendedNode , shouldSplitNode bool ) []string {
411
430
cmd := []string {}
412
431
for node := n ; node != nil ; node = node .Next {
413
432
// Split value by whitespace
414
- rawValue := strings .Trim (node .Value , " \t " )
415
- if len (node .Flags ) > 0 {
416
- rawValue += " " + strings . Join ( node .Flags , " " )
433
+ rawValue := strings .Trim (node .Node . Value , " \t " )
434
+ if len (node .Node . Flags ) > 0 {
435
+ cmd = append ( cmd , node .Node . Flags ... )
417
436
}
418
- parts , err := shlex .Split (rawValue )
419
- if err != nil {
420
- log .Fatalf ("Error splitting: %s\n " , node .Value )
437
+ // log.Printf("ShouldSplitNode: %v\n", shouldSplitNode)
438
+ if shouldSplitNode {
439
+ parts , err := shlex .Split (rawValue )
440
+ if err != nil {
441
+ log .Fatalf ("Error splitting: %s\n " , node .Node .Value )
442
+ }
443
+ cmd = append (cmd , parts ... )
444
+ } else {
445
+ cmd = append (cmd , rawValue )
421
446
}
422
- cmd = append (cmd , parts ... )
423
447
}
424
448
// log.Printf("getCmd: %v\n", cmd)
425
449
return cmd
426
450
}
427
451
452
+ func formatEntrypoint (n * ExtendedNode , c * Config ) string {
453
+ // this can technically change behavior. https://docs.docker.com/reference/dockerfile/#understand-how-cmd-and-entrypoint-interact
454
+ isJSON , ok := n .Node .Attributes ["json" ]
455
+ if ! ok {
456
+ isJSON = false
457
+ }
458
+ if ! isJSON {
459
+ // https://docs.docker.com/reference/dockerfile/#entrypoint
460
+ node := n .Next .Node .Value
461
+ parts , err := shlex .Split (node )
462
+ if err != nil {
463
+ log .Fatalf ("Error splitting: %s\n " , node )
464
+ }
465
+
466
+ doNotSplit := false
467
+ // This is a simplistic check to determine if we need to run in a full shell.
468
+ for _ , part := range parts {
469
+ if part == "&&" || part == ";" || part == "||" {
470
+ doNotSplit = true
471
+ break
472
+ }
473
+ }
474
+
475
+ if doNotSplit {
476
+ n .Next .Node .Flags = append (n .Next .Node .Flags , []string {"/bin/sh" , "-c" }... )
477
+ // Hacky workaround to tell getCmd to not split the command
478
+ if n .Node .Attributes == nil {
479
+ n .Node .Attributes = make (map [string ]bool )
480
+ }
481
+ n .Node .Attributes ["json" ] = true
482
+ }
483
+ }
484
+ // printAST(n, 0)
485
+ return formatCmd (n , c )
486
+ }
428
487
func formatCmd (n * ExtendedNode , c * Config ) string {
429
- cmd := getCmd (n .Next )
488
+ // printAST(n, 0)
489
+ isJSON , ok := n .Node .Attributes ["json" ]
490
+ if ! ok {
491
+ isJSON = false
492
+ }
493
+ cmd := getCmd (n .Next , ! isJSON )
430
494
b , err := Marshal (cmd )
431
495
if err != nil {
432
496
return ""
433
497
}
434
498
bWithSpace := strings .ReplaceAll (string (b ), "\" ,\" " , "\" , \" " )
435
- return strings .ToUpper (n .Value ) + " " + string (bWithSpace ) + "\n "
499
+ return strings .ToUpper (n .Node . Value ) + " " + string (bWithSpace ) + "\n "
436
500
}
437
501
438
502
func formatSpaceSeparated (n * ExtendedNode , c * Config ) string {
439
- cmd := strings .Join (getCmd (n .Next ), " " )
440
- if len (n .Node .Flags ) > 0 {
441
- cmd = strings .Join (n .Node .Flags , " " ) + " " + cmd
503
+ isJSON , ok := n .Node .Attributes ["json" ]
504
+ if ! ok {
505
+ isJSON = false
506
+ }
507
+ cmd , success := GetHeredoc (n )
508
+ if ! success {
509
+ cmd = strings .Join (getCmd (n .Next , isJSON ), " " )
510
+ if len (n .Node .Flags ) > 0 {
511
+ cmd = strings .Join (n .Node .Flags , " " ) + " " + cmd
512
+ }
442
513
}
443
514
444
- return strings .ToUpper (n .Value ) + " " + cmd + "\n "
515
+ return strings .ToUpper (n .Node . Value ) + " " + cmd + "\n "
445
516
}
446
517
447
518
func formatMaintainer (n * ExtendedNode , c * Config ) string {
448
519
449
520
// Get text between quotes
450
- maintainer := strings .Trim (n .Next .Value , "\" " )
521
+ maintainer := strings .Trim (n .Next .Node . Value , "\" " )
451
522
return "LABEL org.opencontainers.image.authors=\" " + maintainer + "\" \n "
452
523
}
453
524
0 commit comments