From fce99c329fe4157bda209b5dfb44b0c2f8fe037e Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Mon, 26 Mar 2018 13:38:13 -0700 Subject: [PATCH] Move build utils to appropriate file Signed-off-by: Joffrey F --- docker/utils/__init__.py | 6 +-- docker/utils/build.py | 91 +++++++++++++++++++++++++++++++++++++++- docker/utils/utils.py | 89 --------------------------------------- 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/docker/utils/__init__.py b/docker/utils/__init__.py index e70a5e61..81c8186c 100644 --- a/docker/utils/__init__.py +++ b/docker/utils/__init__.py @@ -1,13 +1,13 @@ # flake8: noqa -from .build import tar, exclude_paths +from .build import create_archive, exclude_paths, mkbuildcontext, tar from .decorators import check_resource, minimum_version, update_headers from .utils import ( compare_version, convert_port_bindings, convert_volume_binds, - mkbuildcontext, parse_repository_tag, parse_host, + parse_repository_tag, parse_host, kwargs_from_env, convert_filters, datetime_to_timestamp, create_host_config, parse_bytes, parse_env_file, version_lt, version_gte, decode_json_header, split_command, create_ipam_config, create_ipam_pool, parse_devices, normalize_links, convert_service_networks, - format_environment, create_archive, format_extra_hosts + format_environment, format_extra_hosts ) diff --git a/docker/utils/build.py b/docker/utils/build.py index 0f173476..783273ee 100644 --- a/docker/utils/build.py +++ b/docker/utils/build.py @@ -1,8 +1,11 @@ +import io import os import re +import six +import tarfile +import tempfile from ..constants import IS_WINDOWS_PLATFORM -from .utils import create_archive from fnmatch import fnmatch from itertools import chain @@ -127,3 +130,89 @@ def walk(root, patterns, default=True): yield f elif matched: yield f + + +def build_file_list(root): + files = [] + for dirname, dirnames, fnames in os.walk(root): + for filename in fnames + dirnames: + longpath = os.path.join(dirname, filename) + files.append( + longpath.replace(root, '', 1).lstrip('/') + ) + + return files + + +def create_archive(root, files=None, fileobj=None, gzip=False, + extra_files=None): + extra_files = extra_files or [] + if not fileobj: + fileobj = tempfile.NamedTemporaryFile() + t = tarfile.open(mode='w:gz' if gzip else 'w', fileobj=fileobj) + if files is None: + files = build_file_list(root) + for path in files: + if path in [e[0] for e in extra_files]: + # Extra files override context files with the same name + continue + full_path = os.path.join(root, path) + + i = t.gettarinfo(full_path, arcname=path) + if i is None: + # This happens when we encounter a socket file. We can safely + # ignore it and proceed. + continue + + # Workaround https://bugs.python.org/issue32713 + if i.mtime < 0 or i.mtime > 8**11 - 1: + i.mtime = int(i.mtime) + + if 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 + + if i.isfile(): + try: + with open(full_path, 'rb') as f: + t.addfile(i, f) + except IOError: + raise IOError( + 'Can not read file in context: {}'.format(full_path) + ) + else: + # Directories, FIFOs, symlinks... don't need to be read. + t.addfile(i, None) + + for name, contents in extra_files: + info = tarfile.TarInfo(name) + info.size = len(contents) + t.addfile(info, io.BytesIO(contents.encode('utf-8'))) + + t.close() + fileobj.seek(0) + return fileobj + + +def mkbuildcontext(dockerfile): + f = tempfile.NamedTemporaryFile() + t = tarfile.open(mode='w', fileobj=f) + if isinstance(dockerfile, io.StringIO): + dfinfo = tarfile.TarInfo('Dockerfile') + if six.PY3: + raise TypeError('Please use io.BytesIO to create in-memory ' + 'Dockerfiles with Python 3') + else: + dfinfo.size = len(dockerfile.getvalue()) + dockerfile.seek(0) + elif isinstance(dockerfile, io.BytesIO): + dfinfo = tarfile.TarInfo('Dockerfile') + dfinfo.size = len(dockerfile.getvalue()) + dockerfile.seek(0) + else: + dfinfo = t.gettarinfo(fileobj=dockerfile, arcname='Dockerfile') + t.addfile(dfinfo, dockerfile) + t.close() + f.seek(0) + return f diff --git a/docker/utils/utils.py b/docker/utils/utils.py index 5024e471..fe3b9a57 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -1,17 +1,13 @@ import base64 -import io import os import os.path import json import shlex -import tarfile -import tempfile from distutils.version import StrictVersion from datetime import datetime import six -from .. import constants from .. import errors from .. import tls @@ -46,29 +42,6 @@ def create_ipam_config(*args, **kwargs): ) -def mkbuildcontext(dockerfile): - f = tempfile.NamedTemporaryFile() - t = tarfile.open(mode='w', fileobj=f) - if isinstance(dockerfile, io.StringIO): - dfinfo = tarfile.TarInfo('Dockerfile') - if six.PY3: - raise TypeError('Please use io.BytesIO to create in-memory ' - 'Dockerfiles with Python 3') - else: - dfinfo.size = len(dockerfile.getvalue()) - dockerfile.seek(0) - elif isinstance(dockerfile, io.BytesIO): - dfinfo = tarfile.TarInfo('Dockerfile') - dfinfo.size = len(dockerfile.getvalue()) - dockerfile.seek(0) - else: - dfinfo = t.gettarinfo(fileobj=dockerfile, arcname='Dockerfile') - t.addfile(dfinfo, dockerfile) - t.close() - f.seek(0) - return f - - def decode_json_header(header): data = base64.b64decode(header) if six.PY3: @@ -76,68 +49,6 @@ def decode_json_header(header): return json.loads(data) -def build_file_list(root): - files = [] - for dirname, dirnames, fnames in os.walk(root): - for filename in fnames + dirnames: - longpath = os.path.join(dirname, filename) - files.append( - longpath.replace(root, '', 1).lstrip('/') - ) - - return files - - -def create_archive(root, files=None, fileobj=None, gzip=False, - extra_files=None): - if not fileobj: - fileobj = tempfile.NamedTemporaryFile() - t = tarfile.open(mode='w:gz' if gzip else 'w', fileobj=fileobj) - if files is None: - files = build_file_list(root) - for path in files: - if path in [e[0] for e in extra_files]: - # Extra files override context files with the same name - continue - full_path = os.path.join(root, path) - - i = t.gettarinfo(full_path, arcname=path) - if i is None: - # This happens when we encounter a socket file. We can safely - # ignore it and proceed. - continue - - # Workaround https://bugs.python.org/issue32713 - if i.mtime < 0 or i.mtime > 8**11 - 1: - i.mtime = int(i.mtime) - - 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 - - if i.isfile(): - try: - with open(full_path, 'rb') as f: - t.addfile(i, f) - except IOError: - raise IOError( - 'Can not read file in context: {}'.format(full_path) - ) - else: - # Directories, FIFOs, symlinks... don't need to be read. - t.addfile(i, None) - - for name, contents in extra_files: - info = tarfile.TarInfo(name) - info.size = len(contents) - t.addfile(info, io.BytesIO(contents.encode('utf-8'))) - - t.close() - fileobj.seek(0) - return fileobj - - def compare_version(v1, v2): """Compare docker versions