Fix package detection using dpkg-query, add apt-get update before install, add libxcb-cursor0 dep
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
983857bd5b
commit
076ca348d7
2 changed files with 46 additions and 12 deletions
|
|
@ -147,10 +147,30 @@ def _parse_apt_packages(install_sh_content: str) -> set[str]:
|
||||||
|
|
||||||
|
|
||||||
async def _get_installed_packages(packages: set[str]) -> set[str]:
|
async def _get_installed_packages(packages: set[str]) -> set[str]:
|
||||||
"""Check which packages from the set are already installed via dpkg."""
|
"""Check which packages from the set are already installed via dpkg-query."""
|
||||||
if not packages:
|
if not packages:
|
||||||
return set()
|
return set()
|
||||||
installed = set()
|
installed = set()
|
||||||
|
# Use dpkg-query for batch check — more reliable than dpkg -s
|
||||||
|
# Note: dpkg-query returns non-zero if ANY package is unknown, but still
|
||||||
|
# outputs status for known packages on stdout.
|
||||||
|
try:
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"dpkg-query", "-W", "-f", "${Package} ${Status}\n", *sorted(packages),
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE,
|
||||||
|
env=_safe_env(),
|
||||||
|
)
|
||||||
|
stdout, _ = await asyncio.wait_for(proc.communicate(), timeout=10)
|
||||||
|
# returncode may be non-zero if some packages are unknown — that's fine
|
||||||
|
for line in stdout.decode().strip().splitlines():
|
||||||
|
# Format: "packagename install ok installed"
|
||||||
|
if "install ok installed" in line:
|
||||||
|
pkg_name = line.split()[0]
|
||||||
|
installed.add(pkg_name)
|
||||||
|
except (asyncio.TimeoutError, Exception) as e:
|
||||||
|
log.debug("dpkg-query failed, falling back to individual checks: %s", e)
|
||||||
|
# Fallback: check each package individually
|
||||||
for pkg in packages:
|
for pkg in packages:
|
||||||
proc = await asyncio.create_subprocess_exec(
|
proc = await asyncio.create_subprocess_exec(
|
||||||
"dpkg", "-s", pkg,
|
"dpkg", "-s", pkg,
|
||||||
|
|
@ -163,9 +183,8 @@ async def _get_installed_packages(packages: set[str]) -> set[str]:
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
continue
|
continue
|
||||||
if proc.returncode == 0:
|
if proc.returncode == 0:
|
||||||
# Verify it's actually installed (Status: install ok installed)
|
|
||||||
output = stdout.decode()
|
output = stdout.decode()
|
||||||
if "Status:" in output and "installed" in output:
|
if "install ok installed" in output:
|
||||||
installed.add(pkg)
|
installed.add(pkg)
|
||||||
return installed
|
return installed
|
||||||
|
|
||||||
|
|
@ -262,6 +281,20 @@ async def install_deps(req: InstallDepsRequest, _user: str = Depends(get_current
|
||||||
raise HTTPException(400, f"Invalid package name: {pkg}")
|
raise HTTPException(400, f"Invalid package name: {pkg}")
|
||||||
|
|
||||||
apt_bin = shutil.which("apt-get") or "/usr/bin/apt-get"
|
apt_bin = shutil.which("apt-get") or "/usr/bin/apt-get"
|
||||||
|
|
||||||
|
# Update package lists first
|
||||||
|
log.info("Running apt-get update before install")
|
||||||
|
update_proc = await asyncio.create_subprocess_exec(
|
||||||
|
apt_bin, "update", "-qq",
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE,
|
||||||
|
env=_safe_env(),
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(update_proc.communicate(), timeout=120)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
pass # Non-fatal, proceed with install anyway
|
||||||
|
|
||||||
cmd = [apt_bin, "install", "-y"] + req.packages
|
cmd = [apt_bin, "install", "-y"] + req.packages
|
||||||
log.info("Installing system packages: %s", " ".join(req.packages))
|
log.info("Installing system packages: %s", " ".join(req.packages))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ install_deps() {
|
||||||
xdotool \
|
xdotool \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
x11-utils \
|
x11-utils \
|
||||||
|
libxcb-cursor0 \
|
||||||
> /dev/null 2>&1
|
> /dev/null 2>&1
|
||||||
ok "System dependencies installed."
|
ok "System dependencies installed."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue