shipwright
Advanced tools
+7
-0
@@ -0,1 +1,8 @@ | ||
| 0.9.0-alpha (2017-06-12) | ||
| ------------------------ | ||
| - Base the cache key on the globs in Docker COPY/ADD commands. | ||
| (`Issues #98 <https://github.com/6si/shipwright/pull/98>`_). | ||
| 0.8.0 (2017-06-08) | ||
@@ -2,0 +9,0 @@ ------------------ |
+8
-1
| Metadata-Version: 1.1 | ||
| Name: shipwright | ||
| Version: 0.8.0 | ||
| Version: 0.9.0a0 | ||
| Summary: The right way to build, tag and ship shared Docker images. | ||
@@ -159,2 +159,9 @@ Home-page: https://github.com/6si/shipwright/ | ||
| 0.9.0-alpha (2017-06-12) | ||
| ------------------------ | ||
| - Base the cache key on the globs in Docker COPY/ADD commands. | ||
| (`Issues #98 <https://github.com/6si/shipwright/pull/98>`_). | ||
| 0.8.0 (2017-06-08) | ||
@@ -161,0 +168,0 @@ ------------------ |
+1
-1
@@ -23,3 +23,3 @@ from __future__ import absolute_import, print_function | ||
| name='shipwright', | ||
| version='0.8.0', | ||
| version='0.9.0-alpha', | ||
| url='https://github.com/6si/shipwright/', | ||
@@ -26,0 +26,0 @@ license='Apache Software License', |
| Metadata-Version: 1.1 | ||
| Name: shipwright | ||
| Version: 0.8.0 | ||
| Version: 0.9.0a0 | ||
| Summary: The right way to build, tag and ship shared Docker images. | ||
@@ -159,2 +159,9 @@ Home-page: https://github.com/6si/shipwright/ | ||
| 0.9.0-alpha (2017-06-12) | ||
| ------------------------ | ||
| - Base the cache key on the globs in Docker COPY/ADD commands. | ||
| (`Issues #98 <https://github.com/6si/shipwright/pull/98>`_). | ||
| 0.8.0 (2017-06-08) | ||
@@ -161,0 +168,0 @@ ------------------ |
@@ -58,2 +58,3 @@ # -*- coding: utf-8 -*- | ||
| import argparse | ||
| import collections | ||
| import json | ||
@@ -277,2 +278,9 @@ import os | ||
| class SetJSONEncoder(json.JSONEncoder): | ||
| def default(self, obj): | ||
| if isinstance(obj, collections.Set): | ||
| return sorted(obj) | ||
| return super(SetJSONEncoder, self).decode(obj) | ||
| def run(path, arguments, client_cfg, environ, new_style_args=None): | ||
@@ -335,3 +343,3 @@ args = process_arguments( | ||
| if dump_file: | ||
| dump_file.write(json.dumps(event)) | ||
| json.dump(event, dump_file, cls=SetJSONEncoder) | ||
| dump_file.write('\n') | ||
@@ -338,0 +346,0 @@ if 'error' in event: |
| from __future__ import absolute_import | ||
| import json | ||
| import os | ||
| import re | ||
| from collections import namedtuple | ||
@@ -8,6 +10,8 @@ | ||
| 'Image', | ||
| ['name', 'dir_path', 'path', 'parent', 'short_name'], | ||
| ['name', 'dir_path', 'path', 'parent', 'short_name', 'copy_paths'], | ||
| ) | ||
| JSONDecodeError = getattr(json, 'JSONDecodeError', ValueError) | ||
| def list_images(namespace, name_map, root_path): | ||
@@ -21,2 +25,3 @@ images = [] | ||
| dir_path=os.path.dirname(path), | ||
| copy_paths=copy_paths(path), | ||
| path=path, | ||
@@ -120,2 +125,58 @@ parent=parent(path), | ||
| def sub_if(ex, repl, string, flags): | ||
| """ | ||
| Attempt a substitutuion and return the substituted string if there were | ||
| matches. | ||
| """ | ||
| res = re.sub(ex, repl, string, count=1, flags=flags) | ||
| if res != string: | ||
| return res | ||
| def parse_copy(cmd): | ||
| """ | ||
| Parse the source directoreis from a docker COPY or ADD command | ||
| Ignores http or ftp URLs in ADD commands | ||
| """ | ||
| copy = sub_if(r'^\s*(COPY)\s', '', cmd, re.I) | ||
| add = sub_if(r'^\s*(ADD)\s', '', cmd, re.I) | ||
| copy_cmd = copy or add | ||
| if not copy_cmd: | ||
| return [] | ||
| try: | ||
| result = json.loads(copy_cmd) | ||
| except JSONDecodeError: | ||
| result = None | ||
| if not isinstance(result, list): | ||
| result = copy_cmd.split(' ') | ||
| paths = result[:-1] | ||
| if not add: | ||
| return paths | ||
| return [p for p in paths if not re.match('(https?|ftp):', p, re.I)] | ||
| def copy_paths(docker_path): | ||
| dirname = os.path.dirname(docker_path) | ||
| def join(path): | ||
| return os.path.join(dirname, path) | ||
| def copy_paths_gen(): | ||
| yield docker_path | ||
| yield join('.dockerignore') | ||
| with open(docker_path) as f: | ||
| for l in f: | ||
| for p in parse_copy(l): | ||
| yield os.path.normpath(join(p)) | ||
| return frozenset(copy_paths_gen()) | ||
| def parent(docker_path): | ||
@@ -122,0 +183,0 @@ """ |
| from __future__ import absolute_import | ||
| import binascii | ||
| import fnmatch | ||
| import hashlib | ||
| import os.path | ||
| import re | ||
| from collections import namedtuple | ||
@@ -98,5 +100,16 @@ | ||
| p = _abspath(repo_wd, path) | ||
| return any(p.startswith(_abspath(wd, bp) + os.sep) for bp in base_paths) | ||
| for base_path in base_paths: | ||
| path_pattern = _abspath(wd, base_path) | ||
| if not re.match('[*?]', path_pattern): | ||
| if p == path_pattern: | ||
| return True | ||
| extra = '*' if path_pattern.endswith(os.sep) else os.sep + '*' | ||
| path_pattern += extra | ||
| if fnmatch.fnmatch(p, path_pattern): | ||
| return True | ||
| return False | ||
| def _dirty_suffix(repo, base_paths=['.']): | ||
@@ -166,3 +179,5 @@ repo_wd = repo.working_dir | ||
| for c in images: | ||
| paths = [p.dir_path for p in _image_parents(c_index, c)] | ||
| paths = sorted(frozenset.union( | ||
| *(p.copy_paths for p in _image_parents(c_index, c)) | ||
| )) | ||
| ref = (_hexsha(_last_commit(repo, paths)) + | ||
@@ -169,0 +184,0 @@ _dirty_suffix(repo, paths)) |
@@ -9,3 +9,3 @@ from __future__ import absolute_import | ||
| def targets(path='', upto=None, tags=None, mode=None): | ||
| def targets(path='.', upto=None, tags=None, mode=None): | ||
| if upto is None: | ||
@@ -12,0 +12,0 @@ upto = [] |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
96986
2.88%1523
4.32%