summaryrefslogtreecommitdiff
path: root/docker/utils/build.py
diff options
context:
space:
mode:
authorJoffrey F <joffrey@docker.com>2018-03-26 13:38:13 -0700
committerJoffrey F <f.joffrey@gmail.com>2018-03-29 16:25:14 -0700
commitfce99c329fe4157bda209b5dfb44b0c2f8fe037e (patch)
tree0e2807e57cd807c790e2a6da3f6381575824bf90 /docker/utils/build.py
parent77c3e57dcfa5d5e8cf05038861b2037dafe2d0e6 (diff)
downloaddocker-py-fce99c329fe4157bda209b5dfb44b0c2f8fe037e.tar.gz
Move build utils to appropriate file
Signed-off-by: Joffrey F <joffrey@docker.com>
Diffstat (limited to 'docker/utils/build.py')
-rw-r--r--docker/utils/build.py91
1 files changed, 90 insertions, 1 deletions
diff --git a/docker/utils/build.py b/docker/utils/build.py
index 0f17347..783273e 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