|
| 1 | +import hashlib |
1 | 2 | import os
|
2 | 3 | import shutil
|
3 | 4 | import tempfile
|
@@ -78,35 +79,50 @@ def __init__(self):
|
78 | 79 | )
|
79 | 80 |
|
80 | 81 | def detect(self, spec, ref=None, extra_args=None):
|
81 |
| - """`spec` contains a faux protocol of meca+http[s] for detection purposes |
| 82 | + """`spec` contains a faux protocol of http[s]+meca for detection purposes |
82 | 83 | and we assume `spec` trusted as a reachable MECA bundle from an allowed origin
|
83 | 84 | (binderhub RepoProvider class is already checking for this).
|
84 | 85 |
|
85 | 86 | An other HEAD check in made here in order to get the content-length header
|
86 | 87 | """
|
87 |
| - parsed = urlparse(spec) |
88 |
| - if not parsed.scheme.endswith("+meca"): |
89 |
| - return None |
90 |
| - parsed = parsed._replace(scheme=parsed.scheme[:-5]) |
91 |
| - url = urlunparse(parsed) |
92 |
| - |
93 |
| - headers = self.session.head(url).headers |
94 |
| - changes_with_content = headers.get("ETag") or headers.get("Content-Length") |
| 88 | + is_local_file = False |
| 89 | + if spec.endswith(".meca.zip") and os.path.isfile(spec): |
| 90 | + url = os.path.abspath(spec) |
| 91 | + is_local_file = True |
| 92 | + with open(url, "rb") as f: |
| 93 | + file_hash = hashlib.blake2b() |
| 94 | + while chunk := f.read(8192): |
| 95 | + file_hash.update(chunk) |
| 96 | + changes_with_content = file_hash.hexdigest() |
| 97 | + else: |
| 98 | + parsed = urlparse(spec) |
| 99 | + if not parsed.scheme.endswith("+meca"): |
| 100 | + return None |
| 101 | + parsed = parsed._replace(scheme=parsed.scheme[:-5]) |
| 102 | + url = urlunparse(parsed) |
| 103 | + |
| 104 | + headers = self.session.head(url).headers |
| 105 | + changes_with_content = headers.get("ETag") or headers.get("Content-Length") |
95 | 106 |
|
96 | 107 | self.hashed_slug = get_hashed_slug(url, changes_with_content)
|
97 | 108 |
|
98 |
| - return {"url": url, "slug": self.hashed_slug} |
| 109 | + return {"url": url, "slug": self.hashed_slug, "is_local_file": is_local_file} |
99 | 110 |
|
100 | 111 | def fetch(self, spec, output_dir, yield_output=False):
|
101 | 112 | hashed_slug = spec["slug"]
|
102 | 113 | url = spec["url"]
|
| 114 | + is_local_file = spec["is_local_file"] |
103 | 115 |
|
104 | 116 | yield f"Creating temporary directory.\n"
|
105 | 117 | with tempfile.TemporaryDirectory() as tmpdir:
|
106 | 118 | yield f"Temporary directory created at {tmpdir}.\n"
|
107 | 119 |
|
108 |
| - yield f"Fetching MECA Bundle {url}.\n" |
109 |
| - zip_filename = fetch_zipfile(self.session, url, tmpdir) |
| 120 | + if is_local_file: |
| 121 | + yield f"Found MECA Bundle {url}.\n" |
| 122 | + zip_filename = url |
| 123 | + else: |
| 124 | + yield f"Fetching MECA Bundle {url}.\n" |
| 125 | + zip_filename = fetch_zipfile(self.session, url, tmpdir) |
110 | 126 |
|
111 | 127 | yield f"Extracting MECA Bundle {zip_filename}.\n"
|
112 | 128 | is_meca, bundle_dir = extract_validate_and_identify_bundle(
|
|
0 commit comments