Browse code

Fix behavior of absolute paths in .dockerignore

According to documentation (https://docs.docker.com/engine/reference/builder/#dockerignore-file), absolute paths like `/foo/bar` should have the same effect as `foo/bar`. This is not the case today.

This fix normalize paths when reading the .dockerignore file by removing
leading slashes.

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>

Simon Ferquel authored on 2017/03/24 23:39:47
Showing 2 changed files
... ...
@@ -38,8 +38,23 @@ func ReadAll(reader io.Reader) ([]string, error) {
38 38
 		if pattern == "" {
39 39
 			continue
40 40
 		}
41
-		pattern = filepath.Clean(pattern)
42
-		pattern = filepath.ToSlash(pattern)
41
+		// normalize absolute paths to paths relative to the context
42
+		// (taking care of '!' prefix)
43
+		invert := pattern[0] == '!'
44
+		if invert {
45
+			pattern = strings.TrimSpace(pattern[1:])
46
+		}
47
+		if len(pattern) > 0 {
48
+			pattern = filepath.Clean(pattern)
49
+			pattern = filepath.ToSlash(pattern)
50
+			if len(pattern) > 1 && pattern[0] == '/' {
51
+				pattern = pattern[1:]
52
+			}
53
+		}
54
+		if invert {
55
+			pattern = "!" + pattern
56
+		}
57
+
43 58
 		excludes = append(excludes, pattern)
44 59
 	}
45 60
 	if err := scanner.Err(); err != nil {
... ...
@@ -25,7 +25,7 @@ func TestReadAll(t *testing.T) {
25 25
 	}
26 26
 
27 27
 	diName := filepath.Join(tmpDir, ".dockerignore")
28
-	content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile")
28
+	content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile\n# this is a comment\n! /inverted/abs/path\n!\n! \n")
29 29
 	err = ioutil.WriteFile(diName, []byte(content), 0777)
30 30
 	if err != nil {
31 31
 		t.Fatal(err)
... ...
@@ -42,16 +42,28 @@ func TestReadAll(t *testing.T) {
42 42
 		t.Fatal(err)
43 43
 	}
44 44
 
45
+	if len(di) != 7 {
46
+		t.Fatalf("Expected 5 entries, got %v", len(di))
47
+	}
45 48
 	if di[0] != "test1" {
46 49
 		t.Fatal("First element is not test1")
47 50
 	}
48
-	if di[1] != "/test2" {
49
-		t.Fatal("Second element is not /test2")
51
+	if di[1] != "test2" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
52
+		t.Fatal("Second element is not test2")
50 53
 	}
51
-	if di[2] != "/a/file/here" {
52
-		t.Fatal("Third element is not /a/file/here")
54
+	if di[2] != "a/file/here" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
55
+		t.Fatal("Third element is not a/file/here")
53 56
 	}
54 57
 	if di[3] != "lastfile" {
55 58
 		t.Fatal("Fourth element is not lastfile")
56 59
 	}
60
+	if di[4] != "!inverted/abs/path" {
61
+		t.Fatal("Fifth element is not !inverted/abs/path")
62
+	}
63
+	if di[5] != "!" {
64
+		t.Fatalf("Sixth element is not !, but %s", di[5])
65
+	}
66
+	if di[6] != "!" {
67
+		t.Fatalf("Sixth element is not !, but %s", di[6])
68
+	}
57 69
 }