|
| 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