diff options
author | Brandon Bodnar <bodnarbm@gmail.com> | 2016-10-28 00:06:22 -0400 |
---|---|---|
committer | Brandon Bodnar <bodnarbm@gmail.com> | 2016-11-26 21:17:18 -0500 |
commit | e2eb4a3158ece4e9a1122a85accf95e23f6630dc (patch) | |
tree | 7d2a1d6529d2b2108132c39d55a735799c697b2d | |
parent | c66c7f8b0a8ca216e21c9fe1903eb79f4406a93e (diff) | |
download | docker-py-e2eb4a3158ece4e9a1122a85accf95e23f6630dc.tar.gz |
Prevent traversing excluded directories with no possible dockerignore exceptions
Fixes an issue where all files in a rather large excluded folder are traversed and examined when creating the build context for potential exception to the exclusion, even though the exclusion rule is for a completely unrelated folder.
Signed-off-by: Brandon Bodnar <bodnarbm@gmail.com>
-rw-r--r-- | docker/utils/utils.py | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/docker/utils/utils.py b/docker/utils/utils.py index b107f22..8740164 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -214,6 +214,31 @@ def should_include(path, exclude_patterns, include_patterns): return True +def should_check_directory(directory_path, exclude_patterns, include_patterns): + """ + Given a directory path, a list of exclude patterns, and a list of inclusion + patterns: + + 1. Returns True if the directory path should be included according to + should_include. + 2. Returns True if the directory path is the prefix for an inclusion + pattern + 3. Returns False otherwise + """ + + # To account for exception rules, check directories if their path is a + # a prefix to an inclusion pattern. This logic conforms with the current + # docker logic (2016-10-27): + # https://github.com/docker/docker/blob/bc52939b0455116ab8e0da67869ec81c1a1c3e2c/pkg/archive/archive.go#L640-L671 + + path_with_slash = directory_path + os.sep + possible_child_patterns = [pattern for pattern in include_patterns if + (pattern + os.sep).startswith(path_with_slash)] + directory_included = should_include(directory_path, exclude_patterns, + include_patterns) + return directory_included or len(possible_child_patterns) > 0 + + def get_paths(root, exclude_patterns, include_patterns, has_exceptions=False): paths = [] @@ -222,25 +247,13 @@ def get_paths(root, exclude_patterns, include_patterns, has_exceptions=False): if parent == '.': parent = '' - # If exception rules exist, we can't skip recursing into ignored - # directories, as we need to look for exceptions in them. - # - # It may be possible to optimize this further for exception patterns - # that *couldn't* match within ignored directores. - # - # This matches the current docker logic (as of 2015-11-24): - # https://github.com/docker/docker/blob/37ba67bf636b34dc5c0c0265d62a089d0492088f/pkg/archive/archive.go#L555-L557 - - if not has_exceptions: - - # Remove excluded patterns from the list of directories to traverse - # by mutating the dirs we're iterating over. - # This looks strange, but is considered the correct way to skip - # traversal. See https://docs.python.org/2/library/os.html#os.walk - - dirs[:] = [d for d in dirs if - should_include(os.path.join(parent, d), - exclude_patterns, include_patterns)] + # Remove excluded patterns from the list of directories to traverse + # by mutating the dirs we're iterating over. + # This looks strange, but is considered the correct way to skip + # traversal. See https://docs.python.org/2/library/os.html#os.walk + dirs[:] = [d for d in dirs if + should_check_directory(os.path.join(parent, d), + exclude_patterns, include_patterns)] for path in dirs: if should_include(os.path.join(parent, path), |