Merge pull request #1838 from jmcvetta/multiline_dockerfile

Implementation of multiline syntax for Dockerfile
This commit is contained in:
Michael Crosby 2013-09-10 14:22:34 -07:00
commit bd0e4fde9a
4 changed files with 42 additions and 17 deletions

View File

@ -1,7 +1,6 @@
package docker package docker
import ( import (
"bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
@ -458,6 +457,9 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
return nil return nil
} }
// Long lines can be split with a backslash
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
func (b *buildFile) Build(context io.Reader) (string, error) { func (b *buildFile) Build(context io.Reader) (string, error) {
// FIXME: @creack any reason for using /tmp instead of ""? // FIXME: @creack any reason for using /tmp instead of ""?
// FIXME: @creack "name" is a terrible variable name // FIXME: @creack "name" is a terrible variable name
@ -470,22 +472,18 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
} }
defer os.RemoveAll(name) defer os.RemoveAll(name)
b.context = name b.context = name
dockerfile, err := os.Open(path.Join(name, "Dockerfile")) filename := path.Join(name, "Dockerfile")
if err != nil { if _, err := os.Stat(filename); os.IsNotExist(err) {
return "", fmt.Errorf("Can't build a directory with no Dockerfile") return "", fmt.Errorf("Can't build a directory with no Dockerfile")
} }
// FIXME: "file" is also a terrible variable name ;) fileBytes, err := ioutil.ReadFile(filename)
file := bufio.NewReader(dockerfile)
stepN := 0
for {
line, err := file.ReadString('\n')
if err != nil { if err != nil {
if err == io.EOF && line == "" {
break
} else if err != io.EOF {
return "", err return "", err
} }
} dockerfile := string(fileBytes)
dockerfile = lineContinuation.ReplaceAllString(dockerfile, " ")
stepN := 0
for _, line := range strings.Split(dockerfile, "\n") {
line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n") line = strings.Trim(strings.Replace(line, "\t", " ", -1), " \t\r\n")
// Skip comments and empty line // Skip comments and empty line
if len(line) == 0 || line[0] == '#' { if len(line) == 0 || line[0] == '#' {

View File

@ -45,6 +45,34 @@ run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
nil, nil,
}, },
// Exactly the same as above, except uses a line split with a \ to test
// multiline support.
{
`
from {IMAGE}
run sh -c 'echo root:testpass \
> /tmp/passwd'
run mkdir -p /var/run/sshd
run [ "$(cat /tmp/passwd)" = "root:testpass" ]
run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
`,
nil,
nil,
},
// Line containing literal "\n"
{
`
from {IMAGE}
run sh -c 'echo root:testpass > /tmp/passwd'
run echo "foo \n bar"; echo "baz"
run mkdir -p /var/run/sshd
run [ "$(cat /tmp/passwd)" = "root:testpass" ]
run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
`,
nil,
nil,
},
{ {
` `
from {IMAGE} from {IMAGE}

View File

@ -366,7 +366,6 @@ func TestParseRelease(t *testing.T) {
assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "19-generic"}, 0) assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "19-generic"}, 0)
} }
func TestDependencyGraphCircular(t *testing.T) { func TestDependencyGraphCircular(t *testing.T) {
g1 := NewDependencyGraph() g1 := NewDependencyGraph()
a := g1.NewNode("a") a := g1.NewNode("a")