2020from shutil import which
2121from tempfile import TemporaryDirectory
2222from typing import Iterator , Literal , Required , TypedDict , cast
23- from urllib .request import urlretrieve
2423
2524import requirements
2625import yaml
@@ -65,6 +64,7 @@ class FlatpakSourceRef(TypedDict, total=False):
6564
6665
6766BASE_DIR = os .path .dirname (os .path .abspath (__file__ ))
67+ CACHED_DOWNLOADS_DIR = "tmp-downloads"
6868INTERPRETER = sys .executable
6969REQUIREMENTS_FILE_NIGHTLY = os .path .join (BASE_DIR , ".." , ".." , "requirements.txt" )
7070REQUIREMENTS_FILE_STABLE = os .path .join (BASE_DIR , ".." , ".." , "requirements-frozen.txt" )
@@ -205,8 +205,11 @@ def source_ref_skytemple_randomizer(git_tag: str | None) -> FlatpakSourceRef:
205205
206206
207207@contextmanager
208- def clone_repo_for_generator (req : Requirement , git_url : str ) -> Iterator [str ]:
208+ def clone_repo_for_generator (req : Requirement , git_url : str , dirname : str | None = None ) -> Iterator [str ]:
209209 with TemporaryDirectory () as tmp_dir :
210+ if dirname is not None :
211+ tmp_dir = os .path .join (tmp_dir , dirname )
212+ os .makedirs (tmp_dir )
210213 print_t (f"Cloning repo for { req .name } for analysis to tmp dir { tmp_dir } " )
211214 tag = get_git_tag_for_req (req )
212215 run_git ("clone" , git_url , tmp_dir )
@@ -222,7 +225,7 @@ def get_pkgname_and_version_from_repo(req: Requirement, git_url: str) -> tuple[s
222225 return get_pkgname_and_version_from_pyproject_toml (os .path .join (tmp_dir , "pyproject.toml" ))
223226
224227
225- def fixup_and_add_extra_pip_dependencies (out_json_path : str , extras : dict ) -> None :
228+ def fixup_and_add_extra_pip_dependencies (out_json_path : str , extras : dict , cache_dir : str ) -> None :
226229 print_t ("Fixing up requirements JSON file and adding additional dependencies" )
227230 with open (out_json_path , "r" ) as f :
228231 modules = json .load (f )
@@ -254,37 +257,49 @@ def remove_module(name: str, mods: list[str]):
254257 ]
255258 # The pip generator doesn't properly parse the @ part of VCS dependencies, always trying to attribute
256259 # it as a commit. Sigh.
257- # Also installing Git repos only works for one single depedency , so use download tar.gz instead .
260+ # Also installing Git repos only works for one single dependency , so we build a tar.gz with submodules in it .
258261 for source in module ["sources" ]:
259262 if "commit" in source :
260263 if source ["commit" ] is None :
261264 branch = "master"
262265 else :
263266 branch = source ["commit" ]
264267 giturl = source ["url" ]
268+ pseudo_req = Requirement .parse_line (f"{ giturl } @ { giturl } @{ branch } " )
265269 if giturl not in version_cache or giturl not in names_cache :
266- names_cache [giturl ], version_cache [giturl ] = get_pkgname_and_version_from_repo (
267- Requirement .parse_line (f"{ giturl } @ { giturl } @{ branch } " ), giturl
268- )
270+ names_cache [giturl ], version_cache [giturl ] = get_pkgname_and_version_from_repo (pseudo_req , giturl )
269271 # Make sure to install the requirement from the downloaded tar instead
270272 if f"python3-{ names_cache [giturl ]} " == module ["name" ]:
271273 module ["build-commands" ][0 ] = (
272274 module ["build-commands" ][0 ].removesuffix ('"."' ) + f'"{ names_cache [giturl ]} "'
273275 )
274276 source ["type" ] = "file"
275277 del source ["commit" ]
276- source ["url" ] = source ["url" ] + f"/archive/refs/heads/{ branch } .tar.gz"
278+ fname = f"{ names_cache [giturl ]} -{ version_cache [giturl ]} .tar.gz"
279+ source ["url" ] = os .path .abspath (os .path .join (cache_dir , fname ))
277280 if source ["url" ] not in checksum_cache :
278- # download to get checksum
279- with TemporaryDirectory () as tmp_dir :
280- print_t (f"Fetching { source ["url" ]} for hashsum." )
281- fpath = os .path .join (tmp_dir , "file" )
282- urlretrieve (source ["url" ], fpath )
283- with open (fpath , "rb" , buffering = 0 ) as f9 :
281+ # download to generate tarball and to get checksum
282+ with clone_repo_for_generator (
283+ pseudo_req , giturl , f"{ names_cache [giturl ]} -{ version_cache [giturl ]} "
284+ ) as tmp_dir :
285+ print_t (f"Fetching { source ["url" ]} for tar.gz." )
286+ print_cmd (f"generator--download-repo-with-submodules.sh { tmp_dir } { source ["url" ]} " )
287+ subprocess .run (
288+ [
289+ os .path .join (BASE_DIR , "generator--download-repo-with-submodules.sh" ),
290+ tmp_dir ,
291+ source ["url" ],
292+ ],
293+ check = True ,
294+ capture_output = True ,
295+ )
296+ with open (source ["url" ], "rb" , buffering = 0 ) as f9 :
284297 checksum_cache [source ["url" ]] = hashlib .file_digest (f9 , "sha256" ).hexdigest () # type: ignore
285298
286299 source ["sha256" ] = checksum_cache [source ["url" ]]
287- source ["dest-filename" ] = f"{ names_cache [giturl ]} -{ version_cache [giturl ]} .tar.gz"
300+ source ["dest-filename" ] = fname
301+ source ["path" ] = source ["url" ]
302+ del source ["url" ]
288303 with open (out_json_path , "w" ) as f3 :
289304 json .dump (modules , f3 , indent = 4 )
290305
@@ -304,6 +319,7 @@ def pip_add_group(extras: dict, value: str, dest: str | None = None) -> str:
304319def generate (out_dir : str , reqs_file : str , * , tag : str | None = None ) -> None :
305320 reqs = parse_reqs_with_skytemple_files_reqs (reqs_file )
306321 print_t (f"Generating to { out_dir } . Tag info: { tag } " )
322+ os .makedirs (os .path .join (out_dir , CACHED_DOWNLOADS_DIR ), exist_ok = True )
307323 with open (os .path .join (BASE_DIR , MANIFEST_TEMPLATE_FILE ), "r" ) as f :
308324 jinja_env = Environment (loader = DictLoader ({"tmpl" : f .read ()}))
309325
@@ -331,7 +347,11 @@ def generate(out_dir: str, reqs_file: str, *, tag: str | None = None) -> None:
331347 os .path .join (path_skytemple_rust , "Cargo.lock" ),
332348 os .path .join (out_dir , "cargo-sources-skytemple-rust.json" ),
333349 )
334- fixup_and_add_extra_pip_dependencies (os .path .join (out_dir , "requirements-skytemple-randomizer.json" ), extras )
350+ fixup_and_add_extra_pip_dependencies (
351+ os .path .join (out_dir , "requirements-skytemple-randomizer.json" ),
352+ extras ,
353+ os .path .join (out_dir , CACHED_DOWNLOADS_DIR ),
354+ )
335355
336356 print_t ("Writing manifest file..." )
337357 with open (os .path .join (out_dir , OUT_MANIFEST_FILE ), "w" ) as f :
0 commit comments