Skip to content

Commit f9505da

Browse files
committed
Correctly handle longpath prefix in process_dockerfile when joining paths
Signed-off-by: Joffrey F <[email protected]>
1 parent 2d5a7c3 commit f9505da

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

docker/api/build.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,14 @@ def process_dockerfile(dockerfile, path):
339339
abs_dockerfile = dockerfile
340340
if not os.path.isabs(dockerfile):
341341
abs_dockerfile = os.path.join(path, dockerfile)
342-
342+
if constants.IS_WINDOWS_PLATFORM and path.startswith(
343+
constants.WINDOWS_LONGPATH_PREFIX):
344+
abs_dockerfile = '{}{}'.format(
345+
constants.WINDOWS_LONGPATH_PREFIX,
346+
os.path.normpath(
347+
abs_dockerfile[len(constants.WINDOWS_LONGPATH_PREFIX):]
348+
)
349+
)
343350
if (os.path.splitdrive(path)[0] != os.path.splitdrive(abs_dockerfile)[0] or
344351
os.path.relpath(abs_dockerfile, path).startswith('..')):
345352
# Dockerfile not in context - read data to insert into tar later

docker/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
'is deprecated and non-functional. Please remove it.'
1515

1616
IS_WINDOWS_PLATFORM = (sys.platform == 'win32')
17+
WINDOWS_LONGPATH_PREFIX = '\\\\?\\'
1718

1819
DEFAULT_USER_AGENT = "docker-sdk-python/{0}".format(version)
1920
DEFAULT_NUM_POOLS = 25

tests/unit/api_build_test.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import gzip
22
import io
3+
import shutil
34

45
import docker
56
from docker import auth
7+
from docker.api.build import process_dockerfile
68

7-
from .api_test import BaseAPIClientTest, fake_request, url_prefix
89
import pytest
910

11+
from ..helpers import make_tree
12+
from .api_test import BaseAPIClientTest, fake_request, url_prefix
13+
1014

1115
class BuildTest(BaseAPIClientTest):
1216
def test_build_container(self):
@@ -161,3 +165,61 @@ def test_set_auth_headers_with_dict_and_no_auth_configs(self):
161165

162166
self.client._set_auth_headers(headers)
163167
assert headers == expected_headers
168+
169+
@pytest.mark.skipif(
170+
not docker.constants.IS_WINDOWS_PLATFORM,
171+
reason='Windows-specific syntax')
172+
def test_process_dockerfile_win_longpath_prefix(self):
173+
dirs = [
174+
'foo', 'foo/bar', 'baz',
175+
]
176+
177+
files = [
178+
'Dockerfile', 'foo/Dockerfile.foo', 'foo/bar/Dockerfile.bar',
179+
'baz/Dockerfile.baz',
180+
]
181+
182+
base = make_tree(dirs, files)
183+
self.addCleanup(shutil.rmtree, base)
184+
185+
def pre(path):
186+
return docker.constants.WINDOWS_LONGPATH_PREFIX + path
187+
188+
assert process_dockerfile(None, pre(base)) == (None, None)
189+
assert process_dockerfile('Dockerfile', pre(base)) == (
190+
'Dockerfile', None
191+
)
192+
assert process_dockerfile('foo/Dockerfile.foo', pre(base)) == (
193+
'foo/Dockerfile.foo', None
194+
)
195+
assert process_dockerfile(
196+
'../Dockerfile', pre(base + '\\foo')
197+
)[1] is not None
198+
assert process_dockerfile(
199+
'../baz/Dockerfile.baz', pre(base + '/baz')
200+
) == ('../baz/Dockerfile.baz', None)
201+
202+
def test_process_dockerfile(self):
203+
dirs = [
204+
'foo', 'foo/bar', 'baz',
205+
]
206+
207+
files = [
208+
'Dockerfile', 'foo/Dockerfile.foo', 'foo/bar/Dockerfile.bar',
209+
'baz/Dockerfile.baz',
210+
]
211+
212+
base = make_tree(dirs, files)
213+
self.addCleanup(shutil.rmtree, base)
214+
215+
assert process_dockerfile(None, base) == (None, None)
216+
assert process_dockerfile('Dockerfile', base) == ('Dockerfile', None)
217+
assert process_dockerfile('foo/Dockerfile.foo', base) == (
218+
'foo/Dockerfile.foo', None
219+
)
220+
assert process_dockerfile(
221+
'../Dockerfile', base + '/foo'
222+
)[1] is not None
223+
assert process_dockerfile('../baz/Dockerfile.baz', base + '/baz') == (
224+
'../baz/Dockerfile.baz', None
225+
)

0 commit comments

Comments
 (0)