|
5 | 5 | import stat |
6 | 6 | import uuid |
7 | 7 | from functools import partial |
| 8 | +from tempfile import NamedTemporaryFile |
| 9 | + |
| 10 | +import requests |
| 11 | +from cachecontrol import CacheControl |
| 12 | +from cachecontrol.caches import FileCache |
8 | 13 | from typing import Any, Callable, Dict, Iterable, List, Set, Text, Tuple, Union |
9 | 14 |
|
10 | 15 | import schema_salad.validate as validate |
@@ -139,6 +144,29 @@ def trim_listing(obj): |
139 | 144 | if obj.get("location", "").startswith("file://") and "listing" in obj: |
140 | 145 | del obj["listing"] |
141 | 146 |
|
| 147 | +# Download http Files |
| 148 | +def downloadHttpFile(httpurl): |
| 149 | + # type: (Text) -> Text |
| 150 | + cache_session = None |
| 151 | + if "XDG_CACHE_HOME" in os.environ: |
| 152 | + directory = os.environ["XDG_CACHE_HOME"] |
| 153 | + elif "HOME" in os.environ: |
| 154 | + directory = os.environ["HOME"] |
| 155 | + else: |
| 156 | + directory = os.path.expanduser('~') |
| 157 | + |
| 158 | + cache_session = CacheControl( |
| 159 | + requests.Session(), |
| 160 | + cache=FileCache( |
| 161 | + os.path.join(directory, ".cache", "cwltool"))) |
| 162 | + |
| 163 | + r = cache_session.get(httpurl, stream=True) |
| 164 | + with NamedTemporaryFile(mode='wb', delete=False) as f: |
| 165 | + for chunk in r.iter_content(chunk_size=16384): |
| 166 | + if chunk: # filter out keep-alive new chunks |
| 167 | + f.write(chunk) |
| 168 | + r.close() |
| 169 | + return f.name |
142 | 170 |
|
143 | 171 | class PathMapper(object): |
144 | 172 | """Mapping of files from relative path provided in the file to a tuple of |
@@ -208,14 +236,18 @@ def visit(self, obj, stagedir, basedir, copy=False, staged=False): |
208 | 236 | self._pathmap[obj["location"]] = MapperEnt(obj["contents"], tgt, "CreateFile", staged) |
209 | 237 | else: |
210 | 238 | with SourceLine(obj, "location", validate.ValidationException): |
211 | | - # Dereference symbolic links |
212 | 239 | deref = ab |
213 | | - st = os.lstat(deref) |
214 | | - while stat.S_ISLNK(st.st_mode): |
215 | | - rl = os.readlink(deref) |
216 | | - deref = rl if os.path.isabs(rl) else os.path.join( |
217 | | - os.path.dirname(deref), rl) |
| 240 | + if urllib.parse.urlsplit(deref).scheme in ['http','https']: |
| 241 | + deref = downloadHttpFile(path) |
| 242 | + else: |
| 243 | + # Dereference symbolic links |
218 | 244 | st = os.lstat(deref) |
| 245 | + while stat.S_ISLNK(st.st_mode): |
| 246 | + rl = os.readlink(deref) |
| 247 | + deref = rl if os.path.isabs(rl) else os.path.join( |
| 248 | + os.path.dirname(deref), rl) |
| 249 | + st = os.lstat(deref) |
| 250 | + |
219 | 251 | self._pathmap[path] = MapperEnt(deref, tgt, "WritableFile" if copy else "File", staged) |
220 | 252 | self.visitlisting(obj.get("secondaryFiles", []), stagedir, basedir, copy=copy, staged=staged) |
221 | 253 |
|
|
0 commit comments