Skip to content

Commit 1cde87c

Browse files
committed
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 <[email protected]>
1 parent 2a40b35 commit 1cde87c

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

builder/dockerignore/dockerignore.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,23 @@ func ReadAll(reader io.Reader) ([]string, error) {
3838
if pattern == "" {
3939
continue
4040
}
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+
4358
excludes = append(excludes, pattern)
4459
}
4560
if err := scanner.Err(); err != nil {

builder/dockerignore/dockerignore_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestReadAll(t *testing.T) {
2525
}
2626

2727
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")
2929
err = ioutil.WriteFile(diName, []byte(content), 0777)
3030
if err != nil {
3131
t.Fatal(err)
@@ -42,16 +42,28 @@ func TestReadAll(t *testing.T) {
4242
t.Fatal(err)
4343
}
4444

45+
if len(di) != 7 {
46+
t.Fatalf("Expected 5 entries, got %v", len(di))
47+
}
4548
if di[0] != "test1" {
4649
t.Fatal("First element is not test1")
4750
}
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")
5053
}
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")
5356
}
5457
if di[3] != "lastfile" {
5558
t.Fatal("Fourth element is not lastfile")
5659
}
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+
}
5769
}

0 commit comments

Comments
 (0)