gboolean zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force) { try { zypp::ZYpp::Ptr zypp = get_zypp (); if (force) zypp->resolver ()->setForceResolve (force); if (type == UPDATE) { //zypp->resolver ()->setOnlyRequires (TRUE); zypp->resolver ()->setIgnoreAlreadyRecommended (TRUE); } // Gather up any dependencies pk_backend_set_status (backend, PK_STATUS_ENUM_DEP_RESOLVE); if (zypp->resolver ()->resolvePool () == FALSE) { // Manual intervention required to resolve dependencies // TODO: Figure out what we need to do with PackageKit // to pull off interactive problem solving. zypp::ResolverProblemList problems = zypp->resolver ()->problems (); gchar * emsg = NULL, * tempmsg = NULL; for (zypp::ResolverProblemList::iterator it = problems.begin (); it != problems.end (); it++){ if (emsg == NULL) { emsg = g_strdup ((*it)->description ().c_str ()); } else { tempmsg = emsg; emsg = g_strconcat (emsg, "\n", (*it)->description ().c_str (), NULL); g_free (tempmsg); } } // reset the status of all touched PoolItems zypp::ResPool pool = zypp::ResPool::instance (); for (zypp::ResPool::const_iterator it = pool.begin (); it != pool.end (); it++) { if (it->status ().isToBeInstalled ()) it->statusReset (); } pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, emsg); g_free (emsg); zypp->resolver ()->setForceResolve (FALSE); return FALSE; } switch (type) { case INSTALL: pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL); break; case REMOVE: pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE); break; case UPDATE: pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE); break; }; // look for licenses to confirm zypp::ResPool pool = zypp::ResPool::instance (); for (zypp::ResPool::const_iterator it = pool.begin (); it != pool.end (); it++) { if (it->status ().isToBeInstalled () && !(it->satSolvable ().lookupStrAttribute (zypp::sat::SolvAttr::eula).empty ())) { gchar *eula_id = g_strdup ((*it)->name ().c_str ()); gboolean has_eula = pk_backend_is_eula_valid (backend, eula_id); if (!has_eula) { gchar *package_id = zypp_build_package_id_from_resolvable (it->satSolvable ()); pk_backend_eula_required (backend, eula_id, package_id, (*it)->vendor ().c_str (), it->satSolvable ().lookupStrAttribute (zypp::sat::SolvAttr::eula).c_str ()); pk_backend_error_code (backend, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT, "You've to agree/decline a license"); g_free (package_id); g_free (eula_id); return FALSE; } g_free (eula_id); } } // Perform the installation zypp::ZYppCommitPolicy policy; policy.restrictToMedia (0); // 0 - install all packages regardless to media zypp::ZYppCommitResult result = zypp->commit (policy); if(!result._errors.empty () || !result._remaining.empty () || !result._srcremaining.empty ()){ zypp::ZYppCommitResult::PoolItemList errors = result._errors; gchar *emsg = NULL, *tmpmsg = NULL; for (zypp::ZYppCommitResult::PoolItemList::iterator it = errors.begin (); it != errors.end (); it++){ if (emsg == NULL) { emsg = g_strdup ((*it)->name ().c_str ()); }else{ tmpmsg = emsg; emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL); g_free (tmpmsg); } } zypp::ZYppCommitResult::PoolItemList remaining = result._remaining; for (zypp::ZYppCommitResult::PoolItemList::iterator it = remaining.begin (); it != remaining.end (); it++){ if (emsg == NULL) { emsg = g_strdup ((*it)->name ().c_str ()); }else{ tmpmsg = emsg; emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL); g_free (tmpmsg); } } zypp::ZYppCommitResult::PoolItemList srcremaining = result._srcremaining; for (zypp::ZYppCommitResult::PoolItemList::iterator it = srcremaining.begin (); it != srcremaining.end (); it++){ if (emsg == NULL) { emsg = g_strdup ((*it)->name ().c_str ()); }else{ tmpmsg = emsg; emsg = g_strconcat (emsg, "\n", (*it)->name ().c_str (), NULL); g_free (tmpmsg); } } pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, "Transaction could not be completed.\n Theses packages could not be installed: %s", emsg); g_free (emsg); zypp->resolver ()->setForceResolve (FALSE); return FALSE; } zypp->resolver ()->setForceResolve (FALSE); if (type == UPDATE) { zypp->resolver ()->setIgnoreAlreadyRecommended (FALSE); } } catch (const zypp::repo::RepoNotFoundException &ex) { pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_FOUND, ex.asUserString().c_str() ); return FALSE; } catch (const zypp::target::rpm::RpmException &ex) { pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED, ex.asUserString().c_str () ); return FALSE; } catch (const zypp::Exception &ex) { pk_backend_error_code (backend, PK_ERROR_ENUM_INTERNAL_ERROR, ex.asUserString().c_str() ); return FALSE; } return TRUE; }
/** * pk_backend_spawn_parse_stdout: **/ static gboolean pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line, GError **error) { gchar **sections; guint size; gchar *command; gchar *text; gboolean ret = TRUE; guint64 speed; PkInfoEnum info; PkRestartEnum restart; PkGroupEnum group; gulong package_size; gint percentage; PkErrorEnum error_enum; PkStatusEnum status_enum; PkMessageEnum message_enum; PkRestartEnum restart_enum; PkSigTypeEnum sig_type; PkUpdateStateEnum update_state_enum; PkMediaTypeEnum media_type_enum; PkDistroUpgradeEnum distro_upgrade_enum; PkBackendSpawnPrivate *priv = backend_spawn->priv; g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); /* check if output line */ if (line == NULL) return FALSE; /* split by tab */ sections = g_strsplit (line, "\t", 0); command = sections[0]; /* get size */ size = g_strv_length (sections); if (g_strcmp0 (command, "package") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (pk_package_id_check (sections[2]) == FALSE) { g_set_error_literal (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } info = pk_info_enum_from_string (sections[1]); if (info == PK_INFO_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Info enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_package (priv->backend, info, sections[2], sections[3]); } else if (g_strcmp0 (command, "details") == 0) { if (size != 7) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } group = pk_group_enum_from_string (sections[3]); /* ITS4: ignore, checked for overflow */ package_size = atol (sections[6]); if (package_size > 1073741824) { g_set_error_literal (error, 1, 0, "package size cannot be larger than one Gb"); ret = FALSE; goto out; } text = g_strdup (sections[4]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_details (priv->backend, sections[1], sections[2], group, text, sections[5], package_size); g_free (text); } else if (g_strcmp0 (command, "finished") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_finished (priv->backend); /* from this point on, we can start the kill timer */ pk_backend_spawn_start_kill_timer (backend_spawn); } else if (g_strcmp0 (command, "files") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_files (priv->backend, sections[1], sections[2]); } else if (g_strcmp0 (command, "repo-detail") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[3], "true") == 0) { pk_backend_repo_detail (priv->backend, sections[1], sections[2], TRUE); } else if (g_strcmp0 (sections[3], "false") == 0) { pk_backend_repo_detail (priv->backend, sections[1], sections[2], FALSE); } else { g_set_error (error, 1, 0, "invalid qualifier '%s'", sections[3]); ret = FALSE; goto out; } } else if (g_strcmp0 (command, "updatedetail") == 0) { if (size != 13) { g_set_error (error, 1, 0, "invalid command '%s', size %i", command, size); ret = FALSE; goto out; } restart = pk_restart_enum_from_string (sections[7]); if (restart == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[7]); ret = FALSE; goto out; } update_state_enum = pk_update_state_enum_from_string (sections[10]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (sections[8], ";", '\n'); g_strdelimit (sections[9], ";", '\n'); pk_backend_update_detail (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], restart, sections[8], sections[9], update_state_enum, sections[11], sections[12]); } else if (g_strcmp0 (command, "percentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtoint (sections[1], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid percentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid percentage value %i", percentage); ret = FALSE; } else { pk_backend_set_percentage (priv->backend, percentage); } } else if (g_strcmp0 (command, "subpercentage") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtoint (sections[1], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid subpercentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid subpercentage value %i", percentage); ret = FALSE; } else { pk_backend_set_sub_percentage (priv->backend, percentage); } } else if (g_strcmp0 (command, "item-percentage") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (!pk_package_id_check (sections[1])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } ret = pk_strtoint (sections[2], &percentage); if (!ret) { g_set_error (error, 1, 0, "invalid item-percentage value %s", sections[1]); ret = FALSE; } else if (percentage < 0 || percentage > 100) { g_set_error (error, 1, 0, "invalid item-percentage value %i", percentage); ret = FALSE; } else { pk_backend_set_item_progress (priv->backend, sections[1], percentage); } } else if (g_strcmp0 (command, "error") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } error_enum = pk_error_enum_from_string (sections[1]); if (error_enum == PK_ERROR_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Error enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } /* convert back all the ;'s to newlines */ text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); /* convert % else we try to format them */ g_strdelimit (text, "%", '$'); pk_backend_error_code (priv->backend, error_enum, text); g_free (text); } else if (g_strcmp0 (command, "requirerestart") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } restart_enum = pk_restart_enum_from_string (sections[1]); if (restart_enum == PK_RESTART_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Restart enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (!pk_package_id_check (sections[2])) { g_set_error (error, 1, 0, "invalid package_id"); ret = FALSE; goto out; } pk_backend_require_restart (priv->backend, restart_enum, sections[2]); } else if (g_strcmp0 (command, "message") == 0) { if (size != 3) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } message_enum = pk_message_enum_from_string (sections[1]); if (message_enum == PK_MESSAGE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Message enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } text = g_strdup (sections[2]); /* convert ; to \n as we can't emit them on stdout */ g_strdelimit (text, ";", '\n'); pk_backend_message (priv->backend, message_enum, text); g_free (text); } else if (g_strcmp0 (command, "change-transaction-data") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_set_transaction_data (priv->backend, sections[1]); } else if (g_strcmp0 (command, "status") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } status_enum = pk_status_enum_from_string (sections[1]); if (status_enum == PK_STATUS_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Status enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_set_status (priv->backend, status_enum); } else if (g_strcmp0 (command, "speed") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } ret = pk_strtouint64 (sections[1], &speed); if (!ret) { g_set_error (error, 1, 0, "failed to parse speed: '%s'", sections[1]); ret = FALSE; goto out; } pk_backend_set_speed (priv->backend, speed); } else if (g_strcmp0 (command, "allow-cancel") == 0) { if (size != 2) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[1], "true") == 0) { pk_backend_set_allow_cancel (priv->backend, TRUE); } else if (g_strcmp0 (sections[1], "false") == 0) { pk_backend_set_allow_cancel (priv->backend, FALSE); } else { g_set_error (error, 1, 0, "invalid section '%s'", sections[1]); ret = FALSE; goto out; } } else if (g_strcmp0 (command, "no-percentage-updates") == 0) { if (size != 1) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } pk_backend_set_percentage (priv->backend, PK_BACKEND_PERCENTAGE_INVALID); } else if (g_strcmp0 (command, "repo-signature-required") == 0) { if (size != 9) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } sig_type = pk_sig_type_enum_from_string (sections[8]); if (sig_type == PK_SIGTYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "Sig enum not recognised, and hence ignored: '%s'", sections[8]); ret = FALSE; goto out; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "repository name blank, and hence ignored: '%s'", sections[2]); ret = FALSE; goto out; } /* pass _all_ of the data */ ret = pk_backend_repo_signature_required (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5], sections[6], sections[7], sig_type); goto out; } else if (g_strcmp0 (command, "eula-required") == 0) { if (size != 5) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (pk_strzero (sections[1])) { g_set_error (error, 1, 0, "eula_id blank, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error (error, 1, 0, "package_id blank, and hence ignored: '%s'", sections[2]); ret = FALSE; goto out; } if (pk_strzero (sections[4])) { g_set_error (error, 1, 0, "agreement name blank, and hence ignored: '%s'", sections[4]); ret = FALSE; goto out; } ret = pk_backend_eula_required (priv->backend, sections[1], sections[2], sections[3], sections[4]); goto out; } else if (g_strcmp0 (command, "media-change-required") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } media_type_enum = pk_media_type_enum_from_string (sections[1]); if (media_type_enum == PK_MEDIA_TYPE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "media type enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } ret = pk_backend_media_change_required (priv->backend, media_type_enum, sections[2], sections[3]); goto out; } else if (g_strcmp0 (command, "distro-upgrade") == 0) { if (size != 4) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } distro_upgrade_enum = pk_distro_upgrade_enum_from_string (sections[1]); if (distro_upgrade_enum == PK_DISTRO_UPGRADE_ENUM_UNKNOWN) { g_set_error (error, 1, 0, "distro upgrade enum not recognised, and hence ignored: '%s'", sections[1]); ret = FALSE; goto out; } ret = pk_backend_distro_upgrade (priv->backend, distro_upgrade_enum, sections[2], sections[3]); goto out; } else if (g_strcmp0 (command, "category") == 0) { if (size != 6) { g_set_error (error, 1, 0, "invalid command'%s', size %i", command, size); ret = FALSE; goto out; } if (g_strcmp0 (sections[1], sections[2]) == 0) { g_set_error_literal (error, 1, 0, "cat_id cannot be the same as parent_id"); ret = FALSE; goto out; } if (pk_strzero (sections[2])) { g_set_error_literal (error, 1, 0, "cat_id cannot not blank"); ret = FALSE; goto out; } if (pk_strzero (sections[3])) { g_set_error_literal (error, 1, 0, "name cannot not blank"); ret = FALSE; goto out; } if (pk_strzero (sections[5])) { g_set_error_literal (error, 1, 0, "icon cannot not blank"); ret = FALSE; goto out; } if (g_str_has_prefix (sections[5], "/")) { g_set_error (error, 1, 0, "icon '%s' should be a named icon, not a path", sections[5]); ret = FALSE; goto out; } ret = pk_backend_category (priv->backend, sections[1], sections[2], sections[3], sections[4], sections[5]); goto out; } else { ret = FALSE; g_set_error (error, 1, 0, "invalid command '%s'", command); } out: g_strfreev (sections); return ret; }