This is not handled by similar code in the software spoke, because that code is never run for kickstart installs containing a %packages section. --- pyanaconda/errors.py | 11 ++++++++++- pyanaconda/packaging/yumpayload.py | 12 +++++++++++- pyanaconda/ui/gui/__init__.py | 11 +++++++++++ pyanaconda/ui/tui/__init__.py | 3 +++ 4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/errors.py b/pyanaconda/errors.py index 17e75a0..3ae9178 100644 --- a/pyanaconda/errors.py +++ b/pyanaconda/errors.py @@ -227,6 +227,14 @@ class ErrorHandler(object): self.ui.showError(message) return ERROR_RAISE
+ def _dependencyErrorHandler(self, *args, **kwargs): + message = _("The following software marked for installation has errors. " + "This is likely caused by an error with\nyour installation source.") + details = "\n".join(sorted(kwargs["exception"].message)) + + self.ui.showDetailedError(message, details) + return ERROR_RAISE + def cb(self, exn, *args, **kwargs): """This method is the callback that all error handling should pass through. The return value is one of the ERROR_* constants defined @@ -259,7 +267,8 @@ class ErrorHandler(object): "NoSuchGroup": self._noSuchGroupHandler, "NoSuchPackage": self._noSuchPackageHandler, "ScriptError": self._scriptErrorHandler, - "PayloadInstallError": self._payloadInstallHandler} + "PayloadInstallError": self._payloadInstallHandler, + "DependencyError": self._dependencyErrorHandler}
if exn.__class__.__name__ in _map: kwargs["exception"] = exn diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py index 3ce12f7..13c1ba6 100644 --- a/pyanaconda/packaging/yumpayload.py +++ b/pyanaconda/packaging/yumpayload.py @@ -1234,7 +1234,17 @@ reposdir=%s self._setUpMedia(self.install_device)
self._writeInstallConfig() - self.checkSoftwareSelection() + + # We have this block twice. For kickstart installs, this is the only + # place dependencies will be checked. If a dependency error is hit + # here, there's nothing the user can do about it since you cannot go + # back to the first hub. + try: + self.checkSoftwareSelection() + except DependencyError as e: + if errorHandler.cb(e) == ERROR_RAISE: + progress.send_quit(1) + sys.exit(1)
# doPreInstall # create mountpoints for protected device mountpoints (?) diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index 9e15abb..11d39b3 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -136,6 +136,17 @@ class GraphicalUserInterface(UserInterface): dlg.destroy()
@gtk_thread_wait + def showDetailedError(self, message, details): + from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog + dlg = DetailedErrorDialog(None, buttons=[_("_Quit")], + label=message) + + with enlightbox(self._actions[0].window, dlg.window): + dlg.refresh(details) + rc = dlg.run() + dlg.window.destroy() + + @gtk_thread_wait def showYesNoQuestion(self, message): from gi.repository import AnacondaWidgets, Gtk dlg = Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL, diff --git a/pyanaconda/ui/tui/__init__.py b/pyanaconda/ui/tui/__init__.py index b20dc17..c4a15a0 100644 --- a/pyanaconda/ui/tui/__init__.py +++ b/pyanaconda/ui/tui/__init__.py @@ -173,6 +173,9 @@ class TextUserInterface(ui.UserInterface): error_window = ErrorDialog(self._app, message) self._app.switch_screen(error_window)
+ def showDetailedError(self, message, details): + self.showError(message + "\n\n" + details) + def showYesNoQuestion(self, message): """Display a dialog with the given message that presents the user a yes or no choice. This method returns True if the yes choice is selected,