diff --git a/docker/utils/utils.py b/docker/utils/utils.py index e12fcf00..8026c4df 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -4,7 +4,6 @@ import os import os.path import json import shlex -import sys import tarfile import tempfile import warnings @@ -15,6 +14,7 @@ from fnmatch import fnmatch import requests import six +from .. import constants from .. import errors from .. import tls @@ -90,7 +90,12 @@ def tar(path, exclude=None, dockerfile=None, fileobj=None, gzip=False): for path in sorted(exclude_paths(root, exclude, dockerfile=dockerfile)): i = t.gettarinfo(os.path.join(root, path), arcname=path) - if sys.platform == 'win32': + if i is None: + # This happens when we encounter a socket file. We can safely + # ignore it and proceed. + continue + + if constants.IS_WINDOWS_PLATFORM: # Windows doesn't keep track of the execute bit, so we make files # and directories executable by default. i.mode = i.mode & 0o755 | 0o111 diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py index cf00616d..71a8cc70 100644 --- a/tests/unit/utils_test.py +++ b/tests/unit/utils_test.py @@ -5,6 +5,7 @@ import json import os import os.path import shutil +import socket import sys import tarfile import tempfile @@ -894,6 +895,20 @@ class TarTest(unittest.TestCase): sorted(tar_data.getnames()), ['bar', 'bar/foo', 'foo'] ) + def test_tar_socket_file(self): + base = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, base) + for d in ['foo', 'bar']: + os.makedirs(os.path.join(base, d)) + sock = socket.socket(socket.AF_UNIX) + self.addCleanup(sock.close) + sock.bind(os.path.join(base, 'test.sock')) + with tar(base) as archive: + tar_data = tarfile.open(fileobj=archive) + self.assertEqual( + sorted(tar_data.getnames()), ['bar', 'foo'] + ) + class ShouldCheckDirectoryTest(unittest.TestCase): exclude_patterns = [