diff --git a/appveyor.yml b/appveyor.yml index 10e32a540..1fc67cc02 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,3 @@ - version: '{branch}-{build}' install: diff --git a/docker/utils/build.py b/docker/utils/build.py index 6ba47b39f..79b72495d 100644 --- a/docker/utils/build.py +++ b/docker/utils/build.py @@ -1,5 +1,6 @@ import os +from ..constants import IS_WINDOWS_PLATFORM from .fnmatch import fnmatch from .utils import create_archive @@ -39,7 +40,7 @@ def exclude_paths(root, patterns, dockerfile=None): # If the Dockerfile is in a subdirectory that is excluded, get_paths # will not descend into it and the file will be skipped. This ensures # it doesn't happen. - set([dockerfile]) + set([dockerfile.replace('/', os.path.sep)]) if os.path.exists(os.path.join(root, dockerfile)) else set() ) @@ -130,9 +131,12 @@ def match_path(path, pattern): if pattern: pattern = os.path.relpath(pattern) + pattern_components = pattern.split(os.path.sep) + if len(pattern_components) == 1 and IS_WINDOWS_PLATFORM: + pattern_components = pattern.split('/') + if '**' not in pattern: - pattern_components = pattern.split(os.path.sep) path_components = path.split(os.path.sep)[:len(pattern_components)] else: path_components = path.split(os.path.sep) - return fnmatch('/'.join(path_components), pattern) + return fnmatch('/'.join(path_components), '/'.join(pattern_components)) diff --git a/docker/utils/fnmatch.py b/docker/utils/fnmatch.py index 80bdf7732..e95b63ceb 100644 --- a/docker/utils/fnmatch.py +++ b/docker/utils/fnmatch.py @@ -39,15 +39,13 @@ def fnmatch(name, pat): If you don't want this, use fnmatchcase(FILENAME, PATTERN). """ - import os - name = os.path.normcase(name) - pat = os.path.normcase(pat) + name = name.lower() + pat = pat.lower() return fnmatchcase(name, pat) def fnmatchcase(name, pat): """Test whether FILENAME matches PATTERN, including case. - This is a version of fnmatch() which doesn't case-normalize its arguments. """ @@ -67,7 +65,6 @@ def translate(pat): There is no way to quote meta-characters. """ - recursive_mode = False i, n = 0, len(pat) res = '' @@ -100,7 +97,7 @@ def translate(pat): stuff = '\\' + stuff res = '%s[%s]' % (res, stuff) elif recursive_mode and c == '/': - res = res + '/?' + res = res + re.escape(c) + '?' else: res = res + re.escape(c) return res + '\Z(?ms)' diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py index 4c3c3664a..25ed0f9b7 100644 --- a/tests/unit/utils_test.py +++ b/tests/unit/utils_test.py @@ -618,9 +618,11 @@ def test_build_port_bindings_with_nonmatching_internal_port_ranges(self): def convert_paths(collection): - if not IS_WINDOWS_PLATFORM: - return collection - return set(map(lambda x: x.replace('/', '\\'), collection)) + return set(map(convert_path, collection)) + + +def convert_path(path): + return path.replace('/', os.path.sep) class ExcludePathsTest(unittest.TestCase): @@ -685,12 +687,12 @@ def test_exclude_custom_dockerfile(self): set(['Dockerfile.alt', '.dockerignore']) assert self.exclude(['*'], dockerfile='foo/Dockerfile3') == \ - set(['foo/Dockerfile3', '.dockerignore']) + convert_paths(set(['foo/Dockerfile3', '.dockerignore'])) def test_exclude_dockerfile_child(self): includes = self.exclude(['foo/'], dockerfile='foo/Dockerfile3') - assert 'foo/Dockerfile3' in includes - assert 'foo/a.py' not in includes + assert convert_path('foo/Dockerfile3') in includes + assert convert_path('foo/a.py') not in includes def test_single_filename(self): assert self.exclude(['a.py']) == convert_paths( @@ -917,6 +919,7 @@ def test_tar_with_directory_symlinks(self): sorted(tar_data.getnames()), ['bar', 'bar/foo', 'foo'] ) + @pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='No UNIX sockets on Win32') def test_tar_socket_file(self): base = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, base) @@ -945,62 +948,53 @@ class ShouldCheckDirectoryTest(unittest.TestCase): ] def test_should_check_directory_not_excluded(self): - self.assertTrue( - should_check_directory('not_excluded', self.exclude_patterns, - self.include_patterns) + assert should_check_directory( + 'not_excluded', self.exclude_patterns, self.include_patterns ) - - self.assertTrue( - should_check_directory('dir/with', self.exclude_patterns, - self.include_patterns) + assert should_check_directory( + convert_path('dir/with'), self.exclude_patterns, + self.include_patterns ) def test_shoud_check_parent_directories_of_excluded(self): - self.assertTrue( - should_check_directory('dir', self.exclude_patterns, - self.include_patterns) + assert should_check_directory( + 'dir', self.exclude_patterns, self.include_patterns ) - self.assertTrue( - should_check_directory('dir/with', self.exclude_patterns, - self.include_patterns) + assert should_check_directory( + convert_path('dir/with'), self.exclude_patterns, + self.include_patterns ) def test_should_not_check_excluded_directories_with_no_exceptions(self): - self.assertFalse( - should_check_directory('exclude_rather_large_directory', - self.exclude_patterns, self.include_patterns - ) + assert not should_check_directory( + 'exclude_rather_large_directory', self.exclude_patterns, + self.include_patterns ) - self.assertFalse( - should_check_directory('dir/with/subdir_excluded', - self.exclude_patterns, self.include_patterns - ) + assert not should_check_directory( + convert_path('dir/with/subdir_excluded'), self.exclude_patterns, + self.include_patterns ) def test_should_check_excluded_directory_with_exceptions(self): - self.assertTrue( - should_check_directory('dir/with/exceptions', - self.exclude_patterns, self.include_patterns - ) + assert should_check_directory( + convert_path('dir/with/exceptions'), self.exclude_patterns, + self.include_patterns ) - self.assertTrue( - should_check_directory('dir/with/exceptions/in', - self.exclude_patterns, self.include_patterns - ) + assert should_check_directory( + convert_path('dir/with/exceptions/in'), self.exclude_patterns, + self.include_patterns ) def test_should_not_check_siblings_of_exceptions(self): - self.assertFalse( - should_check_directory('dir/with/exceptions/but_not_here', - self.exclude_patterns, self.include_patterns - ) + assert not should_check_directory( + convert_path('dir/with/exceptions/but_not_here'), + self.exclude_patterns, self.include_patterns ) def test_should_check_subdirectories_of_exceptions(self): - self.assertTrue( - should_check_directory('dir/with/exceptions/like_this_one/subdir', - self.exclude_patterns, self.include_patterns - ) + assert should_check_directory( + convert_path('dir/with/exceptions/like_this_one/subdir'), + self.exclude_patterns, self.include_patterns ) diff --git a/tox.ini b/tox.ini index 1a41c6eda..5a5e5415a 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ skipsdist=True [testenv] usedevelop=True commands = - py.test --cov=docker {posargs:tests/unit} + py.test -v --cov=docker {posargs:tests/unit} deps = -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt