import os import subprocess import sys import tarfile import urllib.parse import urllib.request import zipfile def filename(url): parsed = urllib.parse.urlparse(url) path = parsed.path filename = os.path.basename(path) if not filename: raise ValueError("No filename found in URL") return filename def download(url, output): subprocess.run(["curl", "-L", "-o", output, url], check=True) def tar_common_root(tar: tarfile.TarFile) -> str | None: root = None for member in tar.getmembers(): this_root = member.path.split("/")[0] if root is None: root = this_root if this_root != root: return None return root def zip_common_root(zip_file: zipfile.ZipFile) -> str | None: members = zip_file.infolist() if not members: return None root = None for member in members: path = member.filename.replace('\\', '/').lstrip('./').lstrip('/') if not path: continue this_root = path.split('/')[0] if this_root in ('', '.', '..'): continue if root is None: root = this_root elif this_root != root: return None return root def download_decompress(url: str) -> str: download_path = f"./target/{filename(url)}" download(url, download_path) if download_path.endswith(".zip"): with zipfile.ZipFile(download_path, "r") as zip: common_root = zip_common_root(zip) else: with tarfile.open(download_path, "r") as tar: common_root = tar_common_root(tar) extract_dir = "./target" sources_dir = f"./target/{common_root}" if common_root in ["", ".", None]: extract_dir = "./target/sources" sources_dir = "./target/sources" if download_path.endswith(".zip"): with zipfile.ZipFile(download_path, "r") as zip: zip.extractall(extract_dir) else: with tarfile.open(download_path, "r") as tar: tar.extractall(extract_dir) return sources_dir def sources_dir_name() -> str: with open("./target/sources.tag") as file: return file.read() def source_url(url: str): if os.path.exists("./target/sources.tag"): return sources_dir = download_decompress(url) with open("./target/sources.tag", "wt+") as file: file.write(sources_dir) def _git_repo_name(url: str) -> str: return url.split("/")[-1].replace(".git", "") def source_git(url: str, branch: str | None = None): source_path = os.getcwd() + "/target/" + _git_repo_name(url) if os.path.exists("./target/sources.tag"): return cmdline = ["git", "clone", "--depth=1"] if branch: cmdline += ["-b", branch] cmdline += [url, source_path] subprocess.run(cmdline, check=True) with open("./target/sources.tag", "wt+") as file: file.write(source_path)