fix installer
This commit is contained in:
@@ -22,7 +22,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pwd
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -30,6 +30,11 @@ import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
try:
|
||||
import pwd
|
||||
except ImportError:
|
||||
pwd = None
|
||||
|
||||
|
||||
def get_python_in_venv(venv_dir: Path) -> Optional[Path]:
|
||||
try:
|
||||
@@ -72,6 +77,7 @@ def find_requirements(root: Path) -> Optional[Path]:
|
||||
|
||||
def install_requirements(
|
||||
venv_py: Path,
|
||||
repo_root: Path,
|
||||
req_path: Path,
|
||||
reinstall: bool = False,
|
||||
upgrade: bool = False
|
||||
@@ -93,20 +99,13 @@ def install_requirements(
|
||||
check=True,
|
||||
**kwargs
|
||||
)
|
||||
install_cmd = [str(venv_py), "-m", "pip", "install", "-r", str(req_path)]
|
||||
python_version = get_python_version_info(venv_py)
|
||||
install_cmd = [str(venv_py), "-m", "pip", "install", "--prefer-binary"]
|
||||
if upgrade:
|
||||
install_cmd = [str(venv_py), "-m", "pip", "install", "--upgrade", "-r", str(req_path)]
|
||||
install_cmd.append("--upgrade")
|
||||
if reinstall:
|
||||
install_cmd = [
|
||||
str(venv_py),
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--upgrade",
|
||||
"--force-reinstall",
|
||||
"-r",
|
||||
str(req_path),
|
||||
]
|
||||
install_cmd.extend(["--upgrade", "--force-reinstall"])
|
||||
install_cmd.extend(build_hydrus_install_targets(req_path, repo_root, python_version))
|
||||
subprocess.run(install_cmd, check=True, **kwargs)
|
||||
return True
|
||||
except subprocess.CalledProcessError as e:
|
||||
@@ -140,6 +139,69 @@ def parse_requirements_file(req_path: Path) -> List[str]:
|
||||
return names
|
||||
|
||||
|
||||
def get_python_version_info(python_exe: Path) -> Optional[tuple[int, int, int]]:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[
|
||||
str(python_exe),
|
||||
"-c",
|
||||
"import sys; print('.'.join(str(part) for part in sys.version_info[:3]))",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
text=True,
|
||||
check=True,
|
||||
timeout=10,
|
||||
)
|
||||
version_text = (result.stdout or "").strip()
|
||||
major, minor, micro = version_text.split(".", 2)
|
||||
return int(major), int(minor), int(micro)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def is_hydrus_repo(repo_root: Path) -> bool:
|
||||
return (repo_root / "setup_venv.py").exists() and (repo_root / "hydrus_client.py").exists()
|
||||
|
||||
|
||||
def build_hydrus_install_targets(
|
||||
req_path: Path,
|
||||
repo_root: Path,
|
||||
python_version: Optional[tuple[int, int, int]],
|
||||
) -> List[str]:
|
||||
if python_version is None or python_version < (3, 13) or not is_hydrus_repo(repo_root):
|
||||
return ["-r", str(req_path)]
|
||||
|
||||
overrides = {
|
||||
"pyside6": "PySide6==6.10.1",
|
||||
"qtpy": "QtPy==2.4.3",
|
||||
"opencv-python-headless": "opencv-python-headless==4.13.0.90",
|
||||
"numpy": "numpy==2.4.1",
|
||||
}
|
||||
targets: List[str] = []
|
||||
seen_packages = set()
|
||||
|
||||
for raw_line in req_path.read_text(encoding="utf-8").splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
|
||||
package_name = re.split(r"[<>=!~\[]", line, maxsplit=1)[0].strip().lower()
|
||||
if package_name in overrides:
|
||||
line = overrides[package_name]
|
||||
|
||||
targets.append(line)
|
||||
seen_packages.add(package_name)
|
||||
|
||||
if os.name == "nt" and "pywin32" not in seen_packages:
|
||||
targets.append("pywin32")
|
||||
|
||||
print(
|
||||
f"Using Hydrus compatibility dependency set for Python {python_version[0]}.{python_version[1]}.{python_version[2]}"
|
||||
)
|
||||
return targets
|
||||
|
||||
|
||||
def verify_imports(venv_py: Path, packages: List[str]) -> bool:
|
||||
# Skip mpv check as it is problematic to install and causes slow startups
|
||||
packages = [p for p in packages if p.lower() != "mpv"]
|
||||
@@ -228,6 +290,8 @@ def is_first_run(repo_root: Path) -> bool:
|
||||
|
||||
|
||||
def _user_exists(username: str) -> bool:
|
||||
if pwd is None:
|
||||
return False
|
||||
try:
|
||||
pwd.getpwnam(username)
|
||||
return True
|
||||
@@ -914,7 +978,12 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
p.add_argument(
|
||||
"--pull",
|
||||
action="store_true",
|
||||
help="Run 'git pull' before starting the client",
|
||||
help="Force a repository update before starting the client (legacy alias; startup update is enabled by default)",
|
||||
)
|
||||
p.add_argument(
|
||||
"--no-update",
|
||||
action="store_true",
|
||||
help="Skip the default repository git pull before startup",
|
||||
)
|
||||
p.add_argument(
|
||||
"--update-deps",
|
||||
@@ -984,19 +1053,36 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
else:
|
||||
repo_root = workspace_root
|
||||
|
||||
# Handle git pull update if requested
|
||||
# Skip execution during service install/uninstall; it will run when the service starts
|
||||
if args.pull and not (args.install_service or args.uninstall_service):
|
||||
repo_updated = False
|
||||
should_pull_repo = not args.no_update and not (args.install_service or args.uninstall_service)
|
||||
if should_pull_repo:
|
||||
if shutil.which("git"):
|
||||
if (repo_root / ".git").exists():
|
||||
if not args.quiet:
|
||||
print(f"Updating repository via 'git pull' in {repo_root}...")
|
||||
print(f"Updating repository via 'git pull --ff-only' in {repo_root}...")
|
||||
try:
|
||||
# Use creationflags to hide the window on Windows
|
||||
k = {}
|
||||
if os.name == "nt":
|
||||
k["creationflags"] = 0x08000000
|
||||
subprocess.run(["git", "pull"], cwd=str(repo_root), check=False, **k)
|
||||
result = subprocess.run(
|
||||
["git", "pull", "--ff-only"],
|
||||
cwd=str(repo_root),
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
**k,
|
||||
)
|
||||
pull_output = "\n".join(
|
||||
part.strip()
|
||||
for part in [result.stdout or "", result.stderr or ""]
|
||||
if part.strip()
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f"Warning: git pull failed: {pull_output or result.returncode}")
|
||||
else:
|
||||
repo_updated = "already up to date" not in pull_output.lower()
|
||||
if pull_output and not args.quiet:
|
||||
print(pull_output)
|
||||
except Exception as e:
|
||||
print(f"Warning: git pull failed: {e}")
|
||||
else:
|
||||
@@ -1127,7 +1213,7 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not should_update and args.pull and not (args.install_service or args.uninstall_service):
|
||||
if not should_update and (args.pull or repo_updated) and not (args.install_service or args.uninstall_service):
|
||||
should_update = True
|
||||
|
||||
if args.install_deps or args.reinstall or should_update:
|
||||
@@ -1135,7 +1221,7 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
if not req:
|
||||
print("No requirements.txt found; skipping install")
|
||||
else:
|
||||
ok = install_requirements(venv_py, req, reinstall=args.reinstall, upgrade=should_update)
|
||||
ok = install_requirements(venv_py, repo_root, req, reinstall=args.reinstall, upgrade=should_update)
|
||||
if not ok:
|
||||
print("Dependency installation failed; aborting")
|
||||
return 4
|
||||
|
||||
Reference in New Issue
Block a user