fix(gui): show the real reason an Environment Apply/Install failed — 0.10.2
Thread the command output through to the status line and classify it: cancelled at the password prompt vs. the system rejecting the change (e.g. a BIOS/kernel- locked PCIe ASPM policy), instead of a vague "cancelled, or needs privileges". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,12 @@ All notable changes to RigDoctor are recorded here. Format follows
|
|||||||
(`MAJOR.MINOR.PATCH`, pre-1.0). `__version__` and `pyproject.toml` must match the git
|
(`MAJOR.MINOR.PATCH`, pre-1.0). `__version__` and `pyproject.toml` must match the git
|
||||||
release tag (so the auto-updater, D18, can compare versions).
|
release tag (so the auto-updater, D18, can compare versions).
|
||||||
|
|
||||||
|
## [0.10.2] - 2026-05-22
|
||||||
|
### Changed
|
||||||
|
- When an Environment **Apply**/**Install** fails, the status now shows the **real reason**
|
||||||
|
(cancelled at the password prompt vs. the system rejecting the change, e.g. a BIOS/kernel-
|
||||||
|
locked PCIe ASPM policy) instead of a vague "cancelled, or needs privileges".
|
||||||
|
|
||||||
## [0.10.1] - 2026-05-22
|
## [0.10.1] - 2026-05-22
|
||||||
### Fixed
|
### Fixed
|
||||||
- **Environment-page contrast.** The combo-box **drop-down list** was rendering light-on-light
|
- **Environment-page contrast.** The combo-box **drop-down list** was rendering light-on-light
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "rigdoctor"
|
name = "rigdoctor"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
description = "Modular hardware monitoring & crash diagnostics for Linux gamers."
|
description = "Modular hardware monitoring & crash diagnostics for Linux gamers."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""RigDoctor — modular hardware monitoring & crash diagnostics for Linux gamers."""
|
"""RigDoctor — modular hardware monitoring & crash diagnostics for Linux gamers."""
|
||||||
|
|
||||||
__version__ = "0.10.1"
|
__version__ = "0.10.2"
|
||||||
|
|||||||
@@ -19,9 +19,20 @@ from PySide6.QtWidgets import (
|
|||||||
from .widgets import finding_card
|
from .widgets import finding_card
|
||||||
|
|
||||||
|
|
||||||
|
def _fail_reason(out: str) -> str:
|
||||||
|
"""Turn the failed command's output into a short, human reason."""
|
||||||
|
low = (out or "").lower()
|
||||||
|
if "not authorized" in low or "dismissed" in low or "authentication" in low:
|
||||||
|
return "cancelled at the password prompt"
|
||||||
|
if "operation not permitted" in low or "invalid argument" in low or "permission denied" in low:
|
||||||
|
return "the system rejected the change (it may be locked by BIOS/kernel)"
|
||||||
|
last = next((ln.strip() for ln in reversed((out or "").splitlines()) if ln.strip()), "")
|
||||||
|
return (last[:80] or "no privileges, or cancelled")
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentPage(QWidget):
|
class EnvironmentPage(QWidget):
|
||||||
_result = Signal(object) # list[Finding]
|
_result = Signal(object) # list[Finding]
|
||||||
_action_done = Signal(object) # (label, rc) — install or apply finished
|
_action_done = Signal(object) # (label, rc, output) — install or apply finished
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -117,8 +128,8 @@ class EnvironmentPage(QWidget):
|
|||||||
def _work_install(self, component) -> None:
|
def _work_install(self, component) -> None:
|
||||||
from ..core import installer
|
from ..core import installer
|
||||||
|
|
||||||
rc, _out = installer.install_packages(list(component.apt))
|
rc, out = installer.install_packages(list(component.apt))
|
||||||
self._action_done.emit((component.name, rc))
|
self._action_done.emit((component.name, rc, out))
|
||||||
|
|
||||||
def _apply(self, fix_id: str, value: str) -> None:
|
def _apply(self, fix_id: str, value: str) -> None:
|
||||||
if self._busy:
|
if self._busy:
|
||||||
@@ -131,15 +142,15 @@ class EnvironmentPage(QWidget):
|
|||||||
def _work_apply(self, fix_id: str, value: str) -> None:
|
def _work_apply(self, fix_id: str, value: str) -> None:
|
||||||
from ..core import fixes
|
from ..core import fixes
|
||||||
|
|
||||||
rc, _out = fixes.apply(fix_id, value)
|
rc, out = fixes.apply(fix_id, value)
|
||||||
self._action_done.emit((value, rc))
|
self._action_done.emit((value, rc, out))
|
||||||
|
|
||||||
def _on_action_done(self, result) -> None:
|
def _on_action_done(self, result) -> None:
|
||||||
label, rc = result
|
label, rc, out = result
|
||||||
self._busy = False
|
self._busy = False
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
self._status.setText(f"{label} applied — re-checking…")
|
self._status.setText(f"{label} applied — re-checking…")
|
||||||
self._run() # re-run so the finding reflects the new state
|
self._run() # re-run so the finding reflects the new state
|
||||||
else:
|
else:
|
||||||
self._run_btn.setEnabled(True)
|
self._run_btn.setEnabled(True)
|
||||||
self._status.setText(f"'{label}' failed (cancelled, or needs privileges)")
|
self._status.setText(f"'{label}' failed — {_fail_reason(out)}")
|
||||||
|
|||||||
Reference in New Issue
Block a user