Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/main/java/com/github/dockerjava/core/GoLangFileMatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.github.dockerjava.core;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
Expand All @@ -23,16 +24,16 @@
* character class (must be non-empty)
* c matches character c (c != '*', '?', '\\', '[')
* '\\' c matches character c
*
*
* character-range:
* c matches character c (c != '\\', '-', ']')
* '\\' c matches character c
* lo '-' hi matches character c for lo <= c <= hi
*
*
* Match requires pattern to match all of name, not just a substring.
* The only possible returned error is ErrBadPattern, when pattern
* is malformed.
*
*
* On Windows, escaping is disabled. Instead, '\\' is treated as
* path separator.
* </pre>
Expand All @@ -45,20 +46,24 @@ public class GoLangFileMatch {
public static final boolean IS_WINDOWS = File.separatorChar == '\\';

public static boolean match(List<String> patterns, File file) {
return match(patterns, file.getPath());
return !match(patterns, file.getPath()).isEmpty();
}

public static boolean match(String pattern, File file) {
return match(pattern, file.getPath());
}

public static boolean match(List<String> patterns, String name) {
/**
* Returns the matching patterns for the given string
*/
public static List<String> match(List<String> patterns, String name) {
List<String> matches = new ArrayList<String>();
for (String pattern : patterns) {
if (match(pattern, name)) {
return true;
matches.add(pattern);
}
}
return false;
return matches;
}

public static boolean match(String pattern, String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ public GoLangMatchFileFilter(File base, List<String> patterns) {
public boolean accept(File file) {
String relativePath = FilePathUtil.relativize(base, file);

boolean match = GoLangFileMatch.match(patterns, relativePath);
return !match;
return GoLangFileMatch.match(patterns, relativePath).isEmpty();
}

}
72 changes: 61 additions & 11 deletions src/main/java/com/github/dockerjava/core/dockerfile/Dockerfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.Collections2;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
Expand Down Expand Up @@ -89,12 +90,6 @@ public List<String> getIgnores() throws IOException {
}
pattern = FilenameUtils.normalize(pattern);
try {
// validate pattern and make sure we aren't excluding Dockerfile
if (GoLangFileMatch.match(pattern, "Dockerfile")) {
throw new DockerClientException(String.format(
"Dockerfile is excluded by pattern '%s' on line %s in .dockerignore file", pattern,
lineNumber));
}
ignores.add(pattern);
} catch (GoLangFileMatchException e) {
throw new DockerClientException(String.format(
Expand Down Expand Up @@ -169,7 +164,15 @@ public String toString() {
public ScannedResult() throws IOException {

ignores = getIgnores();
filesToAdd.add(dockerFile);

String matchingIgnorePattern = effectiveMatchingIgnorePattern(dockerFile);

if (matchingIgnorePattern == null) {
filesToAdd.add(dockerFile);
} else {
throw new DockerClientException(String.format(
"Dockerfile is excluded by pattern '%s' in .dockerignore file", matchingIgnorePattern));
}

for (DockerfileStatement statement : getStatements()) {
if (statement instanceof DockerfileStatement.Env) {
Expand All @@ -180,6 +183,56 @@ public ScannedResult() throws IOException {
}
}

/**
* Returns all matching ignore patterns for the given file name.
*/
private List<String> matchingIgnorePatterns(String fileName) {
List<String> matches = new ArrayList<String>();

int lineNumber = 0;
for (String pattern : ignores) {
lineNumber++;
try {
if (GoLangFileMatch.match(pattern, fileName)) {
matches.add(pattern);
}
} catch (GoLangFileMatchException e) {
throw new DockerClientException(String.format(
"Invalid pattern '%s' on line %s in .dockerignore file", pattern, lineNumber));
}
}

return matches;
}

/**
* Returns the matching ignore pattern for the given file or null if it should NOT be ignored.
* Exception rules like "!Dockerfile" will be respected.
*/
private String effectiveMatchingIgnorePattern(File file) {
String relativeFilename = FilePathUtil.relativize(getDockerFolder(), file);

List<String> matchingPattern = matchingIgnorePatterns(relativeFilename);

if (matchingPattern.isEmpty())
return null;

String lastMatchingPattern = matchingPattern.get(matchingPattern.size() - 1);

int lastMatchingPatternIndex = ignores.lastIndexOf(lastMatchingPattern);

if(lastMatchingPatternIndex == ignores.size() - 1) return lastMatchingPattern;

List<String> remainingIgnorePattern = ignores.subList(lastMatchingPatternIndex + 1, ignores.size());

for (String ignorePattern : remainingIgnorePattern) {
if (ignorePattern.equals("!" + relativeFilename))
return null;
}

return lastMatchingPattern;
}

private void processAddStatement(DockerfileStatement.Add add) throws IOException {

add = add.transform(environmentMap);
Expand All @@ -202,7 +255,7 @@ private void processAddStatement(DockerfileStatement.Add add) throws IOException
Collection<File> files = FileUtils.listFiles(src, new GoLangMatchFileFilter(src, ignores),
TrueFileFilter.INSTANCE);
filesToAdd.addAll(files);
} else if (!GoLangFileMatch.match(ignores, FilePathUtil.relativize(dockerFolder, src))) {
} else if (effectiveMatchingIgnorePattern(src) == null) {
filesToAdd.add(src);
} else {
throw new DockerClientException(String.format(
Expand Down Expand Up @@ -234,10 +287,7 @@ private Collection<File> resolveWildcards(File file, List<String> ignores) {
}

private void processEnvStatement(DockerfileStatement.Env env) {

environmentMap.put(env.variable, env.value);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* A statement present in a dockerfile.
*/
public abstract class DockerfileStatement<T extends DockerfileStatement> {
public abstract class DockerfileStatement<T extends DockerfileStatement<?>> {

private DockerfileStatement() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ public void testDockerfileIgnored() throws Exception {
dockerClient.buildImageCmd(baseDir).withNoCache().exec(new BuildImageResultCallback()).awaitImageId();
}

@Test
public void testDockerfileNotIgnored() throws Exception {
File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testDockerfileNotIgnored")
.getFile());

dockerClient.buildImageCmd(baseDir).withNoCache().exec(new BuildImageResultCallback()).awaitImageId();
}

@Test(expectedExceptions = { DockerClientException.class })
public void testInvalidDockerIgnorePattern() throws Exception {
File baseDir = new File(Thread.currentThread().getContextClassLoader()
Expand Down
2 changes: 2 additions & 0 deletions src/test/resources/testDockerfileNotIgnored/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!Dockerfile
3 changes: 3 additions & 0 deletions src/test/resources/testDockerfileNotIgnored/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM ubuntu:latest

CMD ["echo", "Success"]