Ver Fonte

Merge pull request #17599 from perhapszzy/master

Add line information in the parsed Dockerfile.
Doug Davis há 9 anos atrás
pai
commit
a5f3ed4801

+ 16 - 0
builder/dockerfile/parser/parser.go

@@ -30,6 +30,8 @@ type Node struct {
 	Attributes map[string]bool // special attributes for this node
 	Original   string          // original line used before parsing
 	Flags      []string        // only top Node should have this set
+	StartLine  int             // the line in the original dockerfile where the node begins
+	EndLine    int             // the line in the original dockerfile where the node ends
 }
 
 var (
@@ -101,19 +103,24 @@ func parseLine(line string) (string, *Node, error) {
 // Parse is the main parse routine.
 // It handles an io.ReadWriteCloser and returns the root of the AST.
 func Parse(rwc io.Reader) (*Node, error) {
+	currentLine := 0
 	root := &Node{}
+	root.StartLine = -1
 	scanner := bufio.NewScanner(rwc)
 
 	for scanner.Scan() {
 		scannedLine := strings.TrimLeftFunc(scanner.Text(), unicode.IsSpace)
+		currentLine++
 		line, child, err := parseLine(scannedLine)
 		if err != nil {
 			return nil, err
 		}
+		startLine := currentLine
 
 		if line != "" && child == nil {
 			for scanner.Scan() {
 				newline := scanner.Text()
+				currentLine++
 
 				if stripComments(strings.TrimSpace(newline)) == "" {
 					continue
@@ -137,6 +144,15 @@ func Parse(rwc io.Reader) (*Node, error) {
 		}
 
 		if child != nil {
+			// Update the line information for the current child.
+			child.StartLine = startLine
+			child.EndLine = currentLine
+			// Update the line information for the root. The starting line of the root is always the
+			// starting line of the first child and the ending line is the ending line of the last child.
+			if root.StartLine < 0 {
+				root.StartLine = currentLine
+			}
+			root.EndLine = currentLine
 			root.Children = append(root.Children, child)
 		}
 	}

+ 35 - 0
builder/dockerfile/parser/parser_test.go

@@ -12,6 +12,7 @@ import (
 
 const testDir = "testfiles"
 const negativeTestDir = "testfiles-negative"
+const testFileLineInfo = "testfile-line/Dockerfile"
 
 func getDirs(t *testing.T, dir string) []string {
 	f, err := os.Open(dir)
@@ -117,3 +118,37 @@ func TestParseWords(t *testing.T) {
 		}
 	}
 }
+
+func TestLineInformation(t *testing.T) {
+	df, err := os.Open(testFileLineInfo)
+	if err != nil {
+		t.Fatalf("Dockerfile missing for %s: %v", testFileLineInfo, err)
+	}
+	defer df.Close()
+
+	ast, err := Parse(df)
+	if err != nil {
+		t.Fatalf("Error parsing dockerfile %s: %v", testFileLineInfo, err)
+	}
+
+	if ast.StartLine != 4 || ast.EndLine != 30 {
+		fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 4, 30, ast.StartLine, ast.EndLine)
+		t.Fatalf("Root line information doesn't match result.")
+	}
+	if len(ast.Children) != 3 {
+		fmt.Fprintf(os.Stderr, "Wrong number of child: expected(%d), actual(%d)\n", 3, len(ast.Children))
+		t.Fatalf("Root line information doesn't match result.")
+	}
+	expected := [][]int{
+		{4, 4},
+		{10, 11},
+		{16, 30},
+	}
+	for i, child := range ast.Children {
+		if child.StartLine != expected[i][0] || child.EndLine != expected[i][1] {
+			fmt.Fprintf(os.Stderr, "Wrong line information for child %d: expected(%d-%d), actual(%d-%d)\n",
+				i, expected[i][0], expected[i][1], child.StartLine, child.EndLine)
+			t.Fatalf("Root line information doesn't match result.")
+		}
+	}
+}

+ 34 - 0
builder/dockerfile/parser/testfile-line/Dockerfile

@@ -0,0 +1,34 @@
+
+
+
+FROM brimstone/ubuntu:14.04
+
+
+# TORUN -v /var/run/docker.sock:/var/run/docker.sock
+
+
+ENV GOPATH \
+/go
+
+
+
+# Install the packages we need, clean up after them and us
+RUN apt-get update \
+	&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.clean \
+
+
+    && apt-get install -y --no-install-recommends git golang ca-certificates \
+    && apt-get clean \
+    && rm -rf /var/lib/apt/lists \
+
+	&& go get -v github.com/brimstone/consuldock \
+    && mv $GOPATH/bin/consuldock /usr/local/bin/consuldock \
+
+	&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \
+	&& apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \
+	&& rm /tmp/dpkg.* \
+	&& rm -rf $GOPATH
+
+
+
+