Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -255,6 +255,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil |
| 255 | 255 |
return nil, errors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target)
|
| 256 | 256 |
} |
| 257 | 257 |
|
| 258 |
+ dockerfile.PrintWarnings(b.Stderr) |
|
| 258 | 259 |
b.buildArgs.WarnOnUnusedBuildArgs(b.Stderr) |
| 259 | 260 |
|
| 260 | 261 |
if dispatchState.imageID == "" {
|
| ... | ... |
@@ -246,6 +246,14 @@ type Result struct {
|
| 246 | 246 |
Warnings []string |
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 |
+// PrintWarnings to the writer |
|
| 250 |
+func (r *Result) PrintWarnings(out io.Writer) {
|
|
| 251 |
+ if len(r.Warnings) == 0 {
|
|
| 252 |
+ return |
|
| 253 |
+ } |
|
| 254 |
+ fmt.Fprintf(out, strings.Join(r.Warnings, "\n")+"\n") |
|
| 255 |
+} |
|
| 256 |
+ |
|
| 249 | 257 |
// Parse reads lines from a Reader, parses the lines into an AST and returns |
| 250 | 258 |
// the AST and escape token |
| 251 | 259 |
func Parse(rwc io.Reader) (*Result, error) {
|
| ... | ... |
@@ -311,7 +319,7 @@ func Parse(rwc io.Reader) (*Result, error) {
|
| 311 | 311 |
AST: root, |
| 312 | 312 |
Warnings: warnings, |
| 313 | 313 |
EscapeToken: d.escapeToken, |
| 314 |
- Platform: d.platformToken, |
|
| 314 |
+ Platform: d.platformToken, |
|
| 315 | 315 |
}, nil |
| 316 | 316 |
} |
| 317 | 317 |
|
| ... | ... |
@@ -27,40 +27,39 @@ func getDirs(t *testing.T, dir string) []string {
|
| 27 | 27 |
return dirs |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 |
-func TestTestNegative(t *testing.T) {
|
|
| 30 |
+func TestParseErrorCases(t *testing.T) {
|
|
| 31 | 31 |
for _, dir := range getDirs(t, negativeTestDir) {
|
| 32 | 32 |
dockerfile := filepath.Join(negativeTestDir, dir, "Dockerfile") |
| 33 | 33 |
|
| 34 | 34 |
df, err := os.Open(dockerfile) |
| 35 |
- require.NoError(t, err) |
|
| 35 |
+ require.NoError(t, err, dockerfile) |
|
| 36 | 36 |
defer df.Close() |
| 37 | 37 |
|
| 38 | 38 |
_, err = Parse(df) |
| 39 |
- assert.Error(t, err) |
|
| 39 |
+ assert.Error(t, err, dockerfile) |
|
| 40 | 40 |
} |
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 |
-func TestTestData(t *testing.T) {
|
|
| 43 |
+func TestParseCases(t *testing.T) {
|
|
| 44 | 44 |
for _, dir := range getDirs(t, testDir) {
|
| 45 | 45 |
dockerfile := filepath.Join(testDir, dir, "Dockerfile") |
| 46 | 46 |
resultfile := filepath.Join(testDir, dir, "result") |
| 47 | 47 |
|
| 48 | 48 |
df, err := os.Open(dockerfile) |
| 49 |
- require.NoError(t, err) |
|
| 49 |
+ require.NoError(t, err, dockerfile) |
|
| 50 | 50 |
defer df.Close() |
| 51 | 51 |
|
| 52 | 52 |
result, err := Parse(df) |
| 53 |
- require.NoError(t, err) |
|
| 53 |
+ require.NoError(t, err, dockerfile) |
|
| 54 | 54 |
|
| 55 | 55 |
content, err := ioutil.ReadFile(resultfile) |
| 56 |
- require.NoError(t, err) |
|
| 56 |
+ require.NoError(t, err, resultfile) |
|
| 57 | 57 |
|
| 58 | 58 |
if runtime.GOOS == "windows" {
|
| 59 | 59 |
// CRLF --> CR to match Unix behavior |
| 60 | 60 |
content = bytes.Replace(content, []byte{'\x0d', '\x0a'}, []byte{'\x0a'}, -1)
|
| 61 | 61 |
} |
| 62 |
- |
|
| 63 |
- assert.Contains(t, result.AST.Dump()+"\n", string(content), "In "+dockerfile) |
|
| 62 |
+ assert.Equal(t, result.AST.Dump()+"\n", string(content), "In "+dockerfile) |
|
| 64 | 63 |
} |
| 65 | 64 |
} |
| 66 | 65 |
|
| ... | ... |
@@ -106,7 +105,7 @@ func TestParseWords(t *testing.T) {
|
| 106 | 106 |
} |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
-func TestLineInformation(t *testing.T) {
|
|
| 109 |
+func TestParseIncludesLineNumbers(t *testing.T) {
|
|
| 110 | 110 |
df, err := os.Open(testFileLineInfo) |
| 111 | 111 |
require.NoError(t, err) |
| 112 | 112 |
defer df.Close() |
| ... | ... |
@@ -115,10 +114,8 @@ func TestLineInformation(t *testing.T) {
|
| 115 | 115 |
require.NoError(t, err) |
| 116 | 116 |
|
| 117 | 117 |
ast := result.AST |
| 118 |
- if ast.StartLine != 5 || ast.endLine != 31 {
|
|
| 119 |
- fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 31, ast.StartLine, ast.endLine) |
|
| 120 |
- t.Fatal("Root line information doesn't match result.")
|
|
| 121 |
- } |
|
| 118 |
+ assert.Equal(t, 5, ast.StartLine) |
|
| 119 |
+ assert.Equal(t, 31, ast.endLine) |
|
| 122 | 120 |
assert.Len(t, ast.Children, 3) |
| 123 | 121 |
expected := [][]int{
|
| 124 | 122 |
{5, 5},
|
| ... | ... |
@@ -126,10 +123,32 @@ func TestLineInformation(t *testing.T) {
|
| 126 | 126 |
{17, 31},
|
| 127 | 127 |
} |
| 128 | 128 |
for i, child := range ast.Children {
|
| 129 |
- if child.StartLine != expected[i][0] || child.endLine != expected[i][1] {
|
|
| 130 |
- t.Logf("Wrong line information for child %d: expected(%d-%d), actual(%d-%d)\n",
|
|
| 131 |
- i, expected[i][0], expected[i][1], child.StartLine, child.endLine) |
|
| 132 |
- t.Fatal("Root line information doesn't match result.")
|
|
| 133 |
- } |
|
| 129 |
+ msg := fmt.Sprintf("Child %d", i)
|
|
| 130 |
+ assert.Equal(t, expected[i], []int{child.StartLine, child.endLine}, msg)
|
|
| 134 | 131 |
} |
| 135 | 132 |
} |
| 133 |
+ |
|
| 134 |
+func TestParseWarnsOnEmptyContinutationLine(t *testing.T) {
|
|
| 135 |
+ dockerfile := bytes.NewBufferString(` |
|
| 136 |
+FROM alpine:3.6 |
|
| 137 |
+ |
|
| 138 |
+RUN something \ |
|
| 139 |
+ |
|
| 140 |
+ following \ |
|
| 141 |
+ |
|
| 142 |
+ more |
|
| 143 |
+ |
|
| 144 |
+RUN another \ |
|
| 145 |
+ |
|
| 146 |
+ thing |
|
| 147 |
+ `) |
|
| 148 |
+ |
|
| 149 |
+ result, err := Parse(dockerfile) |
|
| 150 |
+ require.NoError(t, err) |
|
| 151 |
+ warnings := result.Warnings |
|
| 152 |
+ assert.Len(t, warnings, 3) |
|
| 153 |
+ assert.Contains(t, warnings[0], "Empty continuation line found in") |
|
| 154 |
+ assert.Contains(t, warnings[0], "RUN something following more") |
|
| 155 |
+ assert.Contains(t, warnings[1], "RUN another thing") |
|
| 156 |
+ assert.Contains(t, warnings[2], "will become errors in a future release") |
|
| 157 |
+} |
| ... | ... |
@@ -110,17 +110,13 @@ func newURLRemote(url string, dockerfilePath string, progressReader func(in io.R |
| 110 | 110 |
return progressReader(rc), nil |
| 111 | 111 |
}, |
| 112 | 112 |
}) |
| 113 |
- if err != nil {
|
|
| 114 |
- if err == dockerfileFoundErr {
|
|
| 115 |
- res, err := parser.Parse(dockerfile) |
|
| 116 |
- if err != nil {
|
|
| 117 |
- return nil, nil, err |
|
| 118 |
- } |
|
| 119 |
- return nil, res, nil |
|
| 120 |
- } |
|
| 113 |
+ switch {
|
|
| 114 |
+ case err == dockerfileFoundErr: |
|
| 115 |
+ res, err := parser.Parse(dockerfile) |
|
| 116 |
+ return nil, res, err |
|
| 117 |
+ case err != nil: |
|
| 121 | 118 |
return nil, nil, err |
| 122 | 119 |
} |
| 123 |
- |
|
| 124 | 120 |
return withDockerfileFromContext(c.(modifiableContext), dockerfilePath) |
| 125 | 121 |
} |
| 126 | 122 |
|