Correctly support absolute paths in .dockerignore

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2018-02-12 14:59:41 -08:00
parent 7c19772eb6
commit 34d50483e2
2 changed files with 30 additions and 17 deletions

View File

@ -46,7 +46,7 @@ def exclude_paths(root, patterns, dockerfile=None):
) )
def should_include(path, exclude_patterns, include_patterns): def should_include(path, exclude_patterns, include_patterns, root):
""" """
Given a path, a list of exclude patterns, and a list of inclusion patterns: Given a path, a list of exclude patterns, and a list of inclusion patterns:
@ -61,11 +61,15 @@ def should_include(path, exclude_patterns, include_patterns):
for pattern in include_patterns: for pattern in include_patterns:
if match_path(path, pattern): if match_path(path, pattern):
return True return True
if os.path.isabs(pattern) and match_path(
os.path.join(root, path), pattern):
return True
return False return False
return True return True
def should_check_directory(directory_path, exclude_patterns, include_patterns): def should_check_directory(directory_path, exclude_patterns, include_patterns,
root):
""" """
Given a directory path, a list of exclude patterns, and a list of inclusion Given a directory path, a list of exclude patterns, and a list of inclusion
patterns: patterns:
@ -91,7 +95,7 @@ def should_check_directory(directory_path, exclude_patterns, include_patterns):
if (pattern + '/').startswith(path_with_slash) if (pattern + '/').startswith(path_with_slash)
] ]
directory_included = should_include( directory_included = should_include(
directory_path, exclude_patterns, include_patterns directory_path, exclude_patterns, include_patterns, root
) )
return directory_included or len(possible_child_patterns) > 0 return directory_included or len(possible_child_patterns) > 0
@ -110,26 +114,28 @@ def get_paths(root, exclude_patterns, include_patterns, has_exceptions=False):
# traversal. See https://docs.python.org/2/library/os.html#os.walk # traversal. See https://docs.python.org/2/library/os.html#os.walk
dirs[:] = [ dirs[:] = [
d for d in dirs if should_check_directory( d for d in dirs if should_check_directory(
os.path.join(parent, d), exclude_patterns, include_patterns os.path.join(parent, d), exclude_patterns, include_patterns,
root
) )
] ]
for path in dirs: for path in dirs:
if should_include(os.path.join(parent, path), if should_include(os.path.join(parent, path),
exclude_patterns, include_patterns): exclude_patterns, include_patterns, root):
paths.append(os.path.join(parent, path)) paths.append(os.path.join(parent, path))
for path in files: for path in files:
if should_include(os.path.join(parent, path), if should_include(os.path.join(parent, path),
exclude_patterns, include_patterns): exclude_patterns, include_patterns, root):
paths.append(os.path.join(parent, path)) paths.append(os.path.join(parent, path))
return paths return paths
def match_path(path, pattern): def match_path(path, pattern):
pattern = pattern.rstrip('/' + os.path.sep) pattern = pattern.rstrip('/' + os.path.sep)
if pattern: if pattern and not os.path.isabs(pattern):
pattern = os.path.relpath(pattern) pattern = os.path.relpath(pattern)
pattern_components = pattern.split(os.path.sep) pattern_components = pattern.split(os.path.sep)

View File

@ -876,6 +876,13 @@ class ExcludePathsTest(unittest.TestCase):
) )
) )
def test_exclude_include_absolute_path(self):
base = make_tree([], ['a.py', 'b.py'])
assert exclude_paths(
base,
['/*', '!' + os.path.join(base, '*.py')]
) == set(['a.py', 'b.py'])
class TarTest(unittest.TestCase): class TarTest(unittest.TestCase):
def test_tar_with_excludes(self): def test_tar_with_excludes(self):
@ -1026,52 +1033,52 @@ class ShouldCheckDirectoryTest(unittest.TestCase):
def test_should_check_directory_not_excluded(self): def test_should_check_directory_not_excluded(self):
assert should_check_directory( assert should_check_directory(
'not_excluded', self.exclude_patterns, self.include_patterns 'not_excluded', self.exclude_patterns, self.include_patterns, '.'
) )
assert should_check_directory( assert should_check_directory(
convert_path('dir/with'), self.exclude_patterns, convert_path('dir/with'), self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
def test_shoud_check_parent_directories_of_excluded(self): def test_shoud_check_parent_directories_of_excluded(self):
assert should_check_directory( assert should_check_directory(
'dir', self.exclude_patterns, self.include_patterns 'dir', self.exclude_patterns, self.include_patterns, '.'
) )
assert should_check_directory( assert should_check_directory(
convert_path('dir/with'), self.exclude_patterns, convert_path('dir/with'), self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
def test_should_not_check_excluded_directories_with_no_exceptions(self): def test_should_not_check_excluded_directories_with_no_exceptions(self):
assert not should_check_directory( assert not should_check_directory(
'exclude_rather_large_directory', self.exclude_patterns, 'exclude_rather_large_directory', self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
assert not should_check_directory( assert not should_check_directory(
convert_path('dir/with/subdir_excluded'), self.exclude_patterns, convert_path('dir/with/subdir_excluded'), self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
def test_should_check_excluded_directory_with_exceptions(self): def test_should_check_excluded_directory_with_exceptions(self):
assert should_check_directory( assert should_check_directory(
convert_path('dir/with/exceptions'), self.exclude_patterns, convert_path('dir/with/exceptions'), self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
assert should_check_directory( assert should_check_directory(
convert_path('dir/with/exceptions/in'), self.exclude_patterns, convert_path('dir/with/exceptions/in'), self.exclude_patterns,
self.include_patterns self.include_patterns, '.'
) )
def test_should_not_check_siblings_of_exceptions(self): def test_should_not_check_siblings_of_exceptions(self):
assert not should_check_directory( assert not should_check_directory(
convert_path('dir/with/exceptions/but_not_here'), convert_path('dir/with/exceptions/but_not_here'),
self.exclude_patterns, self.include_patterns self.exclude_patterns, self.include_patterns, '.'
) )
def test_should_check_subdirectories_of_exceptions(self): def test_should_check_subdirectories_of_exceptions(self):
assert should_check_directory( assert should_check_directory(
convert_path('dir/with/exceptions/like_this_one/subdir'), convert_path('dir/with/exceptions/like_this_one/subdir'),
self.exclude_patterns, self.include_patterns self.exclude_patterns, self.include_patterns, '.'
) )