From 77bb6dfe9f2934683f251df820e3609f74eeeaff Mon Sep 17 00:00:00 2001 From: Dean Chen <862469039@qq.com> Date: Thu, 8 Oct 2026 07:35:21 +0500 Subject: [PATCH] build: match dockerignore names case-sensitively fnmatch() lowercased both sides on every OS, so a README.md pattern also dropped readme.md while packing a build context. Use os.path.normcase, which is what this helper already documented. Windows still folds case. Fixes #3450 Signed-off-by: Dean Chen <862469039@qq.com> --- docker/utils/fnmatch.py | 5 +++-- tests/unit/utils_build_test.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docker/utils/fnmatch.py b/docker/utils/fnmatch.py index be745381e4..31bc8c6993 100644 --- a/docker/utils/fnmatch.py +++ b/docker/utils/fnmatch.py @@ -10,6 +10,7 @@ corresponding to PATTERN. (It does not compile it.) """ +import os import re __all__ = ["fnmatch", "fnmatchcase", "translate"] @@ -39,8 +40,8 @@ def fnmatch(name, pat): If you don't want this, use fnmatchcase(FILENAME, PATTERN). """ - name = name.lower() - pat = pat.lower() + name = os.path.normcase(name) + pat = os.path.normcase(pat) return fnmatchcase(name, pat) diff --git a/tests/unit/utils_build_test.py b/tests/unit/utils_build_test.py index 2089afb49d..aa28e59fc8 100644 --- a/tests/unit/utils_build_test.py +++ b/tests/unit/utils_build_test.py @@ -119,6 +119,15 @@ def test_single_filename(self): self.all_paths - {'a.py'} ) + @pytest.mark.skipif( + IS_WINDOWS_PLATFORM, reason='Windows pattern matching folds case' + ) + def test_filename_pattern_is_case_sensitive(self): + from docker.utils.build import Pattern + + assert Pattern('README.md').match('README.md') + assert not Pattern('README.md').match('readme.md') + def test_single_filename_leading_dot_slash(self): assert self.exclude(['./a.py']) == convert_paths( self.all_paths - {'a.py'}