Author: jkupec
Date: Sat Apr 26 16:17:51 2008
New Revision: 9834
URL: http://svn.opensuse.org/viewcvs/zypp?rev=9834&view=rev
Log:
- add 'p' option to the Continue? prompt to restart the solver with
force-resolution = false. The option will be shown only if there
are any packages to remove when install command was used with
force-resolution == true
- todo: for both remove and install - check what was requested and what
was added/removed by the solver. Show 'p' only if some packages were
added/removed by the solver.
- no-recommends always true for 'remove'
Modified:
trunk/zypper/src/zypper-misc.cc
trunk/zypper/src/zypper.h
Modified: trunk/zypper/src/zypper-misc.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/zypper/src/zypper-misc.cc?rev=9834&r1=9833&r2=9834&view=diff
==============================================================================
--- trunk/zypper/src/zypper-misc.cc (original)
+++ trunk/zypper/src/zypper-misc.cc Sat Apr 26 16:17:51 2008
@@ -1,9 +1,8 @@
+#include <iostream>
#include <fstream>
#include <sstream>
#include
#include
-#include
-#include
#include "zypp/ZYppFactory.h"
#include "zypp/base/Logger.h"
@@ -1120,15 +1119,24 @@
}
}
+enum
+{
+ SUMMARY_OK = 0,
+ SUMMARY_NOTHING_TO_DO,
+ SUMMARY_INSTALL_DOES_REMOVE,
+ SUMMARY_REMOVE_DOES_INSTALL
+};
+
/**
- * @return (-1) - nothing to do,
- * 0 - there is at least 1 resolvable to be installed/uninstalled,
+ * sets zypper exit code to:
* ZYPPER_EXIT_INF_REBOOT_NEEDED - if one of patches to be installed needs machine reboot,
* ZYPPER_EXIT_INF_RESTART_NEEDED - if one of patches to be installed needs package manager restart
+ *
+ * @return SUMMARY_*
*/
static int summary(Zypper & zypper)
{
- int retv = -1; // nothing to do;
+ int retv = SUMMARY_NOTHING_TO_DO;
MIL << "Pool contains " << God->pool().size() << " items." << std::endl;
DBG << "Install summary:" << endl;
@@ -1143,19 +1151,17 @@
ResObject::constPtr res = it->resolvable();
if ( it->status().isToBeInstalled() || it->status().isToBeUninstalled() )
{
- if (retv == -1) retv = 0;
-
if (it->resolvable()->kind() == ResTraits<Patch>::kind)
{
Patch::constPtr patch = asKind<Patch>(it->resolvable());
// set return value to 'reboot needed'
if (patch->reboot_needed())
- retv = ZYPPER_EXIT_INF_REBOOT_NEEDED;
+ zypper.setExitCode(ZYPPER_EXIT_INF_REBOOT_NEEDED);
// set return value to 'restart needed' (restart of package manager)
// however, 'reboot needed' takes precedence
- else if (retv != ZYPPER_EXIT_INF_REBOOT_NEEDED && patch->affects_pkg_manager())
- retv = ZYPPER_EXIT_INF_RESTART_NEEDED;
+ else if (zypper.exitCode() != ZYPPER_EXIT_INF_REBOOT_NEEDED && patch->affects_pkg_manager())
+ zypper.setExitCode(ZYPPER_EXIT_INF_RESTART_NEEDED);
}
if ( it->status().isToBeInstalled()
@@ -1174,7 +1180,10 @@
}
}
- if (retv == -1 && zypper.runtimeData().srcpkgs_to_install.empty())
+ if (!to_be_removed.empty() || !to_be_installed.empty())
+ retv = SUMMARY_OK;
+
+ if (retv == SUMMARY_NOTHING_TO_DO && zypper.runtimeData().srcpkgs_to_install.empty())
{
if (zypper.command() == ZypperCommand::VERIFY)
zypper.out().info(_("Dependencies of all installed packages are satisfied."));
@@ -1254,11 +1263,19 @@
}
}
+ bool toremove_by_solver = false;
for (KindToResObjectSet::const_iterator it = to_be_removed.begin();
it != to_be_removed.end(); ++it)
for (setResObject::constPtr::const_iterator resit = it->second.begin();
resit != it->second.end(); ++resit)
{
+ /** \todo this does not work
+ if (!toremove_by_solver)
+ {
+ PoolItem pi(*resit);
+ if (pi.status() == ResStatus::SOLVER)
+ toremove_by_solver = true;
+ }*/
toremove[it->first].insert(*resit);
new_installed_size -= (*resit)->installsize();
}
@@ -1267,6 +1284,14 @@
it != zypper.runtimeData().srcpkgs_to_install.end(); ++it)
toinstall[ResTraits<SrcPackage>::kind].insert(*it);
+ if (!toremove.empty() && (
+ zypper.command() == ZypperCommand::INSTALL ||
+ zypper.command() == ZypperCommand::UPDATE))
+ retv = SUMMARY_INSTALL_DOES_REMOVE;
+ else if ((!toinstall.empty() || toremove_by_solver)
+ && zypper.command() == ZypperCommand::REMOVE)
+ retv = SUMMARY_REMOVE_DOES_INSTALL;
+
// "</install-summary>"
if (zypper.out().type() == Out::TYPE_XML)
{
@@ -1387,7 +1412,7 @@
static void set_force_resolution(Zypper & zypper)
{
// --force-resolution command line parameter value
- tribool force_resolution = indeterminate;
+ TriBool force_resolution = zypper.runtimeData().force_resolution;
if (zypper.cOpts().count("force-resolution"))
force_resolution = true;
@@ -1417,6 +1442,9 @@
force_resolution = false;
}
+ // save the setting
+ zypper.runtimeData().force_resolution = force_resolution;
+
DBG << "force resolution: " << force_resolution << endl;
ostringstream s;
s << _("Force resolution:") << " " << (force_resolution ? _("Yes") : _("No"));
@@ -1435,8 +1463,12 @@
apply_locks(zypper);
dump_pool(); // debug
set_force_resolution(zypper);
- // install also recommended packages unless --no-recommends is specified
- God->resolver()->setOnlyRequires(zypper.cOpts().count("no-recommends"));
+ if (zypper.command() == ZypperCommand::REMOVE)
+ // never install recommends when removing packages
+ God->resolver()->setOnlyRequires(true);
+ else
+ // install also recommended packages unless --no-recommends is specified
+ God->resolver()->setOnlyRequires(zypper.cOpts().count("no-recommends"));
zypper.out().info(_("Resolving dependencies..."), Out::HIGH);
DBG << "Calling the solver..." << endl;
return God->resolver()->resolvePool();
@@ -2129,179 +2161,211 @@
return;
}
- MIL << "solving..." << endl;
-
- while (true) {
- bool success;
- if (zypper.command() == ZypperCommand::VERIFY)
- success = verify(zypper);
- else
- success = resolve(zypper);
- if (success)
- break;
-
- success = show_problems(zypper);
- if (! success) {
- // TODO cancel transaction?
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP); // #242736
- return;
- }
- }
-
-
- // returns -1, 0, ZYPPER_EXIT_INF_REBOOT_NEEDED, or ZYPPER_EXIT_INF_RESTART_NEEDED
- int retv = summary(zypper);
- bool was_installed = false;
- if (retv >= 0 || !zypper.runtimeData().srcpkgs_to_install.empty())
- {
- // check root user
- if (zypper.command() == ZypperCommand::VERIFY && geteuid() != 0)
- {
- zypper.out().error(
- _("Root privileges are required to fix broken package dependencies."));
- zypper.setExitCode(ZYPPER_EXIT_ERR_PRIVILEGES);
- return;
- }
-
- if (false)
+ bool show_forced_problems = true;
+ bool commit_done = false;
+ do
+ {
+ MIL << "solving..." << endl;
+
+ while (true)
{
- // translators: Translate 'p' to whathever you translated it in the y/n/p prompt text.
- string prompt_lablel = _("Continue? (Choose 'p' to show dependency problems.)");
- // translators: Yes / No / show Problems. This prompt will appear
- // after install/update command summary if there will be any package
- // to-be-removed automatically to show why, if asked.
- string prompt_with_p = _("y/n/p");
+ bool success;
+ if (zypper.command() == ZypperCommand::VERIFY)
+ success = verify(zypper);
+ else
+ success = resolve(zypper);
+ if (success)
+ break;
+
+ success = show_problems(zypper);
+ if (! success) {
+ // TODO cancel transaction?
+ zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP); // #242736
+ return;
+ }
}
+
+
+ // returns SUMMARY_*
+ int retv = summary(zypper);
+ if (retv != SUMMARY_NOTHING_TO_DO || !zypper.runtimeData().srcpkgs_to_install.empty())
+ {
+ // check root user
+ if (zypper.command() == ZypperCommand::VERIFY && geteuid() != 0)
+ {
+ zypper.out().error(
+ _("Root privileges are required to fix broken package dependencies."));
+ zypper.setExitCode(ZYPPER_EXIT_ERR_PRIVILEGES);
+ return;
+ }
+
+ bool do_commit = false;
+ if (zypper.runtimeData().force_resolution &&
+ (retv == SUMMARY_INSTALL_DOES_REMOVE || retv == SUMMARY_REMOVE_DOES_INSTALL))
+ {
+ PromptOptions popts;
+ // translators: Yes / No / show Problems. This prompt will appear
+ // after install/update command summary if there will be any package
+ // to-be-removed automatically to show why, if asked.
+ popts.setOptions(_("y/n/p"), 0);
+ // translators: Translate 'p' to whathever you translated it in the y/n/p prompt text.
+ string prompt_text = _("Continue? (Choose 'p' to show dependency problems.)");
+ zypper.out().prompt(PROMPT_YN_INST_REMOVE_CONTINUE, prompt_text, popts);
+ unsigned int reply =
+ get_prompt_reply(zypper, PROMPT_YN_INST_REMOVE_CONTINUE, popts);
+
+ if (reply == 2)
+ {
+ // one more solver solver run with force-resoltion off
+ zypper.runtimeData().force_resolution = false;
+ God->resolver()->undo();
+ continue;
+ }
+ else if (reply == 1)
+ show_forced_problems = false;
+ else
+ {
+ do_commit = true;
+ show_forced_problems = false;
+ }
+ }
+ // no dependency problems
+ else
+ {
+ do_commit = read_bool_answer(PROMPT_YN_INST_REMOVE_CONTINUE, _("Continue?"), true);
+ show_forced_problems = false;
+ }
- // there are resolvables to install/uninstall
- if (read_bool_answer(PROMPT_YN_INST_REMOVE_CONTINUE, _("Continue?"), true))
- {
- if (!confirm_licenses(zypper)) return;
- if (retv >= 0)
+ if (do_commit)
{
- try
+ if (!confirm_licenses(zypper))
+ return;
+
+ if (retv >= 0)
{
- gData.show_media_progress_hack = true;
-
- ostringstream s;
- s << _("committing"); MIL << "committing...";
-
- ZYppCommitResult result;
- if (copts.count("dry-run"))
+ try
{
- s << " " << _("(dry run)") << endl; MIL << "(dry run)";
+ gData.show_media_progress_hack = true;
+
+ ostringstream s;
+ s << _("committing"); MIL << "committing...";
+
+ ZYppCommitResult result;
+ if (copts.count("dry-run"))
+ {
+ s << " " << _("(dry run)") << endl; MIL << "(dry run)";
+ zypper.out().info(s.str(), Out::HIGH);
+
+ result = God->commit(ZYppCommitPolicy().dryRun(true));
+ }
+ else
+ {
+ zypper.out().info(s.str(), Out::HIGH);
+
+ result = God->commit(
+ ZYppCommitPolicy().syncPoolAfterCommit(zypper.runningShell()));
+
+ commit_done = true;
+ }
+
+
+ MIL << endl << "DONE" << endl;
+
+ gData.show_media_progress_hack = false;
+
+ if (!result._errors.empty())
+ retv = ZYPPER_EXIT_ERR_ZYPP;
+
+ s.clear(); s << result;
zypper.out().info(s.str(), Out::HIGH);
-
- result = God->commit(ZYppCommitPolicy().dryRun(true));
}
- else
- {
- zypper.out().info(s.str(), Out::HIGH);
-
- result = God->commit(
- ZYppCommitPolicy().syncPoolAfterCommit(zypper.runningShell()));
-
- was_installed = true;
+ catch ( const media::MediaException & e ) {
+ ZYPP_CAUGHT(e);
+ zypper.out().error(e,
+ _("Problem downloading the package file from the repository:"),
+ _("Please see the above error message for a hint."));
+ zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
+ return;
}
-
-
- MIL << endl << "DONE" << endl;
-
- gData.show_media_progress_hack = false;
-
- if (!result._errors.empty())
- retv = ZYPPER_EXIT_ERR_ZYPP;
+ catch ( zypp::repo::RepoException & e ) {
+ ZYPP_CAUGHT(e);
+
+ RepoManager manager(zypper.globalOpts().rm_options );
- s.clear(); s << result;
- zypper.out().info(s.str(), Out::HIGH);
- }
- catch ( const media::MediaException & e ) {
- ZYPP_CAUGHT(e);
- zypper.out().error(e,
- _("Problem downloading the package file from the repository:"),
- _("Please see the above error message for a hint."));
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
- return;
- }
- catch ( zypp::repo::RepoException & e ) {
- ZYPP_CAUGHT(e);
-
- RepoManager manager(zypper.globalOpts().rm_options );
-
- bool refresh_needed = false;
- for(RepoInfo::urls_const_iterator it = e.info().baseUrlsBegin();
- it != e.info().baseUrlsEnd(); ++it)
- {
- RepoManager::RefreshCheckStatus stat = manager.
- checkIfToRefreshMetadata(e.info(), *it,
- RepoManager::RefreshForced );
- if ( stat == RepoManager::REFRESH_NEEDED )
+ bool refresh_needed = false;
+ for(RepoInfo::urls_const_iterator it = e.info().baseUrlsBegin();
+ it != e.info().baseUrlsEnd(); ++it)
{
- refresh_needed = true;
- break;
+ RepoManager::RefreshCheckStatus stat = manager.
+ checkIfToRefreshMetadata(e.info(), *it,
+ RepoManager::RefreshForced );
+ if ( stat == RepoManager::REFRESH_NEEDED )
+ {
+ refresh_needed = true;
+ break;
+ }
}
+
+ std::string hint = _("Please see the above error message for a hint.");
+ if (refresh_needed)
+ {
+ hint = boost::str(format(
+ // translators: the first %s is 'zypper refresh' and the second
+ // is repo allias
+ _("Repository '%s' is out of date. Running '%s' might help.")) %
+ e.info().alias() % "zypper refresh" );
}
-
- std::string hint = _("Please see the above error message for a hint.");
- if (refresh_needed)
- {
- hint = boost::str(format(
- // translators: the first %s is 'zypper refresh' and the second
- // is repo allias
- _("Repository '%s' is out of date. Running '%s' might help.")) %
- e.info().alias() % "zypper refresh" );
+ zypper.out().error(e,
+ _("Problem downloading the package file from the repository:"),
+ hint);
+ zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
+ return;
+ }
+ catch ( const zypp::FileCheckException & e ) {
+ ZYPP_CAUGHT(e);
+ zypper.out().error(e,
+ _("The package integrity check failed. This may be a problem"
+ " with the repository or media. Try one of the following:\n"
+ "\n"
+ "- just retry previous command\n"
+ "- refresh the repositories using 'zypper refresh'\n"
+ "- use another installation medium (if e.g. damaged)\n"
+ "- use another repository"));
+ zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
+ return;
+ }
+ catch ( const Exception & e ) {
+ ZYPP_CAUGHT(e);
+ zypper.out().error(e,
+ _("Problem occured during or after installation or removal of packages:"),
+ _("Please see the above error message for a hint."));
+ zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
}
- zypper.out().error(e,
- _("Problem downloading the package file from the repository:"),
- hint);
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
- return;
- }
- catch ( const zypp::FileCheckException & e ) {
- ZYPP_CAUGHT(e);
- zypper.out().error(e,
- _("The package integrity check failed. This may be a problem"
- " with the repository or media. Try one of the following:\n"
- "\n"
- "- just retry previous command\n"
- "- refresh the repositories using 'zypper refresh'\n"
- "- use another installation medium (if e.g. damaged)\n"
- "- use another repository"));
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
- return;
- }
- catch ( const Exception & e ) {
- ZYPP_CAUGHT(e);
- zypper.out().error(e,
- _("Problem occured during or after installation or removal of packages:"),
- _("Please see the above error message for a hint."));
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
}
+ // install any pending source packages
+ if (!zypper.runtimeData().srcpkgs_to_install.empty())
+ install_src_pkgs(zypper);
}
- // install any pending source packages
- if (!zypper.runtimeData().srcpkgs_to_install.empty())
- install_src_pkgs(zypper);
}
+ // noting to do
+ else
+ break;
}
+ while (show_forced_problems);
- if (retv < 0)
- retv = ZYPPER_EXIT_OK;
- else if (was_installed)
+ if (commit_done)
{
- if (retv == ZYPPER_EXIT_INF_REBOOT_NEEDED)
+ if (zypper.exitCode() == ZYPPER_EXIT_INF_REBOOT_NEEDED)
zypper.out().warning(
_("One of installed patches requires reboot of"
- " your machine. Reboot as soon as possible."));
- else if (retv == ZYPPER_EXIT_INF_RESTART_NEEDED)
+ " your machine. Reboot as soon as possible."), Out::QUIET);
+ else if (zypper.exitCode() == ZYPPER_EXIT_INF_RESTART_NEEDED)
zypper.out().warning(
_("One of installed patches affects the package"
" manager itself, thus it requires its restart before executing"
" any further operations."),
- Out::NORMAL, Out::TYPE_NORMAL);
+ Out::QUIET, Out::TYPE_NORMAL); // don't show this to machines
}
-
- if (zypper.exitCode() == ZYPPER_EXIT_OK) // don't overwrite previously set exit code
- zypper.setExitCode(retv);
}
// TODO confirm licenses
Modified: trunk/zypper/src/zypper.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/zypper/src/zypper.h?rev=9834&r1=9833&r2=9834&view=diff
==============================================================================
--- trunk/zypper/src/zypper.h (original)
+++ trunk/zypper/src/zypper.h Sat Apr 26 16:17:51 2008
@@ -7,9 +7,10 @@
#include "zypp/base/Exception.h"
#include "zypp/base/NonCopyable.h"
#include "zypp/base/PtrTypes.h"
+#include "zypp/TriBool.h"
#include "zypp/RepoInfo.h"
-#include "zypp/RepoManager.h"
+#include "zypp/RepoManager.h" // for RepoManagerOptions
#include "zypp/SrcPackage.h"
#include "output/Out.h"
@@ -81,7 +82,9 @@
struct RuntimeData
{
RuntimeData()
- : patches_count(0), security_patches_count(0), show_media_progress_hack(false)
+ : patches_count(0), security_patches_count(0)
+ , show_media_progress_hack(false)
+ , force_resolution(zypp::indeterminate)
{}
std::listzypp::RepoInfo repos;
@@ -104,6 +107,9 @@
// all the way up from the media back-end through fetcher and downloader
// into the RepoManager::refreshMetadata(), so that we get a combined percentage
std::string raw_refresh_progress_label;
+
+ /** Used to override the command line option */
+ zypp::TriBool force_resolution;
};
class Zypper : private zypp::base::NonCopyable
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org