test
This commit is contained in:
121
fetch_vendor.py
Normal file
121
fetch_vendor.py
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Скачивает портативный Firefox и geckodriver (Windows) в папку vendor/,
|
||||
чтобы build.py / build_wine.sh встроили их в .exe. Тогда конечному
|
||||
пользователю нужно установить только КриптоПро — Firefox и драйвер уже внутри.
|
||||
|
||||
Запуск (на машине сборки, можно на Linux):
|
||||
python fetch_vendor.py # win64 (по умолчанию)
|
||||
python fetch_vendor.py --arch win32
|
||||
python fetch_vendor.py --lang en-US
|
||||
|
||||
Для распаковки Firefox нужен 7-Zip:
|
||||
Linux: sudo apt install p7zip-full
|
||||
Windows: установите 7-Zip и добавьте 7z в PATH
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.request
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent
|
||||
VENDOR = ROOT / "vendor"
|
||||
GECKO_API = "https://api.github.com/repos/mozilla/geckodriver/releases/latest"
|
||||
|
||||
|
||||
def _download(url: str) -> bytes:
|
||||
print(f" ↓ {url}")
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "fetch-vendor"})
|
||||
with urllib.request.urlopen(req, timeout=120) as resp:
|
||||
return resp.read()
|
||||
|
||||
|
||||
def _which_7z() -> str | None:
|
||||
for name in ("7z", "7za", "7zr"):
|
||||
if shutil.which(name):
|
||||
return name
|
||||
return None
|
||||
|
||||
|
||||
def fetch_geckodriver(arch: str) -> None:
|
||||
print("geckodriver:")
|
||||
data = json.loads(_download(GECKO_API).decode("utf-8"))
|
||||
asset = next(
|
||||
(a for a in data["assets"] if f"{arch}.zip" in a["name"] and a["name"].endswith(".zip")),
|
||||
None,
|
||||
)
|
||||
if not asset:
|
||||
names = [a["name"] for a in data["assets"]]
|
||||
sys.exit(f" Не найден ассет для {arch}. Доступно: {names}")
|
||||
|
||||
blob = _download(asset["browser_download_url"])
|
||||
with zipfile.ZipFile(io.BytesIO(blob)) as z:
|
||||
member = next(n for n in z.namelist() if n.endswith("geckodriver.exe"))
|
||||
VENDOR.mkdir(exist_ok=True)
|
||||
with z.open(member) as src, open(VENDOR / "geckodriver.exe", "wb") as dst:
|
||||
shutil.copyfileobj(src, dst)
|
||||
print(f" ✓ {VENDOR / 'geckodriver.exe'} ({data['tag_name']})")
|
||||
|
||||
|
||||
def fetch_firefox(arch: str, lang: str) -> None:
|
||||
print("Firefox (портативный):")
|
||||
sevenzip = _which_7z()
|
||||
if not sevenzip:
|
||||
print(
|
||||
" ✗ 7-Zip не найден — не могу распаковать установщик Firefox.\n"
|
||||
" Установите 7-Zip (Linux: sudo apt install p7zip-full), либо вручную\n"
|
||||
" распакуйте Firefox так, чтобы получилось vendor/firefox/firefox.exe"
|
||||
)
|
||||
return
|
||||
|
||||
os_param = "win64" if arch == "win64" else "win"
|
||||
url = f"https://download.mozilla.org/?product=firefox-latest&os={os_param}&lang={lang}"
|
||||
installer = VENDOR / "_firefox_setup.exe"
|
||||
VENDOR.mkdir(exist_ok=True)
|
||||
installer.write_bytes(_download(url))
|
||||
|
||||
extract_dir = VENDOR / "_ff_extract"
|
||||
if extract_dir.exists():
|
||||
shutil.rmtree(extract_dir)
|
||||
# Установщик Firefox — это 7-Zip SFX; внутри папка core/ с firefox.exe.
|
||||
subprocess.run(
|
||||
[sevenzip, "x", "-y", f"-o{extract_dir}", str(installer)],
|
||||
check=True, stdout=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
core = extract_dir / "core"
|
||||
if not (core / "firefox.exe").exists():
|
||||
sys.exit(f" В установщике не найден core/firefox.exe (распаковано в {extract_dir})")
|
||||
|
||||
target = VENDOR / "firefox"
|
||||
if target.exists():
|
||||
shutil.rmtree(target)
|
||||
shutil.move(str(core), str(target))
|
||||
|
||||
installer.unlink(missing_ok=True)
|
||||
shutil.rmtree(extract_dir, ignore_errors=True)
|
||||
print(f" ✓ {target / 'firefox.exe'}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--arch", choices=("win64", "win32"), default="win64")
|
||||
ap.add_argument("--lang", default="ru")
|
||||
args = ap.parse_args()
|
||||
|
||||
print(f"Папка: {VENDOR} (arch={args.arch}, lang={args.lang})\n")
|
||||
fetch_geckodriver(args.arch)
|
||||
print()
|
||||
fetch_firefox(args.arch, args.lang)
|
||||
print("\nГотово. Теперь соберите: python build.py")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user